Example #1
0
static char *				/* I - Printer name or NULL */
cups_connect(const char *name,		/* I - Destination (printer[@host]) */
             char       *printer,	/* O - Printer name [HTTP_MAX_URI] */
             char       *hostname)	/* O - Hostname [HTTP_MAX_URI] */
{
    char	hostbuf[HTTP_MAX_URI],		/* Name of host */
            http_hostname[HTTP_MAX_HOST];	/* Hostname associated with connection */
    _cups_globals_t  *cg = _cupsGlobals();/* Pointer to library globals */


    DEBUG_printf(("cups_connect(\"%s\", %p, %p)\n", name, printer, hostname));

    if (name == NULL)
    {
        _cupsSetError(IPP_BAD_REQUEST, NULL);

        return (NULL);
    }

    /*
     * All jobs are now queued to cupsServer() to avoid hostname
     * resolution problems and to ensure that the user sees all
     * locally queued jobs locally.
     */

    strlcpy(hostbuf, cupsServer(), sizeof(hostbuf));

    httpGetHostname(cg->http, http_hostname, sizeof(http_hostname));

    if (hostname != NULL)
        strlcpy(hostname, hostbuf, HTTP_MAX_URI);
    else
        hostname = hostbuf;

    if (printer != NULL)
        strlcpy(printer, name, HTTP_MAX_URI);
    else
        printer = (char *)name;

    if (cg->http != NULL)
    {
        if (!strcasecmp(http_hostname, hostname))
            return (printer);

        httpClose(cg->http);
    }

    DEBUG_printf(("connecting to %s on port %d...\n", hostname, ippPort()));

    if ((cg->http = httpConnectEncrypt(hostname, ippPort(),
                                       cupsEncryption())) == NULL)
    {
        DEBUG_puts("Unable to connect to server!");

        _cupsSetError(IPP_SERVICE_UNAVAILABLE, strerror(errno));

        return (NULL);
    }
    else
        return (printer);
}
Example #2
0
static int				/* O - 1 on success, 0 on failure */
cups_get_printer_uri(
    http_t     *http,			/* I - HTTP connection */
    const char *name,			/* I - Name of printer or class */
    char       *host,			/* I - Hostname buffer */
    int        hostsize,		/* I - Size of hostname buffer */
    int        *port,			/* O - Port number */
    char       *resource,		/* I - Resource buffer */
    int        resourcesize,		/* I - Size of resource buffer */
    int        depth)			/* I - Depth of query */
{
    int		i;			/* Looping var */
    int		http_port;		/* Port number */
    http_t	*http2;			/* Alternate HTTP connection */
    ipp_t		*request,		/* IPP request */
                *response;		/* IPP response */
    ipp_attribute_t *attr;		/* Current attribute */
    char		uri[HTTP_MAX_URI],	/* printer-uri attribute */
                scheme[HTTP_MAX_URI],	/* Scheme name */
                username[HTTP_MAX_URI],	/* Username:password */
                classname[255],		/* Temporary class name */
                http_hostname[HTTP_MAX_HOST];
    /* Hostname associated with connection */
    static const char * const requested_attrs[] =
    {   /* Requested attributes */
        "printer-uri-supported",
        "printer-type",
        "member-uris"
    };


    DEBUG_printf(("cups_get_printer_uri(http=%p, name=\"%s\", host=%p, "
                  "hostsize=%d, resource=%p, resourcesize=%d, depth=%d)\n",
                  http, name ? name : "(null)", host, hostsize,
                  resource, resourcesize, depth));

    /*
     * 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, "Unable to create printer-uri!");

        *host     = '\0';
        *resource = '\0';

        return (0);
    }

    DEBUG_printf(("cups_get_printer_uri: printer-uri=\"%s\"\n", uri));

    /*
     * Get the hostname and port number we are connected to...
     */

    httpGetHostname(http, http_hostname, sizeof(http_hostname));

#ifdef AF_INET6
    if (http->hostaddr->addr.sa_family == AF_INET6)
        http_port = ntohs(http->hostaddr->ipv6.sin6_port);
    else
#endif /* AF_INET6 */
        if (http->hostaddr->addr.sa_family == AF_INET)
            http_port = ntohs(http->hostaddr->ipv4.sin_port);
        else
            http_port = ippPort();

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

    request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);

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

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

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

    if ((response = cupsDoRequest(http, request, "/")) != NULL)
    {
        if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL)
        {
            /*
             * Get the first actual printer name in the class...
             */

            for (i = 0; i < attr->num_values; i ++)
            {
                httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text,
                                scheme, sizeof(scheme), username, sizeof(username),
                                host, hostsize, port, resource, resourcesize);
                if (!strncmp(resource, "/printers/", 10))
                {
                    /*
                     * Found a printer!
                     */

                    ippDelete(response);

                    return (1);
                }
            }

            /*
             * No printers in this class - try recursively looking for a printer,
             * but not more than 3 levels deep...
             */

            if (depth < 3)
            {
                for (i = 0; i < attr->num_values; i ++)
                {
                    httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text,
                                    scheme, sizeof(scheme), username, sizeof(username),
                                    host, hostsize, port, resource, resourcesize);
                    if (!strncmp(resource, "/classes/", 9))
                    {
                        /*
                         * Found a class!  Connect to the right server...
                         */

                        if (!strcasecmp(http_hostname, host) && *port == http_port)
                            http2 = http;
                        else if ((http2 = httpConnectEncrypt(host, *port,
                                                             cupsEncryption())) == NULL)
                        {
                            DEBUG_puts("Unable to connect to server!");

                            continue;
                        }

                        /*
                        * Look up printers on that server...
                        */

                        strlcpy(classname, resource + 9, sizeof(classname));

                        cups_get_printer_uri(http2, classname, host, hostsize, port,
                                             resource, resourcesize, depth + 1);

                        /*
                        * Close the connection as needed...
                        */

                        if (http2 != http)
                            httpClose(http2);

                        if (*host)
                            return (1);
                    }
                }
            }
        }
        else if ((attr = ippFindAttribute(response, "printer-uri-supported",
                                          IPP_TAG_URI)) != NULL)
        {
            httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text,
                            scheme, sizeof(scheme), username, sizeof(username),
                            host, hostsize, port, resource, resourcesize);
            ippDelete(response);

            if (!strncmp(resource, "/classes/", 9))
            {
                _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found for class!"));

                *host     = '\0';
                *resource = '\0';

                return (0);
            }

            return (1);
        }

        ippDelete(response);
    }

    if (cupsLastError() != IPP_NOT_FOUND)
        _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found!"));

    *host     = '\0';
    *resource = '\0';

    return (0);
}
static void
cups_create_localizations(
    http_t       *http,			/* I - Connection to destination */
    cups_dinfo_t *dinfo)		/* I - Destination informations */
{
  http_t		*http2;		/* Connection for strings file */
  http_status_t		status;		/* Request status */
  ipp_attribute_t	*attr;		/* "printer-strings-uri" attribute */
  char			scheme[32],	/* URI scheme */
  			userpass[256],	/* Username/password info */
  			hostname[256],	/* Hostname */
  			resource[1024],	/* Resource */
  			http_hostname[256],
  					/* Hostname of connection */
			tempfile[1024];	/* Temporary filename */
  int			port;		/* Port number */
  http_encryption_t	encryption;	/* Encryption to use */
  cups_file_t		*temp;		/* Temporary file */


 /*
  * Create an empty message catalog...
  */

  dinfo->localizations = _cupsMessageNew(NULL);

 /*
  * See if there are any localizations...
  */

  if ((attr = ippFindAttribute(dinfo->attrs, "printer-strings-uri",
                               IPP_TAG_URI)) == NULL)
  {
   /*
    * Nope...
    */

    DEBUG_puts("4cups_create_localizations: No printer-strings-uri (uri) "
               "value.");
    return;				/* Nope */
  }

 /*
  * Pull apart the URI and determine whether we need to try a different
  * server...
  */

  if (httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[0].string.text,
                      scheme, sizeof(scheme), userpass, sizeof(userpass),
                      hostname, sizeof(hostname), &port, resource,
                      sizeof(resource)) < HTTP_URI_OK)
  {
    DEBUG_printf(("4cups_create_localizations: Bad printer-strings-uri value "
                  "\"%s\".", attr->values[0].string.text));
    return;
  }

  httpGetHostname(http, http_hostname, sizeof(http_hostname));

  if (!_cups_strcasecmp(http_hostname, hostname) &&
      port == _httpAddrPort(http->hostaddr))
  {
   /*
    * Use the same connection...
    */

    http2 = http;
  }
  else
  {
   /*
    * Connect to the alternate host...
    */

    if (!strcmp(scheme, "https"))
      encryption = HTTP_ENCRYPT_ALWAYS;
    else
      encryption = HTTP_ENCRYPT_IF_REQUESTED;

    if ((http2 = httpConnectEncrypt(hostname, port, encryption)) == NULL)
    {
      DEBUG_printf(("4cups_create_localizations: Unable to connect to "
                    "%s:%d: %s", hostname, port, cupsLastErrorString()));
      return;
    }
  }

 /*
  * Get a temporary file...
  */

  if ((temp = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
  {
    DEBUG_printf(("4cups_create_localizations: Unable to create temporary "
                  "file: %s", cupsLastErrorString()));
    if (http2 != http)
      httpClose(http2);
    return;
  }

  status = cupsGetFd(http2, resource, cupsFileNumber(temp));

  DEBUG_printf(("4cups_create_localizations: GET %s = %s", resource,
                httpStatus(status)));

  if (status == HTTP_OK)
  {
   /*
    * Got the file, read it...
    */

    char		buffer[8192],	/* Message buffer */
    			*id,		/* ID string */
    			*str;		/* Translated message */
    _cups_message_t	*m;		/* Current message */

    lseek(cupsFileNumber(temp), 0, SEEK_SET);

    while (cups_read_strings(temp, buffer, sizeof(buffer), &id, &str))
    {
      if ((m = malloc(sizeof(_cups_message_t))) == NULL)
        break;

      m->id  = strdup(id);
      m->str = strdup(str);

      if (m->id && m->str)
        cupsArrayAdd(dinfo->localizations, m);
      else
      {
        if (m->id)
          free(m->id);

        if (m->str)
          free(m->str);

        free(m);
        break;
      }
    }
  }

  DEBUG_printf(("4cups_create_localizations: %d messages loaded.",
                cupsArrayCount(dinfo->localizations)));

 /*
  * Cleanup...
  */

  unlink(tempfile);
  cupsFileClose(temp);

  if (http2 != http)
    httpClose(http2);
}
Example #4
0
static int				/* O - Zero on success, non-zero on failure */
lpd_queue(const char      *hostname,	/* I - Host to connect to */
          http_addrlist_t *addrlist,	/* I - List of host addresses */
          const char      *printer,	/* I - Printer/queue name */
	  int             print_fd,	/* I - File to print */
	  int             snmp_fd,	/* I - SNMP socket */
	  int             mode,		/* I - Print mode */
          const char      *user,	/* I - Requesting user */
	  const char      *title,	/* I - Job title */
	  int             copies,	/* I - Number of copies */
	  int             banner,	/* I - Print LPD banner? */
          int             format,	/* I - Format specifier */
          int             order,	/* I - Order of data/control files */
	  int             reserve,	/* I - Reserve ports? */
	  int             manual_copies,/* I - Do copies by hand... */
	  int             timeout,	/* I - Timeout... */
	  int             contimeout,	/* I - Connection timeout */
	  const char      *orighost)	/* I - job-originating-host-name */
{
  char			localhost[255];	/* Local host name */
  int			error;		/* Error number */
  struct stat		filestats;	/* File statistics */
  int			lport;		/* LPD connection local port */
  int			fd;		/* LPD socket */
  char			control[10240],	/* LPD control 'file' */
			*cptr;		/* Pointer into control file string */
  char			status;		/* Status byte from command */
  int			delay;		/* Delay for retries... */
  char			addrname[256];	/* Address name */
  http_addrlist_t	*addr;		/* Socket address */
  int			have_supplies;	/* Printer supports supply levels? */
  int			copy;		/* Copies written */
  time_t		start_time;	/* Time of first connect */
  size_t		nbytes;		/* Number of bytes written */
  off_t			tbytes;		/* Total bytes written */
  char			buffer[32768];	/* Output buffer */
#ifdef WIN32
  DWORD			tv;		/* Timeout in milliseconds */
#else
  struct timeval	tv;		/* Timeout in secs and usecs */
#endif /* WIN32 */


 /*
  * Remember when we started trying to connect to the printer...
  */

  start_time = time(NULL);

 /*
  * Loop forever trying to print the file...
  */

  while (!abort_job)
  {
   /*
    * First try to reserve a port for this connection...
    */

    fprintf(stderr, "DEBUG: Connecting to %s:%d for printer %s\n", hostname,
            httpAddrPort(&(addrlist->addr)), printer);
    _cupsLangPrintFilter(stderr, "INFO", _("Connecting to printer."));

    for (lport = reserve == RESERVE_RFC1179 ? 732 : 1024, addr = addrlist,
             delay = 5;;
         addr = addr->next)
    {
     /*
      * Stop if this job has been canceled...
      */

      if (abort_job)
        return (CUPS_BACKEND_FAILED);

     /*
      * Choose the next priviledged port...
      */

      if (!addr)
        addr = addrlist;

      lport --;

      if (lport < 721 && reserve == RESERVE_RFC1179)
	lport = 731;
      else if (lport < 1)
	lport = 1023;

#ifdef HAVE_GETEUID
      if (geteuid() || !reserve)
#else
      if (getuid() || !reserve)
#endif /* HAVE_GETEUID */
      {
       /*
	* Just create a regular socket...
	*/

	if ((fd = socket(addr->addr.addr.sa_family, SOCK_STREAM, 0)) < 0)
	{
	  perror("DEBUG: Unable to create socket");
	  sleep(1);

          continue;
	}

        lport = 0;
      }
      else
      {
       /*
	* We're running as root and want to comply with RFC 1179.  Reserve a
	* priviledged lport between 721 and 731...
	*/

	if ((fd = rresvport_af(&lport, addr->addr.addr.sa_family)) < 0)
	{
	  perror("DEBUG: Unable to reserve port");
	  sleep(1);

	  continue;
	}
      }

     /*
      * Connect to the printer or server...
      */

      if (abort_job)
      {
	close(fd);

	return (CUPS_BACKEND_FAILED);
      }

      if (!connect(fd, &(addr->addr.addr), httpAddrLength(&(addr->addr))))
	break;

      error = errno;
      close(fd);

      if (addr->next)
        continue;

      if (getenv("CLASS") != NULL)
      {
       /*
        * If the CLASS environment variable is set, the job was submitted
	* to a class and not to a specific queue.  In this case, we want
	* to abort immediately so that the job can be requeued on the next
	* available printer in the class.
	*/

        _cupsLangPrintFilter(stderr, "INFO",
			     _("Unable to contact printer, queuing on next "
			       "printer in class."));

       /*
        * Sleep 5 seconds to keep the job from requeuing too rapidly...
	*/

	sleep(5);

        return (CUPS_BACKEND_FAILED);
      }

      fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error));

      if (error == ECONNREFUSED || error == EHOSTDOWN ||
          error == EHOSTUNREACH)
      {
        if (contimeout && (time(NULL) - start_time) > contimeout)
	{
	  _cupsLangPrintFilter(stderr, "ERROR",
			       _("The printer is not responding."));
	  return (CUPS_BACKEND_FAILED);
	}

	switch (error)
	{
	  case EHOSTDOWN :
	      _cupsLangPrintFilter(stderr, "WARNING",
			           _("The printer may not exist or "
			             "is unavailable at this time."));
	      break;

	  case EHOSTUNREACH :
	      _cupsLangPrintFilter(stderr, "WARNING",
			           _("The printer is unreachable at "
				     "this time."));
	      break;

	  case ECONNREFUSED :
	  default :
	      _cupsLangPrintFilter(stderr, "WARNING",
	                           _("The printer is in use."));
	      break;
        }

	sleep(delay);

	if (delay < 30)
	  delay += 5;
      }
      else if (error == EADDRINUSE)
      {
       /*
	* Try on another port...
	*/

	sleep(1);
      }
      else
      {
	_cupsLangPrintFilter(stderr, "ERROR",
	                     _("The printer is not responding."));
	sleep(30);
      }
    }

   /*
    * Set the timeout...
    */

#ifdef WIN32
    tv = (DWORD)(timeout * 1000);

    setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
    setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv));
#else
    tv.tv_sec  = timeout;
    tv.tv_usec = 0;

    setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
    setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
#endif /* WIN32 */

    fputs("STATE: -connecting-to-device\n", stderr);
    _cupsLangPrintFilter(stderr, "INFO", _("Connected to printer."));

    fprintf(stderr, "DEBUG: Connected to %s:%d (local port %d)...\n",
	    httpAddrString(&(addr->addr), addrname, sizeof(addrname)),
	    httpAddrPort(&(addr->addr)), lport);

   /*
    * See if the printer supports SNMP...
    */

    if (snmp_fd >= 0)
      have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), NULL,
                                           NULL);
    else
      have_supplies = 0;

   /*
    * Check for side-channel requests...
    */

    backendCheckSideChannel(snmp_fd, &(addrlist->addr));

   /*
    * Next, open the print file and figure out its size...
    */

    if (print_fd)
    {
     /*
      * Use the size from the print file...
      */

      if (fstat(print_fd, &filestats))
      {
	close(fd);

	perror("DEBUG: unable to stat print file");
	return (CUPS_BACKEND_FAILED);
      }

      filestats.st_size *= manual_copies;
    }
    else
    {
     /*
      * Use a "very large value" for the size so that the printer will
      * keep printing until we close the connection...
      */

#ifdef _LARGEFILE_SOURCE
      filestats.st_size = (size_t)(999999999999.0);
#else
      filestats.st_size = 2147483647;
#endif /* _LARGEFILE_SOURCE */
    }

   /*
    * Send a job header to the printer, specifying no banner page and
    * literal output...
    */

    if (lpd_command(fd, "\002%s\n",
                    printer))		/* Receive print job(s) */
    {
      close(fd);
      return (CUPS_BACKEND_FAILED);
    }

    if (orighost && _cups_strcasecmp(orighost, "localhost"))
      strlcpy(localhost, orighost, sizeof(localhost));
    else
      httpGetHostname(NULL, localhost, sizeof(localhost));

    snprintf(control, sizeof(control),
             "H%.31s\n"		/* RFC 1179, Section 7.2 - host name <= 31 chars */
	     "P%.31s\n"		/* RFC 1179, Section 7.2 - user name <= 31 chars */
	     "J%.99s\n",	/* RFC 1179, Section 7.2 - job name <= 99 chars */
	     localhost, user, title);
    cptr = control + strlen(control);

    if (banner)
    {
      snprintf(cptr, sizeof(control) - (cptr - control),
               "C%.31s\n"	/* RFC 1179, Section 7.2 - class name <= 31 chars */
	       "L%s\n",
               localhost, user);
      cptr   += strlen(cptr);
    }

    while (copies > 0)
    {
      snprintf(cptr, sizeof(control) - (cptr - control), "%cdfA%03d%.15s\n",
               format, (int)getpid() % 1000, localhost);
      cptr   += strlen(cptr);
      copies --;
    }

    snprintf(cptr, sizeof(control) - (cptr - control),
             "UdfA%03d%.15s\n"
	     "N%.131s\n",	/* RFC 1179, Section 7.2 - sourcefile name <= 131 chars */
             (int)getpid() % 1000, localhost, title);

    fprintf(stderr, "DEBUG: Control file is:\n%s", control);

    if (order == ORDER_CONTROL_DATA)
    {
     /*
      * Check for side-channel requests...
      */

      backendCheckSideChannel(snmp_fd, &(addr->addr));

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

      if (lpd_command(fd, "\002%d cfA%03.3d%.15s\n", strlen(control),
                      (int)getpid() % 1000, localhost))
      {
	close(fd);

        return (CUPS_BACKEND_FAILED);
      }

      fprintf(stderr, "DEBUG: Sending control file (%u bytes)\n",
	      (unsigned)strlen(control));

      if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
      {
	status = errno;
	perror("DEBUG: Unable to write control file");

      }
      else
      {
        if (read(fd, &status, 1) < 1)
	{
	  _cupsLangPrintFilter(stderr, "WARNING",
	                       _("The printer did not respond."));
	  status = errno;
	}
      }

      if (status != 0)
	_cupsLangPrintFilter(stderr, "ERROR",
			     _("Remote host did not accept control file (%d)."),
			     status);
      else
	_cupsLangPrintFilter(stderr, "INFO",
	                     _("Control file sent successfully."));
    }
    else
      status = 0;

    if (status == 0)
    {
     /*
      * Check for side-channel requests...
      */

      backendCheckSideChannel(snmp_fd, &(addr->addr));

     /*
      * Send the print file...
      */

      if (lpd_command(fd, "\003" CUPS_LLFMT " dfA%03.3d%.15s\n",
                      CUPS_LLCAST filestats.st_size, (int)getpid() % 1000,
		      localhost))
      {
	close(fd);

        return (CUPS_BACKEND_FAILED);
      }

      fprintf(stderr, "DEBUG: Sending data file (" CUPS_LLFMT " bytes)\n",
	      CUPS_LLCAST filestats.st_size);

      tbytes = 0;
      for (copy = 0; copy < manual_copies; copy ++)
      {
	lseek(print_fd, 0, SEEK_SET);

	while ((nbytes = read(print_fd, buffer, sizeof(buffer))) > 0)
	{
	  _cupsLangPrintFilter(stderr, "INFO",
			       _("Spooling job, %.0f%% complete."),
			       100.0 * tbytes / filestats.st_size);

	  if (lpd_write(fd, buffer, nbytes) < nbytes)
	  {
	    perror("DEBUG: Unable to send print file to printer");
            break;
	  }
	  else
            tbytes += nbytes;
	}
      }

      if (mode == MODE_STANDARD)
      {
	if (tbytes < filestats.st_size)
	  status = errno;
	else if (lpd_write(fd, "", 1) < 1)
	{
	  perror("DEBUG: Unable to send trailing nul to printer");
	  status = errno;
	}
	else
	{
	 /*
          * Read the status byte from the printer; if we can't read the byte
	  * back now, we should set status to "errno", however at this point
	  * we know the printer got the whole file and we don't necessarily
	  * want to requeue it over and over...
	  */

          if (recv(fd, &status, 1, 0) < 1)
	  {
	    _cupsLangPrintFilter(stderr, "WARNING",
			         _("The printer did not respond."));
	    status = 0;
          }
	}
      }
      else
        status = 0;

      if (status != 0)
	_cupsLangPrintFilter(stderr, "ERROR",
			     _("Remote host did not accept data file (%d)."),
			     status);
      else
	_cupsLangPrintFilter(stderr, "INFO",
	                     _("Data file sent successfully."));
    }

    if (status == 0 && order == ORDER_DATA_CONTROL)
    {
     /*
      * Check for side-channel requests...
      */

      backendCheckSideChannel(snmp_fd, &(addr->addr));

     /*
      * Send control file...
      */

      if (lpd_command(fd, "\002%d cfA%03.3d%.15s\n", strlen(control),
                      (int)getpid() % 1000, localhost))
      {
	close(fd);

        return (CUPS_BACKEND_FAILED);
      }

      fprintf(stderr, "DEBUG: Sending control file (%lu bytes)\n",
	      (unsigned long)strlen(control));

      if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1))
      {
	status = errno;
	perror("DEBUG: Unable to write control file");
      }
      else
      {
        if (read(fd, &status, 1) < 1)
	{
	  _cupsLangPrintFilter(stderr, "WARNING",
			       _("The printer did not respond."));
	  status = errno;
	}
      }

      if (status != 0)
	_cupsLangPrintFilter(stderr, "ERROR",
			     _("Remote host did not accept control file (%d)."),
			     status);
      else
	_cupsLangPrintFilter(stderr, "INFO",
	                     _("Control file sent successfully."));
    }

   /*
    * Collect the final supply levels as needed...
    */

    if (have_supplies)
      backendSNMPSupplies(snmp_fd, &(addr->addr), NULL, NULL);

   /*
    * Close the socket connection and input file...
    */

    close(fd);

    if (status == 0)
      return (CUPS_BACKEND_OK);

   /*
    * Waiting for a retry...
    */

    sleep(30);
  }

 /*
  * If we get here, then the job has been canceled...
  */

  return (CUPS_BACKEND_FAILED);
}
Example #5
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i, j, k;		/* Looping vars */
  http_t	*http;			/* HTTP connection */
  http_encryption_t encryption;		/* Encryption type */
  http_status_t	status;			/* Status of GET command */
  int		failures;		/* Number of test failures */
  char		buffer[8192];		/* Input buffer */
  long		bytes;			/* Number of bytes read */
  FILE		*out;			/* Output file */
  char		encode[256],		/* Base64-encoded string */
		decode[256];		/* Base64-decoded string */
  int		decodelen;		/* Length of decoded string */
  char		scheme[HTTP_MAX_URI],	/* Scheme from URI */
		hostname[HTTP_MAX_URI],	/* Hostname from URI */
		username[HTTP_MAX_URI],	/* Username:password from URI */
		resource[HTTP_MAX_URI];	/* Resource from URI */
  int		port;			/* Port number from URI */
  http_uri_status_t uri_status;		/* Status of URI separation */
  http_addrlist_t *addrlist,		/* Address list */
		*addr;			/* Current address */
  off_t		length, total;		/* Length and total bytes */
  time_t	start, current;		/* Start and end time */
  const char	*encoding;		/* Negotiated Content-Encoding */
  static const char * const uri_status_strings[] =
		{
		  "HTTP_URI_STATUS_OVERFLOW",
		  "HTTP_URI_STATUS_BAD_ARGUMENTS",
		  "HTTP_URI_STATUS_BAD_RESOURCE",
		  "HTTP_URI_STATUS_BAD_PORT",
		  "HTTP_URI_STATUS_BAD_HOSTNAME",
		  "HTTP_URI_STATUS_BAD_USERNAME",
		  "HTTP_URI_STATUS_BAD_SCHEME",
		  "HTTP_URI_STATUS_BAD_URI",
		  "HTTP_URI_STATUS_OK",
		  "HTTP_URI_STATUS_MISSING_SCHEME",
		  "HTTP_URI_STATUS_UNKNOWN_SCHEME",
		  "HTTP_URI_STATUS_MISSING_RESOURCE"
		};


 /*
  * Do API tests if we don't have a URL on the command-line...
  */

  if (argc == 1)
  {
    failures = 0;

   /*
    * httpGetDateString()/httpGetDateTime()
    */

    fputs("httpGetDateString()/httpGetDateTime(): ", stdout);

    start = time(NULL);
    strlcpy(buffer, httpGetDateString(start), sizeof(buffer));
    current = httpGetDateTime(buffer);

    i = (int)(current - start);
    if (i < 0)
      i = -i;

    if (!i)
      puts("PASS");
    else
    {
      failures ++;
      puts("FAIL");
      printf("    Difference is %d seconds, %02d:%02d:%02d...\n", i, i / 3600,
             (i / 60) % 60, i % 60);
      printf("    httpGetDateString(%d) returned \"%s\"\n", (int)start, buffer);
      printf("    httpGetDateTime(\"%s\") returned %d\n", buffer, (int)current);
      printf("    httpGetDateString(%d) returned \"%s\"\n", (int)current,
             httpGetDateString(current));
    }

   /*
    * httpDecode64_2()/httpEncode64_2()
    */

    fputs("httpDecode64_2()/httpEncode64_2(): ", stdout);

    for (i = 0, j = 0; i < (int)(sizeof(base64_tests) / sizeof(base64_tests[0])); i ++)
    {
      httpEncode64_2(encode, sizeof(encode), base64_tests[i][0],
                     (int)strlen(base64_tests[i][0]));
      decodelen = (int)sizeof(decode);
      httpDecode64_2(decode, &decodelen, base64_tests[i][1]);

      if (strcmp(decode, base64_tests[i][0]))
      {
        failures ++;

        if (j)
	{
	  puts("FAIL");
	  j = 1;
	}

        printf("    httpDecode64_2() returned \"%s\", expected \"%s\"...\n",
	       decode, base64_tests[i][0]);
      }

      if (strcmp(encode, base64_tests[i][1]))
      {
        failures ++;

        if (j)
	{
	  puts("FAIL");
	  j = 1;
	}

        printf("    httpEncode64_2() returned \"%s\", expected \"%s\"...\n",
	       encode, base64_tests[i][1]);
      }
    }

    if (!j)
      puts("PASS");

   /*
    * httpGetHostname()
    */

    fputs("httpGetHostname(): ", stdout);

    if (httpGetHostname(NULL, hostname, sizeof(hostname)))
      printf("PASS (%s)\n", hostname);
    else
    {
      failures ++;
      puts("FAIL");
    }

   /*
    * httpAddrGetList()
    */

    printf("httpAddrGetList(%s): ", hostname);

    addrlist = httpAddrGetList(hostname, AF_UNSPEC, NULL);
    if (addrlist)
    {
      for (i = 0, addr = addrlist; addr; i ++, addr = addr->next)
      {
        char	numeric[1024];		/* Numeric IP address */


	httpAddrString(&(addr->addr), numeric, sizeof(numeric));
	if (!strcmp(numeric, "UNKNOWN"))
	  break;
      }

      if (addr)
        printf("FAIL (bad address for %s)\n", hostname);
      else
        printf("PASS (%d address(es) for %s)\n", i, hostname);

      httpAddrFreeList(addrlist);
    }
    else if (isdigit(hostname[0] & 255))
    {
      puts("FAIL (ignored because hostname is numeric)");
    }
    else
    {
      failures ++;
      puts("FAIL");
    }

   /*
    * Test httpSeparateURI()...
    */

    fputs("httpSeparateURI(): ", stdout);
    for (i = 0, j = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++)
    {
      uri_status = httpSeparateURI(HTTP_URI_CODING_MOST,
				   uri_tests[i].uri, scheme, sizeof(scheme),
                                   username, sizeof(username),
				   hostname, sizeof(hostname), &port,
				   resource, sizeof(resource));
      if (uri_status != uri_tests[i].result ||
          strcmp(scheme, uri_tests[i].scheme) ||
	  strcmp(username, uri_tests[i].username) ||
	  strcmp(hostname, uri_tests[i].hostname) ||
	  port != uri_tests[i].port ||
	  strcmp(resource, uri_tests[i].resource))
      {
        failures ++;

	if (!j)
	{
	  puts("FAIL");
	  j = 1;
	}

        printf("    \"%s\":\n", uri_tests[i].uri);

	if (uri_status != uri_tests[i].result)
	  printf("        Returned %s instead of %s\n",
	         uri_status_strings[uri_status + 8],
		 uri_status_strings[uri_tests[i].result + 8]);

        if (strcmp(scheme, uri_tests[i].scheme))
	  printf("        Scheme \"%s\" instead of \"%s\"\n",
	         scheme, uri_tests[i].scheme);

	if (strcmp(username, uri_tests[i].username))
	  printf("        Username \"%s\" instead of \"%s\"\n",
	         username, uri_tests[i].username);

	if (strcmp(hostname, uri_tests[i].hostname))
	  printf("        Hostname \"%s\" instead of \"%s\"\n",
	         hostname, uri_tests[i].hostname);

	if (port != uri_tests[i].port)
	  printf("        Port %d instead of %d\n",
	         port, uri_tests[i].port);

	if (strcmp(resource, uri_tests[i].resource))
	  printf("        Resource \"%s\" instead of \"%s\"\n",
	         resource, uri_tests[i].resource);
      }
    }

    if (!j)
      printf("PASS (%d URIs tested)\n",
             (int)(sizeof(uri_tests) / sizeof(uri_tests[0])));

   /*
    * Test httpAssembleURI()...
    */

    fputs("httpAssembleURI(): ", stdout);
    for (i = 0, j = 0, k = 0;
         i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0]));
	 i ++)
      if (uri_tests[i].result == HTTP_URI_STATUS_OK &&
          !strstr(uri_tests[i].uri, "%64") &&
          strstr(uri_tests[i].uri, "//"))
      {
        k ++;
	uri_status = httpAssembleURI(uri_tests[i].assemble_coding,
				     buffer, sizeof(buffer),
	                             uri_tests[i].scheme,
				     uri_tests[i].username,
	                             uri_tests[i].hostname,
				     uri_tests[i].assemble_port,
				     uri_tests[i].resource);

        if (uri_status != HTTP_URI_STATUS_OK)
	{
          failures ++;

	  if (!j)
	  {
	    puts("FAIL");
	    j = 1;
	  }

          printf("    \"%s\": %s\n", uri_tests[i].uri,
	         uri_status_strings[uri_status + 8]);
        }
	else if (strcmp(buffer, uri_tests[i].uri))
	{
          failures ++;

	  if (!j)
	  {
	    puts("FAIL");
	    j = 1;
	  }

          printf("    \"%s\": assembled = \"%s\"\n", uri_tests[i].uri,
	         buffer);
	}
      }

    if (!j)
      printf("PASS (%d URIs tested)\n", k);

   /*
    * httpAssembleUUID
    */

    fputs("httpAssembleUUID: ", stdout);
    httpAssembleUUID("hostname.example.com", 631, "printer", 12345, buffer,
                     sizeof(buffer));
    if (strncmp(buffer, "urn:uuid:", 9))
    {
      printf("FAIL (%s)\n", buffer);
      failures ++;
    }
    else
      printf("PASS (%s)\n", buffer);

   /*
    * Show a summary and return...
    */

    if (failures)
      printf("\n%d TESTS FAILED!\n", failures);
    else
      puts("\nALL TESTS PASSED!");

    return (failures);
  }
  else if (strstr(argv[1], "._tcp"))
  {
   /*
    * Test resolving an mDNS name.
    */

    char	resolved[1024];		/* Resolved URI */


    printf("_httpResolveURI(%s, _HTTP_RESOLVE_DEFAULT): ", argv[1]);
    fflush(stdout);

    if (!_httpResolveURI(argv[1], resolved, sizeof(resolved),
                         _HTTP_RESOLVE_DEFAULT, NULL, NULL))
    {
      puts("FAIL");
      return (1);
    }
    else
      printf("PASS (%s)\n", resolved);

    printf("_httpResolveURI(%s, _HTTP_RESOLVE_FQDN): ", argv[1]);
    fflush(stdout);

    if (!_httpResolveURI(argv[1], resolved, sizeof(resolved),
                         _HTTP_RESOLVE_FQDN, NULL, NULL))
    {
      puts("FAIL");
      return (1);
    }
    else if (strstr(resolved, ".local:"))
    {
      printf("FAIL (%s)\n", resolved);
      return (1);
    }
    else
    {
      printf("PASS (%s)\n", resolved);
      return (0);
    }
  }
  else if (!strcmp(argv[1], "-u") && argc == 3)
  {
   /*
    * Test URI separation...
    */

    uri_status = httpSeparateURI(HTTP_URI_CODING_ALL, argv[2], scheme,
                                 sizeof(scheme), username, sizeof(username),
				 hostname, sizeof(hostname), &port,
				 resource, sizeof(resource));
    printf("uri_status = %s\n", uri_status_strings[uri_status + 8]);
    printf("scheme     = \"%s\"\n", scheme);
    printf("username   = \"%s\"\n", username);
    printf("hostname   = \"%s\"\n", hostname);
    printf("port       = %d\n", port);
    printf("resource   = \"%s\"\n", resource);

    return (0);
  }

 /*
  * Test HTTP GET requests...
  */

  http = NULL;
  out = stdout;

  for (i = 1; i < argc; i ++)
  {
    if (!strcmp(argv[i], "-o"))
    {
      i ++;
      if (i >= argc)
        break;

      out = fopen(argv[i], "wb");
      continue;
    }

    httpSeparateURI(HTTP_URI_CODING_MOST, argv[i], scheme, sizeof(scheme),
                    username, sizeof(username),
                    hostname, sizeof(hostname), &port,
		    resource, sizeof(resource));

    if (!_cups_strcasecmp(scheme, "https") || !_cups_strcasecmp(scheme, "ipps") ||
        port == 443)
      encryption = HTTP_ENCRYPTION_ALWAYS;
    else
      encryption = HTTP_ENCRYPTION_IF_REQUESTED;

    http = httpConnect2(hostname, port, NULL, AF_UNSPEC, encryption, 1, 30000,
                        NULL);
    if (http == NULL)
    {
      perror(hostname);
      continue;
    }
    printf("Checking file \"%s\"...\n", resource);

    do
    {
      if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
      {
	httpClearFields(http);
	if (httpReconnect2(http, 30000, NULL))
	{
          status = HTTP_STATUS_ERROR;
          break;
	}
      }

      httpClearFields(http);
      httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http));
      httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en");
      if (httpHead(http, resource))
      {
        if (httpReconnect2(http, 30000, NULL))
        {
          status = HTTP_STATUS_ERROR;
          break;
        }
        else
        {
          status = HTTP_STATUS_UNAUTHORIZED;
          continue;
        }
      }

      while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);

      if (status == HTTP_STATUS_UNAUTHORIZED)
      {
       /*
	* Flush any error message...
	*/

	httpFlush(http);

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

	if (cupsDoAuthentication(http, "GET", resource))
	{
	  status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
	  break;
	}

	if (httpReconnect2(http, 30000, NULL))
	{
	  status = HTTP_STATUS_ERROR;
	  break;
	}

	continue;
      }
#ifdef HAVE_SSL
      else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
      {
	/* Flush any error message... */
	httpFlush(http);

	/* Reconnect... */
	if (httpReconnect2(http, 30000, NULL))
	{
	  status = HTTP_STATUS_ERROR;
	  break;
	}

	/* Upgrade with encryption... */
	httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);

	/* Try again, this time with encryption enabled... */
	continue;
      }
#endif /* HAVE_SSL */
    }
    while (status == HTTP_STATUS_UNAUTHORIZED ||
           status == HTTP_STATUS_UPGRADE_REQUIRED);

    if (status == HTTP_STATUS_OK)
      puts("HEAD OK:");
    else
      printf("HEAD failed with status %d...\n", status);

    encoding = httpGetContentEncoding(http);

    printf("Requesting file \"%s\" (Accept-Encoding: %s)...\n", resource,
           encoding ? encoding : "identity");

    do
    {
      if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
      {
	httpClearFields(http);
	if (httpReconnect2(http, 30000, NULL))
	{
          status = HTTP_STATUS_ERROR;
          break;
	}
      }

      httpClearFields(http);
      httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http));
      httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en");
      httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, encoding);

      if (httpGet(http, resource))
      {
        if (httpReconnect2(http, 30000, NULL))
        {
          status = HTTP_STATUS_ERROR;
          break;
        }
        else
        {
          status = HTTP_STATUS_UNAUTHORIZED;
          continue;
        }
      }

      while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);

      if (status == HTTP_STATUS_UNAUTHORIZED)
      {
       /*
	* Flush any error message...
	*/

	httpFlush(http);

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

	if (cupsDoAuthentication(http, "GET", resource))
	{
	  status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
	  break;
	}

	if (httpReconnect2(http, 30000, NULL))
	{
	  status = HTTP_STATUS_ERROR;
	  break;
	}

	continue;
      }
#ifdef HAVE_SSL
      else if (status == HTTP_STATUS_UPGRADE_REQUIRED)
      {
	/* Flush any error message... */
	httpFlush(http);

	/* Reconnect... */
	if (httpReconnect2(http, 30000, NULL))
	{
	  status = HTTP_STATUS_ERROR;
	  break;
	}

	/* Upgrade with encryption... */
	httpEncryption(http, HTTP_ENCRYPTION_REQUIRED);

	/* Try again, this time with encryption enabled... */
	continue;
      }
#endif /* HAVE_SSL */
    }
    while (status == HTTP_STATUS_UNAUTHORIZED || status == HTTP_STATUS_UPGRADE_REQUIRED);

    if (status == HTTP_STATUS_OK)
      puts("GET OK:");
    else
      printf("GET failed with status %d...\n", status);

    start  = time(NULL);
    length = httpGetLength2(http);
    total  = 0;

    while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
    {
      total += bytes;
      fwrite(buffer, bytes, 1, out);
      if (out != stdout)
      {
        current = time(NULL);
        if (current == start) current ++;
        printf("\r" CUPS_LLFMT "/" CUPS_LLFMT " bytes ("
	       CUPS_LLFMT " bytes/sec)      ", CUPS_LLCAST total,
	       CUPS_LLCAST length, CUPS_LLCAST (total / (current - start)));
        fflush(stdout);
      }
    }
  }

  puts("Closing connection to server...");
  httpClose(http);

  if (out != stdout)
    fclose(out);

  return (0);
}
Example #6
0
char *					/* O - New URL */
cgiRewriteURL(const char *uri,		/* I - Current URI */
              char       *url,		/* O - New URL */
	      int        urlsize,	/* I - Size of URL buffer */
	      const char *newresource)	/* I - Replacement resource */
{
  char			method[HTTP_MAX_URI],
			userpass[HTTP_MAX_URI],
			hostname[HTTP_MAX_URI],
			rawresource[HTTP_MAX_URI],
			resource[HTTP_MAX_URI],
					/* URI components... */
			*rawptr,	/* Pointer into rawresource */
			*resptr;	/* Pointer into resource */
  int			port;		/* Port number */
  static int		ishttps = -1;	/* Using encryption? */
  static const char	*server;	/* Name of server */
  static char		servername[1024];
					/* Local server name */
  static const char	hexchars[] = "0123456789ABCDEF";
					/* Hexadecimal conversion characters */


 /*
  * Check if we have been called before...
  */

  if (ishttps < 0)
  {
   /*
    * No, initialize static vars for the conversion...
    *
    * First get the server name associated with the client interface as
    * well as the locally configured hostname.  We'll check *both* of
    * these to see if the printer URL is local...
    */

    if ((server = getenv("SERVER_NAME")) == NULL)
      server = "";

    httpGetHostname(NULL, servername, sizeof(servername));

   /*
    * Then flag whether we are using SSL on this connection...
    */

    ishttps = getenv("HTTPS") != NULL;
  }

 /*
  * Convert the URI to a URL...
  */

  httpSeparateURI(HTTP_URI_CODING_ALL, uri, method, sizeof(method), userpass,
                  sizeof(userpass), hostname, sizeof(hostname), &port,
		  rawresource, sizeof(rawresource));

  if (!strcmp(method, "ipp") ||
      !strcmp(method, "http") ||
      !strcmp(method, "https"))
  {
    if (newresource)
    {
     /*
      * Force the specified resource name instead of the one in the URL...
      */

      strlcpy(resource, newresource, sizeof(resource));
    }
    else
    {
     /*
      * Rewrite the resource string so it doesn't contain any
      * illegal chars...
      */

      for (rawptr = rawresource, resptr = resource; *rawptr; rawptr ++)
	if ((*rawptr & 128) || *rawptr == '%' || *rawptr == ' ' ||
	    *rawptr == '#' || *rawptr == '?' ||
	    *rawptr == '.') /* For MSIE */
	{
	  if (resptr < (resource + sizeof(resource) - 3))
	  {
	    *resptr++ = '%';
	    *resptr++ = hexchars[(*rawptr >> 4) & 15];
	    *resptr++ = hexchars[*rawptr & 15];
	  }
	}
	else if (resptr < (resource + sizeof(resource) - 1))
	  *resptr++ = *rawptr;

      *resptr = '\0';
    }
Example #7
0
int					/* O - 1 on success, 0 on failure */
cupsAdminSetServerSettings(
    http_t        *http,		/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
    int           num_settings,		/* I - Number of settings */
    cups_option_t *settings)		/* I - Settings */
{
  int		i;			/* Looping var */
  http_status_t status;			/* GET/PUT status */
  const char	*server_port_env;	/* SERVER_PORT env var */
  int		server_port;		/* IPP port for server */
  cups_file_t	*cupsd;			/* cupsd.conf file */
  char		cupsdconf[1024];	/* cupsd.conf filename */
  int		remote;			/* Remote cupsd.conf file? */
  char		tempfile[1024];		/* Temporary new cupsd.conf */
  cups_file_t	*temp;			/* Temporary file */
  char		line[1024],		/* Line from cupsd.conf file */
		*value;			/* Value on line */
  int		linenum,		/* Line number in file */
		in_location,		/* In a location section? */
		in_policy,		/* In a policy section? */
		in_default_policy,	/* In the default policy section? */
		in_cancel_job,		/* In a cancel-job section? */
		in_admin_location,	/* In the /admin location? */
		in_conf_location,	/* In the /admin/conf location? */
		in_log_location,	/* In the /admin/log location? */
		in_root_location;	/* In the / location? */
  const char	*val;			/* Setting value */
  int		share_printers,		/* Share local printers */
		remote_admin,		/* Remote administration allowed? */
		remote_any,		/* Remote access from anywhere? */
		user_cancel_any,	/* Cancel-job policy set? */
		debug_logging;		/* LogLevel debug set? */
  int		wrote_port_listen,	/* Wrote the port/listen lines? */
		wrote_browsing,		/* Wrote the browsing lines? */
		wrote_policy,		/* Wrote the policy? */
		wrote_loglevel,		/* Wrote the LogLevel line? */
		wrote_admin_location,	/* Wrote the /admin location? */
		wrote_conf_location,	/* Wrote the /admin/conf location? */
		wrote_log_location,	/* Wrote the /admin/log location? */
		wrote_root_location;	/* Wrote the / location? */
  int		indent;			/* Indentation */
  int		cupsd_num_settings;	/* New number of settings */
  int		old_share_printers,	/* Share local printers */
		old_remote_admin,	/* Remote administration allowed? */
		old_remote_any,		/* Remote access from anywhere? */
		old_user_cancel_any,	/* Cancel-job policy set? */
		old_debug_logging;	/* LogLevel debug set? */
  cups_option_t	*cupsd_settings,	/* New settings */
		*setting;		/* Current setting */
  _cups_globals_t *cg = _cupsGlobals();	/* Global data */


 /*
  * Range check input...
  */

  if (!http)
    http = _cupsConnect();

  if (!http || !num_settings || !settings)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);

    return (0);
  }

 /*
  * Get the cupsd.conf file...
  */

  if (get_cupsd_conf(http, cg, 0, cupsdconf, sizeof(cupsdconf),
                     &remote) == HTTP_STATUS_OK)
  {
    if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL)
    {
      _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0);
      return (0);
    }
  }
  else
    return (0);

 /*
  * Get current settings...
  */

  if (!cupsAdminGetServerSettings(http, &cupsd_num_settings,
				  &cupsd_settings))
    return (0);

  if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, cupsd_num_settings,
                           cupsd_settings)) != NULL)
    old_debug_logging = atoi(val);
  else
    old_debug_logging = 0;

  DEBUG_printf(("1cupsAdminSetServerSettings: old debug_logging=%d",
                old_debug_logging));

  if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, cupsd_num_settings,
                           cupsd_settings)) != NULL)
    old_remote_admin = atoi(val);
  else
    old_remote_admin = 0;

  DEBUG_printf(("1cupsAdminSetServerSettings: old remote_admin=%d",
                old_remote_admin));

  if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, cupsd_num_settings,
                           cupsd_settings)) != NULL)
    old_remote_any = atoi(val);
  else
    old_remote_any = 0;

  DEBUG_printf(("1cupsAdminSetServerSettings: old remote_any=%d",
                old_remote_any));

  if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, cupsd_num_settings,
                           cupsd_settings)) != NULL)
    old_share_printers = atoi(val);
  else
    old_share_printers = 0;

  DEBUG_printf(("1cupsAdminSetServerSettings: old share_printers=%d",
                old_share_printers));

  if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, cupsd_num_settings,
                           cupsd_settings)) != NULL)
    old_user_cancel_any = atoi(val);
  else
    old_user_cancel_any = 0;

  DEBUG_printf(("1cupsAdminSetServerSettings: old user_cancel_any=%d",
                old_user_cancel_any));

  cupsFreeOptions(cupsd_num_settings, cupsd_settings);

 /*
  * Get basic settings...
  */

  if ((val = cupsGetOption(CUPS_SERVER_DEBUG_LOGGING, num_settings,
                           settings)) != NULL)
  {
    debug_logging = atoi(val);

    if (debug_logging == old_debug_logging)
    {
     /*
      * No change to this setting...
      */

      debug_logging = -1;
    }
  }
  else
    debug_logging = -1;

  DEBUG_printf(("1cupsAdminSetServerSettings: debug_logging=%d",
                debug_logging));

  if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ANY, num_settings, settings)) != NULL)
  {
    remote_any = atoi(val);

    if (remote_any == old_remote_any)
    {
     /*
      * No change to this setting...
      */

      remote_any = -1;
    }
  }
  else
    remote_any = -1;

  DEBUG_printf(("1cupsAdminSetServerSettings: remote_any=%d", remote_any));

  if ((val = cupsGetOption(CUPS_SERVER_REMOTE_ADMIN, num_settings,
                           settings)) != NULL)
  {
    remote_admin = atoi(val);

    if (remote_admin == old_remote_admin)
    {
     /*
      * No change to this setting...
      */

      remote_admin = -1;
    }
  }
  else
    remote_admin = -1;

  DEBUG_printf(("1cupsAdminSetServerSettings: remote_admin=%d",
                remote_admin));

  if ((val = cupsGetOption(CUPS_SERVER_SHARE_PRINTERS, num_settings,
                           settings)) != NULL)
  {
    share_printers = atoi(val);

    if (share_printers == old_share_printers)
    {
     /*
      * No change to this setting...
      */

      share_printers = -1;
    }
  }
  else
    share_printers = -1;

  DEBUG_printf(("1cupsAdminSetServerSettings: share_printers=%d",
                share_printers));

  if ((val = cupsGetOption(CUPS_SERVER_USER_CANCEL_ANY, num_settings,
                           settings)) != NULL)
  {
    user_cancel_any = atoi(val);

    if (user_cancel_any == old_user_cancel_any)
    {
     /*
      * No change to this setting...
      */

      user_cancel_any = -1;
    }
  }
  else
    user_cancel_any = -1;

  DEBUG_printf(("1cupsAdminSetServerSettings: user_cancel_any=%d",
                user_cancel_any));

 /*
  * Create a temporary file for the new cupsd.conf file...
  */

  if ((temp = cupsTempFile2(tempfile, sizeof(tempfile))) == NULL)
  {
    cupsFileClose(cupsd);

    if (remote)
      unlink(cupsdconf);

    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0);
    return (0);
  }

 /*
  * Copy the old file to the new, making changes along the way...
  */

  cupsd_num_settings   = 0;
  in_admin_location    = 0;
  in_cancel_job        = 0;
  in_conf_location     = 0;
  in_default_policy    = 0;
  in_location          = 0;
  in_log_location      = 0;
  in_policy            = 0;
  in_root_location     = 0;
  linenum              = 0;
  wrote_admin_location = 0;
  wrote_browsing       = 0;
  wrote_conf_location  = 0;
  wrote_log_location   = 0;
  wrote_loglevel       = 0;
  wrote_policy         = 0;
  wrote_port_listen    = 0;
  wrote_root_location  = 0;
  indent               = 0;

  if ((server_port_env = getenv("SERVER_PORT")) != NULL)
  {
    if ((server_port = atoi(server_port_env)) <= 0)
      server_port = ippPort();
  }
  else
    server_port = ippPort();

  if (server_port <= 0)
    server_port = IPP_PORT;

  while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum))
  {
    if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")) &&
        (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0))
    {
      if (!wrote_port_listen)
      {
        wrote_port_listen = 1;

	if (remote_admin > 0 || remote_any > 0 || share_printers > 0)
	{
	  cupsFilePuts(temp, "# Allow remote access\n");
	  cupsFilePrintf(temp, "Port %d\n", server_port);
	}
	else
	{
	  cupsFilePuts(temp, "# Only listen for connections from the local "
	                     "machine.\n");
	  cupsFilePrintf(temp, "Listen localhost:%d\n", server_port);
	}

#ifdef CUPS_DEFAULT_DOMAINSOCKET
        if ((!value || strcmp(CUPS_DEFAULT_DOMAINSOCKET, value)) &&
	    !access(CUPS_DEFAULT_DOMAINSOCKET, 0))
          cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n");
#endif /* CUPS_DEFAULT_DOMAINSOCKET */
      }
      else if (value && value[0] == '/'
#ifdef CUPS_DEFAULT_DOMAINSOCKET
               && strcmp(CUPS_DEFAULT_DOMAINSOCKET, value)
#endif /* CUPS_DEFAULT_DOMAINSOCKET */
               )
        cupsFilePrintf(temp, "Listen %s\n", value);
    }
    else if ((!_cups_strcasecmp(line, "Browsing") ||
              !_cups_strcasecmp(line, "BrowseLocalProtocols")) &&
	     share_printers >= 0)
    {
      if (!wrote_browsing)
      {
	int new_share_printers = (share_printers > 0 ||
				  (share_printers == -1 &&
				   old_share_printers > 0));

        wrote_browsing = 1;

        if (new_share_printers)
	{
	  const char *localp = cupsGetOption("BrowseLocalProtocols",
					     num_settings, settings);

          if (!localp || !localp[0])
	    localp = cupsGetOption("BrowseLocalProtocols", cupsd_num_settings,
	                           cupsd_settings);

	  cupsFilePuts(temp, "# Share local printers on the local network.\n");
	  cupsFilePuts(temp, "Browsing On\n");

	  if (!localp)
	    localp = CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS;

	  cupsFilePrintf(temp, "BrowseLocalProtocols %s\n", localp);

	  cupsd_num_settings = cupsAddOption("BrowseLocalProtocols", localp,
					     cupsd_num_settings,
					     &cupsd_settings);
        }
	else
	{
	  cupsFilePuts(temp, "# Disable printer sharing.\n");
	  cupsFilePuts(temp, "Browsing Off\n");
	}
      }
    }
    else if (!_cups_strcasecmp(line, "LogLevel") && debug_logging >= 0)
    {
      wrote_loglevel = 1;

      if (debug_logging)
      {
        cupsFilePuts(temp,
	             "# Show troubleshooting information in error_log.\n");
	cupsFilePuts(temp, "LogLevel debug\n");
      }
      else
      {
        cupsFilePuts(temp, "# Show general information in error_log.\n");
	cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n");
      }
    }
    else if (!_cups_strcasecmp(line, "<Policy"))
    {
      in_default_policy = !_cups_strcasecmp(value, "default");
      in_policy         = 1;

      cupsFilePrintf(temp, "%s %s>\n", line, value);
      indent += 2;
    }
    else if (!_cups_strcasecmp(line, "</Policy>"))
    {
      indent -= 2;
      if (!wrote_policy && in_default_policy)
      {
	wrote_policy = 1;

        if (!user_cancel_any)
	  cupsFilePuts(temp, "  # Only the owner or an administrator can "
	                     "cancel a job...\n"
	                     "  <Limit Cancel-Job>\n"
	                     "    Order deny,allow\n"
			     "    Require user @OWNER "
			     CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n"
			     "  </Limit>\n");
      }

      in_policy         = 0;
      in_default_policy = 0;

      cupsFilePuts(temp, "</Policy>\n");
    }
    else if (!_cups_strcasecmp(line, "<Location"))
    {
      in_location = 1;
      indent += 2;
      if (!strcmp(value, "/admin"))
	in_admin_location = 1;
      else if (!strcmp(value, "/admin/conf"))
	in_conf_location = 1;
      else if (!strcmp(value, "/admin/log"))
	in_log_location = 1;
      else if (!strcmp(value, "/"))
	in_root_location = 1;

      cupsFilePrintf(temp, "%s %s>\n", line, value);
    }
    else if (!_cups_strcasecmp(line, "</Location>"))
    {
      in_location = 0;
      indent -= 2;
      if (in_admin_location && remote_admin >= 0)
      {
	wrote_admin_location = 1;

	if (remote_admin)
          cupsFilePuts(temp, "  # Allow remote administration...\n");
	else if (remote_admin == 0)
          cupsFilePuts(temp, "  # Restrict access to the admin pages...\n");

        cupsFilePuts(temp, "  Order allow,deny\n");

	if (remote_admin)
	  cupsFilePrintf(temp, "  Allow %s\n",
	                 remote_any > 0 ? "all" : "@LOCAL");
      }
      else if (in_conf_location && remote_admin >= 0)
      {
	wrote_conf_location = 1;

	if (remote_admin)
          cupsFilePuts(temp, "  # Allow remote access to the configuration "
	                     "files...\n");
	else
          cupsFilePuts(temp, "  # Restrict access to the configuration "
	                     "files...\n");

        cupsFilePuts(temp, "  Order allow,deny\n");

	if (remote_admin)
	  cupsFilePrintf(temp, "  Allow %s\n",
	                 remote_any > 0 ? "all" : "@LOCAL");
      }
      else if (in_log_location && remote_admin >= 0)
      {
	wrote_log_location = 1;

	if (remote_admin)
          cupsFilePuts(temp, "  # Allow remote access to the log "
	                     "files...\n");
	else
          cupsFilePuts(temp, "  # Restrict access to the log "
	                     "files...\n");

        cupsFilePuts(temp, "  Order allow,deny\n");

	if (remote_admin)
	  cupsFilePrintf(temp, "  Allow %s\n",
	                 remote_any > 0 ? "all" : "@LOCAL");
      }
      else if (in_root_location &&
               (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0))
      {
	wrote_root_location = 1;

	if (remote_admin > 0 && share_printers > 0)
          cupsFilePuts(temp, "  # Allow shared printing and remote "
	                     "administration...\n");
	else if (remote_admin > 0)
          cupsFilePuts(temp, "  # Allow remote administration...\n");
	else if (share_printers > 0)
          cupsFilePuts(temp, "  # Allow shared printing...\n");
	else if (remote_any > 0)
          cupsFilePuts(temp, "  # Allow remote access...\n");
	else
          cupsFilePuts(temp, "  # Restrict access to the server...\n");

        cupsFilePuts(temp, "  Order allow,deny\n");

	if (remote_admin > 0 || remote_any > 0 || share_printers > 0)
	  cupsFilePrintf(temp, "  Allow %s\n",
	                 remote_any > 0 ? "all" : "@LOCAL");
      }

      in_admin_location = 0;
      in_conf_location  = 0;
      in_log_location   = 0;
      in_root_location  = 0;

      cupsFilePuts(temp, "</Location>\n");
    }
    else if (!_cups_strcasecmp(line, "<Limit"))
    {
      if (in_default_policy)
      {
       /*
	* See if the policy limit is for the Cancel-Job operation...
	*/

	char	*valptr;		/* Pointer into value */


	if (!_cups_strcasecmp(value, "cancel-job") && user_cancel_any >= 0)
	{
	 /*
	  * Don't write anything for this limit section...
	  */

	  in_cancel_job = 2;
	}
	else
	{
	  cupsFilePrintf(temp, "%*s%s", indent, "", line);

	  while (*value)
	  {
	    for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++);

	    if (*valptr)
	      *valptr++ = '\0';

	    if (!_cups_strcasecmp(value, "cancel-job") && user_cancel_any >= 0)
	    {
	     /*
	      * Write everything except for this definition...
	      */

	      in_cancel_job = 1;
	    }
	    else
	      cupsFilePrintf(temp, " %s", value);

	    for (value = valptr; _cups_isspace(*value); value ++);
	  }

	  cupsFilePuts(temp, ">\n");
	}
      }
      else
        cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value);

      indent += 2;
    }
    else if (!_cups_strcasecmp(line, "</Limit>") && in_cancel_job)
    {
      indent -= 2;

      if (in_cancel_job == 1)
	cupsFilePuts(temp, "  </Limit>\n");

      wrote_policy = 1;

      if (!user_cancel_any)
	cupsFilePuts(temp, "  # Only the owner or an administrator can cancel "
			   "a job...\n"
			   "  <Limit Cancel-Job>\n"
			   "    Order deny,allow\n"
			   "    Require user @OWNER "
			   CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n"
			   "  </Limit>\n");

      in_cancel_job = 0;
    }
    else if ((((in_admin_location || in_conf_location || in_root_location) &&
               (remote_admin >= 0 || remote_any >= 0)) ||
              (in_root_location && share_printers >= 0)) &&
             (!_cups_strcasecmp(line, "Allow") || !_cups_strcasecmp(line, "Deny") ||
	      !_cups_strcasecmp(line, "Order")))
      continue;
    else if (in_cancel_job == 2)
      continue;
    else if (line[0] == '<')
    {
      if (value)
      {
        cupsFilePrintf(temp, "%*s%s %s>\n", indent, "", line, value);
	indent += 2;
      }
      else
      {
	if (line[1] == '/')
	  indent -= 2;

	cupsFilePrintf(temp, "%*s%s\n", indent, "", line);
      }
    }
    else if (!in_policy && !in_location &&
             (val = cupsGetOption(line, num_settings, settings)) != NULL)
    {
     /*
      * Replace this directive's value with the new one...
      */

      cupsd_num_settings = cupsAddOption(line, val, cupsd_num_settings,
                                         &cupsd_settings);

     /*
      * Write the new value in its place, without indentation since we
      * only support setting root directives, not in sections...
      */

      cupsFilePrintf(temp, "%s %s\n", line, val);
    }
    else if (value)
    {
      if (!in_policy && !in_location)
      {
       /*
        * Record the non-policy, non-location directives that we find
	* in the server settings, since we cache this info and record it
	* in cupsAdminGetServerSettings()...
	*/

	cupsd_num_settings = cupsAddOption(line, value, cupsd_num_settings,
                                           &cupsd_settings);
      }

      cupsFilePrintf(temp, "%*s%s %s\n", indent, "", line, value);
    }
    else
      cupsFilePrintf(temp, "%*s%s\n", indent, "", line);
  }

 /*
  * Write any missing info...
  */

  if (!wrote_browsing && share_printers >= 0)
  {
    if (share_printers > 0)
    {
      cupsFilePuts(temp, "# Share local printers on the local network.\n");
      cupsFilePuts(temp, "Browsing On\n");
    }
    else
    {
      cupsFilePuts(temp, "# Disable printer sharing and shared printers.\n");
      cupsFilePuts(temp, "Browsing Off\n");
    }
  }

  if (!wrote_loglevel && debug_logging >= 0)
  {
    if (debug_logging)
    {
      cupsFilePuts(temp, "# Show troubleshooting information in error_log.\n");
      cupsFilePuts(temp, "LogLevel debug\n");
    }
    else
    {
      cupsFilePuts(temp, "# Show general information in error_log.\n");
      cupsFilePuts(temp, "LogLevel " CUPS_DEFAULT_LOG_LEVEL "\n");
    }
  }

  if (!wrote_port_listen &&
      (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0))
  {
    if (remote_admin > 0 || remote_any > 0 || share_printers > 0)
    {
      cupsFilePuts(temp, "# Allow remote access\n");
      cupsFilePrintf(temp, "Port %d\n", ippPort());
    }
    else
    {
      cupsFilePuts(temp,
                   "# Only listen for connections from the local machine.\n");
      cupsFilePrintf(temp, "Listen localhost:%d\n", ippPort());
    }

#ifdef CUPS_DEFAULT_DOMAINSOCKET
    if (!access(CUPS_DEFAULT_DOMAINSOCKET, 0))
      cupsFilePuts(temp, "Listen " CUPS_DEFAULT_DOMAINSOCKET "\n");
#endif /* CUPS_DEFAULT_DOMAINSOCKET */
  }

  if (!wrote_root_location &&
      (remote_admin >= 0 || remote_any >= 0 || share_printers >= 0))
  {
    if (remote_admin > 0 && share_printers > 0)
      cupsFilePuts(temp,
                   "# Allow shared printing and remote administration...\n");
    else if (remote_admin > 0)
      cupsFilePuts(temp, "# Allow remote administration...\n");
    else if (share_printers > 0)
      cupsFilePuts(temp, "# Allow shared printing...\n");
    else if (remote_any > 0)
      cupsFilePuts(temp, "# Allow remote access...\n");
    else
      cupsFilePuts(temp, "# Restrict access to the server...\n");

    cupsFilePuts(temp, "<Location />\n"
                       "  Order allow,deny\n");

    if (remote_admin > 0 || remote_any > 0 || share_printers > 0)
      cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");

    cupsFilePuts(temp, "</Location>\n");
  }

  if (!wrote_admin_location && remote_admin >= 0)
  {
    if (remote_admin)
      cupsFilePuts(temp, "# Allow remote administration...\n");
    else
      cupsFilePuts(temp, "# Restrict access to the admin pages...\n");

    cupsFilePuts(temp, "<Location /admin>\n"
                       "  Order allow,deny\n");

    if (remote_admin)
      cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");

    cupsFilePuts(temp, "</Location>\n");
  }

  if (!wrote_conf_location && remote_admin >= 0)
  {
    if (remote_admin)
      cupsFilePuts(temp,
                   "# Allow remote access to the configuration files...\n");
    else
      cupsFilePuts(temp, "# Restrict access to the configuration files...\n");

    cupsFilePuts(temp, "<Location /admin/conf>\n"
                       "  AuthType Default\n"
                       "  Require user @SYSTEM\n"
                       "  Order allow,deny\n");

    if (remote_admin)
      cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");

    cupsFilePuts(temp, "</Location>\n");
  }

  if (!wrote_log_location && remote_admin >= 0)
  {
    if (remote_admin)
      cupsFilePuts(temp,
                   "# Allow remote access to the log files...\n");
    else
      cupsFilePuts(temp, "# Restrict access to the log files...\n");

    cupsFilePuts(temp, "<Location /admin/log>\n"
                       "  AuthType Default\n"
                       "  Require user @SYSTEM\n"
                       "  Order allow,deny\n");

    if (remote_admin)
      cupsFilePrintf(temp, "  Allow %s\n", remote_any > 0 ? "all" : "@LOCAL");

    cupsFilePuts(temp, "</Location>\n");
  }

  if (!wrote_policy && user_cancel_any >= 0)
  {
    cupsFilePuts(temp, "<Policy default>\n"
                       "  # Job-related operations must be done by the owner "
		       "or an administrator...\n"
                       "  <Limit Send-Document Send-URI Hold-Job Release-Job "
		       "Restart-Job Purge-Jobs Set-Job-Attributes "
		       "Create-Job-Subscription Renew-Subscription "
		       "Cancel-Subscription Get-Notifications Reprocess-Job "
		       "Cancel-Current-Job Suspend-Current-Job Resume-Job "
		       "CUPS-Move-Job>\n"
                       "    Require user @OWNER @SYSTEM\n"
                       "    Order deny,allow\n"
                       "  </Limit>\n"
                       "  # All administration operations require an "
		       "administrator to authenticate...\n"
		       "  <Limit Pause-Printer Resume-Printer "
                       "Set-Printer-Attributes Enable-Printer "
		       "Disable-Printer Pause-Printer-After-Current-Job "
		       "Hold-New-Jobs Release-Held-New-Jobs Deactivate-Printer "
		       "Activate-Printer Restart-Printer Shutdown-Printer "
		       "Startup-Printer Promote-Job Schedule-Job-After "
		       "CUPS-Add-Printer CUPS-Delete-Printer "
		       "CUPS-Add-Class CUPS-Delete-Class "
		       "CUPS-Accept-Jobs CUPS-Reject-Jobs "
		       "CUPS-Set-Default CUPS-Add-Device CUPS-Delete-Device>\n"
                       "    AuthType Default\n"
		       "    Require user @SYSTEM\n"
                       "    Order deny,allow\n"
                       "</Limit>\n");

    if (!user_cancel_any)
      cupsFilePuts(temp, "  # Only the owner or an administrator can cancel "
                         "a job...\n"
	                 "  <Limit Cancel-Job>\n"
	                 "    Order deny,allow\n"
	                 "    Require user @OWNER "
			 CUPS_DEFAULT_PRINTOPERATOR_AUTH "\n"
			 "  </Limit>\n");

    cupsFilePuts(temp, "  <Limit All>\n"
                       "  Order deny,allow\n"
                       "  </Limit>\n"
		       "</Policy>\n");
  }

  for (i = num_settings, setting = settings; i > 0; i --, setting ++)
    if (setting->name[0] != '_' &&
        _cups_strcasecmp(setting->name, "Listen") &&
	_cups_strcasecmp(setting->name, "Port") &&
        !cupsGetOption(setting->name, cupsd_num_settings, cupsd_settings))
    {
     /*
      * Add this directive to the list of directives we have written...
      */

      cupsd_num_settings = cupsAddOption(setting->name, setting->value,
                                         cupsd_num_settings, &cupsd_settings);

     /*
      * Write the new value, without indentation since we only support
      * setting root directives, not in sections...
      */

      cupsFilePrintf(temp, "%s %s\n", setting->name, setting->value);
    }

  cupsFileClose(cupsd);
  cupsFileClose(temp);

 /*
  * Upload the configuration file to the server...
  */

  status = cupsPutFile(http, "/admin/conf/cupsd.conf", tempfile);

  if (status == HTTP_STATUS_CREATED)
  {
   /*
    * Updated OK, add the basic settings...
    */

    if (debug_logging >= 0)
      cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING,
                                	 debug_logging ? "1" : "0",
					 cupsd_num_settings, &cupsd_settings);
    else
      cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING,
                                	 old_debug_logging ? "1" : "0",
					 cupsd_num_settings, &cupsd_settings);

    if (remote_admin >= 0)
      cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN,
                                	 remote_admin ? "1" : "0",
					 cupsd_num_settings, &cupsd_settings);
    else
      cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN,
                                	 old_remote_admin ? "1" : "0",
					 cupsd_num_settings, &cupsd_settings);

    if (remote_any >= 0)
      cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY,
					 remote_any ? "1" : "0",
					 cupsd_num_settings, &cupsd_settings);
    else
      cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY,
					 old_remote_any ? "1" : "0",
					 cupsd_num_settings, &cupsd_settings);

    if (share_printers >= 0)
      cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
                                	 share_printers ? "1" : "0",
					 cupsd_num_settings, &cupsd_settings);
    else
      cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
                                	 old_share_printers ? "1" : "0",
					 cupsd_num_settings, &cupsd_settings);

    if (user_cancel_any >= 0)
      cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
                                	 user_cancel_any ? "1" : "0",
					 cupsd_num_settings, &cupsd_settings);
    else
      cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
                                	 old_user_cancel_any ? "1" : "0",
					 cupsd_num_settings, &cupsd_settings);

   /*
    * Save the new values...
    */

    invalidate_cupsd_cache(cg);

    cg->cupsd_num_settings = cupsd_num_settings;
    cg->cupsd_settings     = cupsd_settings;
    cg->cupsd_update       = time(NULL);

    httpGetHostname(http, cg->cupsd_hostname, sizeof(cg->cupsd_hostname));
  }
  else
    cupsFreeOptions(cupsd_num_settings, cupsd_settings);

 /*
  * Remote our temp files and return...
  */

  if (remote)
    unlink(cupsdconf);

  unlink(tempfile);

  return (status == HTTP_STATUS_CREATED);
}
Example #8
0
void
email_message(const char *to,		/* I - Recipient of message */
              const char *subject,	/* I - Subject of message */
	      const char *text)		/* I - Text of message */
{
  cups_file_t	*fp;			/* Pipe/socket to mail server */
  const char	*nl;			/* Newline to use */
  char		response[1024];		/* SMTP response buffer */


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

  if (mailtoSendmail[0])
  {
   /*
    * Use the sendmail command...
    */

    fp = pipe_sendmail(to);

    if (!fp)
      return;

    nl = "\n";
  }
  else
  {
   /*
    * Use an SMTP server...
    */

    char	hostbuf[1024];		/* Local hostname */


    if (strchr(mailtoSMTPServer, ':'))
      fp = cupsFileOpen(mailtoSMTPServer, "s");
    else
    {
      char	spec[1024];		/* Host:service spec */


      snprintf(spec, sizeof(spec), "%s:smtp", mailtoSMTPServer);
      fp = cupsFileOpen(spec, "s");
    }

    if (!fp)
    {
      fprintf(stderr, "ERROR: Unable to connect to SMTP server \"%s\"!\n",
              mailtoSMTPServer);
      return;
    }

    fprintf(stderr, "DEBUG: Connected to \"%s\"...\n", mailtoSMTPServer);

    cupsFilePrintf(fp, "HELO %s\r\n",
                   httpGetHostname(NULL, hostbuf, sizeof(hostbuf)));
    fprintf(stderr, "DEBUG: >>> HELO %s\n", hostbuf);

    if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
      goto smtp_error;
    fprintf(stderr, "DEBUG: <<< %s\n", response);

    cupsFilePrintf(fp, "MAIL FROM:%s\r\n", mailtoFrom);
    fprintf(stderr, "DEBUG: >>> MAIL FROM:%s\n", mailtoFrom);

    if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
      goto smtp_error;
    fprintf(stderr, "DEBUG: <<< %s\n", response);

    cupsFilePrintf(fp, "RCPT TO:%s\r\n", to);
    fprintf(stderr, "DEBUG: >>> RCPT TO:%s\n", to);

    if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
      goto smtp_error;
    fprintf(stderr, "DEBUG: <<< %s\n", response);

    cupsFilePuts(fp, "DATA\r\n");
    fputs("DEBUG: DATA\n", stderr);

    if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
      goto smtp_error;
    fprintf(stderr, "DEBUG: <<< %s\n", response);

    nl = "\r\n";
  }

 /*
  * Send the message...
  */

  cupsFilePrintf(fp, "Date: %s%s", httpGetDateString(time(NULL)), nl);
  cupsFilePrintf(fp, "From: %s%s", mailtoFrom, nl);
  cupsFilePrintf(fp, "Subject: %s %s%s", mailtoSubject, subject, nl);
  if (mailtoReplyTo[0])
  {
    cupsFilePrintf(fp, "Sender: %s%s", mailtoReplyTo, nl);
    cupsFilePrintf(fp, "Reply-To: %s%s", mailtoReplyTo, nl);
  }
  cupsFilePrintf(fp, "To: %s%s", to, nl);
  if (mailtoCc[0])
    cupsFilePrintf(fp, "Cc: %s%s", mailtoCc, nl);
  cupsFilePrintf(fp, "Content-Type: text/plain%s", nl);
  cupsFilePuts(fp, nl);
  cupsFilePrintf(fp, "%s%s", text, nl);
  cupsFilePrintf(fp, ".\n", nl);

 /*
  * Close the connection to the mail server...
  */

  if (mailtoSendmail[0])
  {
   /*
    * Close the pipe and wait for the sendmail command to finish...
    */

    int	status;				/* Exit status */


    cupsFileClose(fp);

    if (wait(&status))
      status = errno << 8;

   /*
    * Report any non-zero status...
    */

    if (status)
    {
      if (WIFEXITED(status))
        fprintf(stderr, "ERROR: Sendmail command returned status %d!\n",
	        WEXITSTATUS(status));
      else
        fprintf(stderr, "ERROR: Sendmail command crashed on signal %d!\n",
	        WTERMSIG(status));
    }
  }
  else
  {
   /*
    * Finish up the SMTP submission and close the connection...
    */

    if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
      goto smtp_error;
    fprintf(stderr, "DEBUG: <<< %s\n", response);

   /*
    * Process SMTP errors here...
    */

    smtp_error:

    cupsFilePuts(fp, "QUIT\r\n");
    fputs("DEBUG: QUIT\n", stderr);

    if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500)
      goto smtp_error;
    fprintf(stderr, "DEBUG: <<< %s\n", response);

    cupsFileClose(fp);

    fprintf(stderr, "DEBUG: Closed connection to \"%s\"...\n",
            mailtoSMTPServer);
  }
}
Example #9
0
int					/* O - Exit status */
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i, j, k;		/* Looping vars */
  http_t	*http;			/* HTTP connection */
  http_status_t	status;			/* Status of GET command */
  int		failures;		/* Number of test failures */
  char		buffer[8192];		/* Input buffer */
  long		bytes;			/* Number of bytes read */
  FILE		*out;			/* Output file */
  char		encode[256],		/* Base64-encoded string */
		decode[256];		/* Base64-decoded string */
  int		decodelen;		/* Length of decoded string */
  char		scheme[HTTP_MAX_URI],	/* Scheme from URI */
		hostname[HTTP_MAX_URI],	/* Hostname from URI */
		username[HTTP_MAX_URI],	/* Username:password from URI */
		resource[HTTP_MAX_URI];	/* Resource from URI */
  int		port;			/* Port number from URI */
  http_uri_status_t uri_status;		/* Status of URI separation */
  http_addrlist_t *addrlist,		/* Address list */
		*addr;			/* Current address */
  off_t		length, total;		/* Length and total bytes */
  time_t	start, current;		/* Start and end time */
  static const char * const uri_status_strings[] =
		{
		  "HTTP_URI_OVERFLOW",
		  "HTTP_URI_BAD_ARGUMENTS",
		  "HTTP_URI_BAD_RESOURCE",
		  "HTTP_URI_BAD_PORT",
		  "HTTP_URI_BAD_HOSTNAME",
		  "HTTP_URI_BAD_USERNAME",
		  "HTTP_URI_BAD_SCHEME",
		  "HTTP_URI_BAD_URI",
		  "HTTP_URI_OK",
		  "HTTP_URI_MISSING_SCHEME",
		  "HTTP_URI_UNKNOWN_SCHEME",
		  "HTTP_URI_MISSING_RESOURCE"
		};


 /*
  * Do API tests if we don't have a URL on the command-line...
  */

  if (argc == 1)
  {
    failures = 0;

   /*
    * httpGetDateString()/httpGetDateTime()
    */

    fputs("httpGetDateString()/httpGetDateTime(): ", stdout);

    start = time(NULL);
    strcpy(buffer, httpGetDateString(start));
    current = httpGetDateTime(buffer);

    i = (int)(current - start);
    if (i < 0)
      i = -i;

    if (!i)
      puts("PASS");
    else
    {
      failures ++;
      puts("FAIL");
      printf("    Difference is %d seconds, %02d:%02d:%02d...\n", i, i / 3600,
             (i / 60) % 60, i % 60);
      printf("    httpGetDateString(%d) returned \"%s\"\n", (int)start, buffer);
      printf("    httpGetDateTime(\"%s\") returned %d\n", buffer, (int)current);
      printf("    httpGetDateString(%d) returned \"%s\"\n", (int)current,
             httpGetDateString(current));
    }

   /*
    * httpDecode64_2()/httpEncode64_2()
    */

    fputs("httpDecode64_2()/httpEncode64_2(): ", stdout);

    for (i = 0, j = 0; i < (int)(sizeof(base64_tests) / sizeof(base64_tests[0])); i ++)
    {
      httpEncode64_2(encode, sizeof(encode), base64_tests[i][0],
                     strlen(base64_tests[i][0]));
      decodelen = (int)sizeof(decode);
      httpDecode64_2(decode, &decodelen, base64_tests[i][1]);

      if (strcmp(decode, base64_tests[i][0]))
      {
        failures ++;

        if (j)
	{
	  puts("FAIL");
	  j = 1;
	}

        printf("    httpDecode64_2() returned \"%s\", expected \"%s\"...\n",
	       decode, base64_tests[i][0]);
      }

      if (strcmp(encode, base64_tests[i][1]))
      {
        failures ++;

        if (j)
	{
	  puts("FAIL");
	  j = 1;
	}

        printf("    httpEncode64_2() returned \"%s\", expected \"%s\"...\n",
	       encode, base64_tests[i][1]);
      }
    }

    if (!j)
      puts("PASS");

   /*
    * httpGetHostname()
    */

    fputs("httpGetHostname(): ", stdout);

    if (httpGetHostname(NULL, hostname, sizeof(hostname)))
      printf("PASS (%s)\n", hostname);
    else
    {
      failures ++;
      puts("FAIL");
    }

   /*
    * httpAddrGetList()
    */

    printf("httpAddrGetList(%s): ", hostname);

    addrlist = httpAddrGetList(hostname, AF_UNSPEC, NULL);
    if (addrlist)
    {
      for (i = 0, addr = addrlist; addr; i ++, addr = addr->next)
      {
        char	numeric[1024];		/* Numeric IP address */


	httpAddrString(&(addr->addr), numeric, sizeof(numeric));
	if (!strcmp(numeric, "UNKNOWN"))
	  break;
      }

      if (addr)
        printf("FAIL (bad address for %s)\n", hostname);
      else
        printf("PASS (%d address(es) for %s)\n", i, hostname);

      httpAddrFreeList(addrlist);
    }
    else
    {
      failures ++;
      puts("FAIL");
    }

   /*
    * Test httpSeparateURI()...
    */

    fputs("httpSeparateURI(): ", stdout);
    for (i = 0, j = 0; i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0])); i ++)
    {
      uri_status = httpSeparateURI(HTTP_URI_CODING_MOST,
				   uri_tests[i].uri, scheme, sizeof(scheme),
                                   username, sizeof(username),
				   hostname, sizeof(hostname), &port,
				   resource, sizeof(resource));
      if (uri_status != uri_tests[i].result ||
          strcmp(scheme, uri_tests[i].scheme) ||
	  strcmp(username, uri_tests[i].username) ||
	  strcmp(hostname, uri_tests[i].hostname) ||
	  port != uri_tests[i].port ||
	  strcmp(resource, uri_tests[i].resource))
      {
        failures ++;

	if (!j)
	{
	  puts("FAIL");
	  j = 1;
	}

        printf("    \"%s\":\n", uri_tests[i].uri);

	if (uri_status != uri_tests[i].result)
	  printf("        Returned %s instead of %s\n",
	         uri_status_strings[uri_status + 8],
		 uri_status_strings[uri_tests[i].result + 8]);

        if (strcmp(scheme, uri_tests[i].scheme))
	  printf("        Scheme \"%s\" instead of \"%s\"\n",
	         scheme, uri_tests[i].scheme);

	if (strcmp(username, uri_tests[i].username))
	  printf("        Username \"%s\" instead of \"%s\"\n",
	         username, uri_tests[i].username);

	if (strcmp(hostname, uri_tests[i].hostname))
	  printf("        Hostname \"%s\" instead of \"%s\"\n",
	         hostname, uri_tests[i].hostname);

	if (port != uri_tests[i].port)
	  printf("        Port %d instead of %d\n",
	         port, uri_tests[i].port);

	if (strcmp(resource, uri_tests[i].resource))
	  printf("        Resource \"%s\" instead of \"%s\"\n",
	         resource, uri_tests[i].resource);
      }
    }

    if (!j)
      printf("PASS (%d URIs tested)\n",
             (int)(sizeof(uri_tests) / sizeof(uri_tests[0])));

   /*
    * Test httpAssembleURI()...
    */

    fputs("httpAssembleURI(): ", stdout);
    for (i = 0, j = 0, k = 0;
         i < (int)(sizeof(uri_tests) / sizeof(uri_tests[0]));
	 i ++)
      if (uri_tests[i].result == HTTP_URI_OK &&
          !strstr(uri_tests[i].uri, "%64") &&
          strstr(uri_tests[i].uri, "//"))
      {
        k ++;
	uri_status = httpAssembleURI(HTTP_URI_CODING_MOST,
				     buffer, sizeof(buffer),
	                             uri_tests[i].scheme,
				     uri_tests[i].username,
	                             uri_tests[i].hostname,
				     uri_tests[i].assemble_port,
				     uri_tests[i].resource);

        if (uri_status != HTTP_URI_OK)
	{
          failures ++;

	  if (!j)
	  {
	    puts("FAIL");
	    j = 1;
	  }

          printf("    \"%s\": %s\n", uri_tests[i].uri,
	         uri_status_strings[uri_status + 8]);
        }
	else if (strcmp(buffer, uri_tests[i].uri))
	{
          failures ++;

	  if (!j)
	  {
	    puts("FAIL");
	    j = 1;
	  }

          printf("    \"%s\": assembled = \"%s\"\n", uri_tests[i].uri,
	         buffer);
	}
      }

    if (!j)
      printf("PASS (%d URIs tested)\n", k);

   /*
    * Show a summary and return...
    */

    if (failures)
      printf("\n%d TESTS FAILED!\n", failures);
    else
      puts("\nALL TESTS PASSED!");

    return (failures);
  }

 /*
  * Test HTTP GET requests...
  */

  http = NULL;
  out = stdout;

  for (i = 1; i < argc; i ++)
  {
    if (!strcmp(argv[i], "-o"))
    {
      i ++;
      if (i >= argc)
        break;

      out = fopen(argv[i], "wb");
      continue;
    }

    httpSeparateURI(HTTP_URI_CODING_MOST, argv[i], scheme, sizeof(scheme),
                    username, sizeof(username),
                    hostname, sizeof(hostname), &port,
		    resource, sizeof(resource));

    http = httpConnectEncrypt(hostname, port, HTTP_ENCRYPT_IF_REQUESTED);
    if (http == NULL)
    {
      perror(hostname);
      continue;
    }
    printf("Requesting file \"%s\"...\n", resource);
    httpClearFields(http);
    httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en");
    httpGet(http, resource);
    while ((status = httpUpdate(http)) == HTTP_CONTINUE);

    if (status == HTTP_OK)
      puts("GET OK:");
    else
      printf("GET failed with status %d...\n", status);


    start  = time(NULL);
    length = httpGetLength2(http);
    total  = 0;

    while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
    {
      total += bytes;
      fwrite(buffer, bytes, 1, out);
      if (out != stdout)
      {
        current = time(NULL);
        if (current == start) current ++;
        printf("\r" CUPS_LLFMT "/" CUPS_LLFMT " bytes ("
	       CUPS_LLFMT " bytes/sec)      ", CUPS_LLCAST total,
	       CUPS_LLCAST length, CUPS_LLCAST (total / (current - start)));
        fflush(stdout);
      }
    }
  }

  puts("Closing connection to server...");
  httpClose(http);

  if (out != stdout)
    fclose(out);

  return (0);
}
Example #10
0
static http_status_t			/* O - Status of request */
get_cupsd_conf(
    http_t          *http,		/* I - Connection to server */
    _cups_globals_t *cg,		/* I - Global data */
    time_t          last_update,	/* I - Last update time for file */
    char            *name,		/* I - Filename buffer */
    size_t          namesize,		/* I - Size of filename buffer */
    int             *remote)		/* O - Remote file? */
{
  int		fd;			/* Temporary file descriptor */
#ifndef _WIN32
  struct stat	info;			/* cupsd.conf file information */
#endif /* _WIN32 */
  http_status_t	status;			/* Status of getting cupsd.conf */
  char		host[HTTP_MAX_HOST];	/* Hostname for connection */


 /*
  * See if we already have the data we need...
  */

  httpGetHostname(http, host, sizeof(host));

  if (_cups_strcasecmp(cg->cupsd_hostname, host))
    invalidate_cupsd_cache(cg);

  snprintf(name, namesize, "%s/cupsd.conf", cg->cups_serverroot);
  *remote = 0;

#ifndef _WIN32
  if (!_cups_strcasecmp(host, "localhost") && !access(name, R_OK))
  {
   /*
    * Read the local file rather than using HTTP...
    */

    if (stat(name, &info))
    {
      char	message[1024];		/* Message string */


      snprintf(message, sizeof(message),
               _cupsLangString(cupsLangDefault(), _("stat of %s failed: %s")),
               name, strerror(errno));
      _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0);

      *name = '\0';

      return (HTTP_STATUS_SERVER_ERROR);
    }
    else if (last_update && info.st_mtime <= last_update)
      status = HTTP_STATUS_NOT_MODIFIED;
    else
      status = HTTP_STATUS_OK;
  }
  else
#endif /* !_WIN32 */
  {
   /*
    * Read cupsd.conf via a HTTP GET request...
    */

    if ((fd = cupsTempFd(name, (int)namesize)) < 0)
    {
      *name = '\0';

      _cupsSetError(IPP_STATUS_ERROR_INTERNAL, NULL, 0);

      invalidate_cupsd_cache(cg);

      return (HTTP_STATUS_SERVER_ERROR);
    }

    *remote = 1;

    httpClearFields(http);

    if (last_update)
      httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE,
                   httpGetDateString(last_update));

    status = cupsGetFd(http, "/admin/conf/cupsd.conf", fd);

    close(fd);

    if (status != HTTP_STATUS_OK)
    {
      unlink(name);
      *name = '\0';
    }
  }

  return (status);
}
Example #11
0
int					/* O - 1 on success, 0 on failure */
serverFinalizeConfiguration(void)
{
  char			local[1024];	/* Local hostname */


 /*
  * Default hostname...
  */

  if (!ServerName && httpGetHostname(NULL, local, sizeof(local)))
    ServerName = strdup(local);

  if (!ServerName)
    ServerName = strdup("localhost");

#ifdef HAVE_SSL
 /*
  * Setup TLS certificate for server...
  */

  cupsSetServerCredentials(KeychainPath, ServerName, 1);
#endif /* HAVE_SSL */

 /*
  * Default directories...
  */

  if (!DataDirectory)
  {
    char	directory[1024];	/* New directory */
    const char	*tmpdir;		/* Temporary directory */

#ifdef WIN32
    if ((tmpdir = getenv("TEMP")) == NULL)
      tmpdir = "C:/TEMP";
#elif defined(__APPLE__)
    if ((tmpdir = getenv("TMPDIR")) == NULL)
      tmpdir = "/private/tmp";
#else
    if ((tmpdir = getenv("TMPDIR")) == NULL)
      tmpdir = "/tmp";
#endif /* WIN32 */

    snprintf(directory, sizeof(directory), "%s/ippserver.%d", tmpdir, (int)getpid());

    if (mkdir(directory, 0755) && errno != EEXIST)
    {
      serverLog(SERVER_LOGLEVEL_ERROR, "Unable to create default data directory \"%s\": %s", directory, strerror(errno));
      return (0);
    }

    serverLog(SERVER_LOGLEVEL_INFO, "Using default data directory \"%s\".", directory);

    DataDirectory = strdup(directory);
  }

  if (!SpoolDirectory)
  {
    SpoolDirectory = strdup(DataDirectory);

    serverLog(SERVER_LOGLEVEL_INFO, "Using default spool directory \"%s\".", DataDirectory);
  }

 /*
  * Initialize Bonjour...
  */

  serverDNSSDInit();

 /*
  * Apply default listeners if none are specified...
  */

  if (!Listeners)
  {
#ifdef WIN32
   /*
    * Windows is almost always used as a single user system, so use a default port
    * number of 8631.
    */

    if (!DefaultPort)
      DefaultPort = 8631;

#else
   /*
    * Use 8000 + UID mod 1000 for the default port number...
    */

    if (!DefaultPort)
      DefaultPort = 8000 + ((int)getuid() % 1000);
#endif /* WIN32 */

    serverLog(SERVER_LOGLEVEL_INFO, "Using default listeners for %s:%d.", ServerName, DefaultPort);

    if (!serverCreateListeners(strcmp(ServerName, "localhost") ? NULL : "localhost", DefaultPort))
      return (0);
  }

  return (1);
}
Example #12
0
int
main(int  argc,				/* I - Number of command-line arguments */
     char *argv[])			/* I - Command-line arguments */
{
  int		i, j;			/* Looping var */
  int		job_id;			/* Job ID */
  char		ch;			/* Option character */
  char		*printer,		/* Destination printer or class */
		*instance;		/* Instance */
  const char	*title,			/* Job title */
		*val;			/* Environment variable name */
  int		num_copies;		/* Number of copies per file */
  int		num_files;		/* Number of files to print */
  const char	*files[1000];		/* Files to print */
  cups_dest_t	*dest;			/* Selected destination */
  int		num_options;		/* Number of options */
  cups_option_t	*options;		/* Options */
  int		deletefile;		/* Delete file after print? */
  char		buffer[8192];		/* Copy buffer */


  _cupsSetLocale(argv);

  deletefile  = 0;
  printer     = NULL;
  dest        = NULL;
  num_options = 0;
  options     = NULL;
  num_files   = 0;
  title       = NULL;

  for (i = 1; i < argc; i ++)
    if (argv[i][0] == '-')
      switch (ch = argv[i][1])
      {
        case 'E' : /* Encrypt */
#ifdef HAVE_SSL
	    cupsSetEncryption(HTTP_ENCRYPT_REQUIRED);
#else
            _cupsLangPrintf(stderr, _("%s: Sorry, no encryption support."),
	                    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."), argv[0]);
	        return (1);
	      }

              cupsSetUser(argv[i]);
	    }
	    break;

        case 'H' : /* Connect to host */
	    if (argv[i][2] != '\0')
              cupsSetServer(argv[i] + 2);
	    else
	    {
	      i ++;

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

	case '1' : /* TROFF font set 1 */
	case '2' : /* TROFF font set 2 */
	case '3' : /* TROFF font set 3 */
	case '4' : /* TROFF font set 4 */
	case 'i' : /* indent */
	case 'w' : /* width */
	    if (argv[i][2] == '\0')
	    {
	      i ++;

	      if (i >= argc)
	      {
		_cupsLangPrintf(stderr,
		                _("%s: Error - expected value after \"-%c\" "
				  "option."), argv[0], ch);
		return (1);
	      }
	    }

        case 'c' : /* CIFPLOT */
	case 'd' : /* DVI */
	case 'f' : /* FORTRAN */
	case 'g' : /* plot */
	case 'n' : /* Ditroff */
	case 't' : /* Troff */
	case 'v' : /* Raster image */
	    _cupsLangPrintf(stderr,
	                    _("%s: Warning - \"%c\" format modifier not "
			      "supported - output may not be correct."),
			    argv[0], ch);
	    break;

	case 'o' : /* Option */
	    if (argv[i][2] != '\0')
	      num_options = cupsParseOptions(argv[i] + 2, num_options, &options);
	    else
	    {
	      i ++;
	      if (i >= argc)
	      {
	        _cupsLangPrintf(stderr,
		                _("%s: Error - expected option=value after "
			          "\"-o\" option."), argv[0]);
		return (1);
	      }

	      num_options = cupsParseOptions(argv[i], num_options, &options);
	    }
	    break;

	case 'l' : /* Literal/raw */
            num_options = cupsAddOption("raw", "true", num_options, &options);
	    break;

	case 'p' : /* Prettyprint */
            num_options = cupsAddOption("prettyprint", "true", num_options,
	                                &options);
	    break;

	case 'h' : /* Suppress burst page */
            num_options = cupsAddOption("job-sheets", "none", num_options,
	                                &options);
	    break;

	case 's' : /* Don't use symlinks */
	    break;

	case 'm' : /* Mail on completion */
	    {
	      char	email[1024];	/* EMail address */


	      snprintf(email, sizeof(email), "mailto:%s@%s", cupsUser(),
	               httpGetHostname(NULL, buffer, sizeof(buffer)));
	      num_options = cupsAddOption("notify-recipient-uri", email,
	                                  num_options, &options);
	    }
	    break;

	case 'q' : /* Queue file but don't print */
            num_options = cupsAddOption("job-hold-until", "indefinite",
	                                num_options, &options);
	    break;

	case 'r' : /* Remove file after printing */
	    deletefile = 1;
	    break;

        case 'P' : /* Destination printer or class */
	    if (argv[i][2] != '\0')
	      printer = argv[i] + 2;
	    else
	    {
	      i ++;
	      if (i >= argc)
	      {
	        _cupsLangPrintf(stderr,
		        	_("%s: Error - expected destination after "
			          "\"-P\" option."), argv[0]);
		return (1);
	      }

	      printer = argv[i];
	    }

            if ((instance = strrchr(printer, '/')) != NULL)
	      *instance++ = '\0';

            if ((dest = cupsGetNamedDest(NULL, printer, instance)) != NULL)
	    {
	      for (j = 0; j < dest->num_options; j ++)
	        if (cupsGetOption(dest->options[j].name, num_options,
		                  options) == NULL)
	          num_options = cupsAddOption(dest->options[j].name,
		                              dest->options[j].value,
					      num_options, &options);
	    }
	    break;

	case '#' : /* Number of copies */
	    if (argv[i][2] != '\0')
	      num_copies = atoi(argv[i] + 2);
	    else
	    {
	      i ++;
	      if (i >= argc)
	      {
	        _cupsLangPrintf(stderr,
		        	_("%s: Error - expected copies after "
			          "\"-#\" option."), argv[0]);
		return (1);
	      }

	      num_copies = atoi(argv[i]);
	    }

            sprintf(buffer, "%d", num_copies);
            num_options = cupsAddOption("copies", buffer, num_options, &options);
	    break;

	case 'C' : /* Class */
	case 'J' : /* Job name */
	case 'T' : /* Title */
	    if (argv[i][2] != '\0')
	      title = argv[i] + 2;
	    else
	    {
	      i ++;
	      if (i >= argc)
	      {
		_cupsLangPrintf(stderr,
		                _("%s: Error - expected name after \"-%c\" "
				  "option."), argv[0], ch);
		return (1);
	      }

	      title = argv[i];
	    }
	    break;

	default :
	    _cupsLangPrintf(stderr,
	                    _("%s: Error - unknown option \"%c\"."), argv[0],
			    argv[i][1]);
	    return (1);
      }
    else if (num_files < 1000)
    {
     /*
      * Print a file...
      */

      if (access(argv[i], R_OK) != 0)
      {
        _cupsLangPrintf(stderr,
	                _("%s: Error - unable to access \"%s\" - %s"),
		        argv[0], argv[i], strerror(errno));
        return (1);
      }

      files[num_files] = argv[i];
      num_files ++;

      if (title == NULL)
      {
        if ((title = strrchr(argv[i], '/')) != NULL)
	  title ++;
	else
          title = argv[i];
      }
    }
    else
      _cupsLangPrintf(stderr,
                      _("%s: Error - too many files - \"%s\"."), argv[0],
		      argv[i]);
 /*
  * See if we have any files to print; if not, print from stdin...
  */

  if (printer == NULL)
  {
    if ((dest = cupsGetNamedDest(NULL, NULL, NULL)) != NULL)
    {
      printer = dest->name;

      for (j = 0; j < dest->num_options; j ++)
	if (cupsGetOption(dest->options[j].name, num_options, options) == NULL)
	  num_options = cupsAddOption(dest->options[j].name,
		                      dest->options[j].value,
				      num_options, &options);
    }
  }

  if (printer == NULL)
  {
    val = NULL;

    if ((printer = getenv("LPDEST")) == NULL)
    {
      if ((printer = getenv("PRINTER")) != NULL)
      {
        if (!strcmp(printer, "lp"))
          printer = NULL;
	else
	  val = "PRINTER";
      }
    }
    else
      val = "LPDEST";

    if (printer && !cupsGetNamedDest(NULL, printer, NULL))
      _cupsLangPrintf(stderr,
                      _("%s: Error - %s environment variable names "
		        "non-existent destination \"%s\"."), argv[0], val,
		      printer);
    else if (cupsLastError() == IPP_NOT_FOUND)
      _cupsLangPrintf(stderr,
                      _("%s: Error - no default destination available."),
		      argv[0]);
    else
      _cupsLangPrintf(stderr, _("%s: Error - scheduler not responding."),
		      argv[0]);

    return (1);
  }

  if (num_files > 0)
  {
    job_id = cupsPrintFiles(printer, num_files, files, title, num_options, options);

    if (deletefile && job_id > 0)
    {
     /*
      * Delete print files after printing...
      */

      for (i = 0; i < num_files; i ++)
        unlink(files[i]);
    }
  }
  else if ((job_id = cupsCreateJob(CUPS_HTTP_DEFAULT, printer,
                                   title ? title : "(stdin)",
                                   num_options, options)) > 0)
  {
    http_status_t	status;		/* Write status */
    const char		*format;	/* Document format */
    ssize_t		bytes;		/* Bytes read */

    if (cupsGetOption("raw", num_options, options))
      format = CUPS_FORMAT_RAW;
    else if ((format = cupsGetOption("document-format", num_options,
                                     options)) == NULL)
      format = CUPS_FORMAT_AUTO;

    status = cupsStartDocument(CUPS_HTTP_DEFAULT, printer, job_id, NULL,
                               format, 1);

    while (status == HTTP_CONTINUE &&
           (bytes = read(0, buffer, sizeof(buffer))) > 0)
      status = cupsWriteRequestData(CUPS_HTTP_DEFAULT, buffer, bytes);

    if (status != HTTP_CONTINUE)
    {
      _cupsLangPrintf(stderr, _("%s: Error - unable to queue from stdin - %s."),
		      argv[0], httpStatus(status));
      cupsFinishDocument(CUPS_HTTP_DEFAULT, printer);
      cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0);
      return (1);
    }

    if (cupsFinishDocument(CUPS_HTTP_DEFAULT, printer) != IPP_OK)
    {
      _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString());
      cupsCancelJob2(CUPS_HTTP_DEFAULT, printer, job_id, 0);
      return (1);
    }
  }

  if (job_id < 1)
  {
    _cupsLangPrintf(stderr, "%s: %s", argv[0], cupsLastErrorString());
    return (1);
  }

  return (0);
}
Example #13
0
int					/* I - 1 on success, 0 on failure */
load_configuration(void)
{
  cups_file_t	*fp;			/* mailto.conf file */
  const char	*server_root,		/* CUPS_SERVERROOT environment variable */
		*server_admin;		/* SERVER_ADMIN environment variable */
  char		line[1024],		/* Line from file */
		*value;			/* Value for directive */
  int		linenum;		/* Line number in file */


 /*
  * Initialize defaults...
  */

  mailtoCc[0] = '\0';

  if ((server_admin = getenv("SERVER_ADMIN")) != NULL)
    strlcpy(mailtoFrom, server_admin, sizeof(mailtoFrom));
  else
    snprintf(mailtoFrom, sizeof(mailtoFrom), "root@%s",
             httpGetHostname(NULL, line, sizeof(line)));

  strlcpy(mailtoSendmail, "/usr/sbin/sendmail", sizeof(mailtoSendmail));

  mailtoSMTPServer[0] = '\0';

  mailtoSubject[0] = '\0';

 /*
  * Try loading the config file...
  */

  if ((server_root = getenv("CUPS_SERVERROOT")) == NULL)
    server_root = CUPS_SERVERROOT;

  snprintf(line, sizeof(line), "%s/mailto.conf", server_root);

  if ((fp = cupsFileOpen(line, "r")) == NULL)
  {
    fprintf(stderr, "ERROR: Unable to open \"%s\" - %s\n", line,
            strerror(errno));
    return (1);
  }

  linenum = 0;

  while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum))
  {
    if (!value)
    {
      fprintf(stderr, "ERROR: No value found for %s directive on line %d!\n",
              line, linenum);
      cupsFileClose(fp);
      return (0);
    }

    if (!strcasecmp(line, "Cc"))
      strlcpy(mailtoCc, value, sizeof(mailtoCc));
    else if (!strcasecmp(line, "From"))
      strlcpy(mailtoFrom, value, sizeof(mailtoFrom));
    else if (!strcasecmp(line, "Sendmail"))
    {
      strlcpy(mailtoSendmail, value, sizeof(mailtoSendmail));
      mailtoSMTPServer[0] = '\0';
    }
    else if (!strcasecmp(line, "SMTPServer"))
    {
      mailtoSendmail[0] = '\0';
      strlcpy(mailtoSMTPServer, value, sizeof(mailtoSMTPServer));
    }
    else if (!strcasecmp(line, "Subject"))
      strlcpy(mailtoSubject, value, sizeof(mailtoSubject));
    else
    {
      fprintf(stderr,
              "ERROR: Unknown configuration directive \"%s\" on line %d!\n",
              line, linenum);
    }
  }

 /*
  * Close file and return...
  */

  cupsFileClose(fp);

  return (1);
}
Example #14
0
const char *				/* O - Filename for PPD file */
cupsGetPPD2(http_t     *http,		/* I - HTTP connection */
            const char *name)		/* I - Printer name */
{
    int		http_port;		/* Port number */
    char		http_hostname[HTTP_MAX_HOST];
    /* Hostname associated with connection */
    http_t	*http2;			/* Alternate HTTP connection */
    int		fd;			/* PPD file */
    char		localhost[HTTP_MAX_URI],/* Local hostname */
                hostname[HTTP_MAX_URI],	/* Hostname */
                resource[HTTP_MAX_URI];	/* Resource name */
    int		port;			/* Port number */
    http_status_t	status;			/* HTTP status from server */
    _cups_globals_t *cg = _cupsGlobals();	/* Pointer to library globals */


    /*
     * Range check input...
     */

    DEBUG_printf(("cupsGetPPD2(http=%p, name=\"%s\")\n", http,
                  name ? name : "(null)"));

    if (!http || !name)
    {
        if (!http)
            _cupsSetError(IPP_INTERNAL_ERROR, "No HTTP connection!");
        else
            _cupsSetError(IPP_INTERNAL_ERROR, "No printer name!");

        return (NULL);
    }

    /*
     * Try finding a printer URI for this printer...
     */

    if (!cups_get_printer_uri(http, name, hostname, sizeof(hostname), &port,
                              resource, sizeof(resource), 0))
        return (NULL);

    DEBUG_printf(("cupsGetPPD3: Printer hostname=\"%s\", port=%d\n", hostname, port));

    /*
     * Remap local hostname to localhost...
     */

    httpGetHostname(NULL, localhost, sizeof(localhost));

    DEBUG_printf(("Local hostname=\"%s\"\n", localhost));

    if (!strcasecmp(localhost, hostname))
        strcpy(hostname, "localhost");

    /*
     * Get the hostname and port number we are connected to...
     */

    httpGetHostname(http, http_hostname, sizeof(http_hostname));

#ifdef AF_INET6
    if (http->hostaddr->addr.sa_family == AF_INET6)
        http_port = ntohs(http->hostaddr->ipv6.sin6_port);
    else
#endif /* AF_INET6 */
        if (http->hostaddr->addr.sa_family == AF_INET)
            http_port = ntohs(http->hostaddr->ipv4.sin_port);
        else
            http_port = ippPort();

    DEBUG_printf(("Connection hostname=\"%s\", port=%d\n", http_hostname,
                  http_port));

    /*
     * Reconnect to the correct server as needed...
     */

    if (!strcasecmp(http_hostname, hostname) && port == http_port)
        http2 = http;
    else if ((http2 = httpConnectEncrypt(hostname, port,
                                         cupsEncryption())) == NULL)
    {
        DEBUG_puts("Unable to connect to server!");

        return (NULL);
    }

    /*
     * Get a temp file...
     */

    if ((fd = cupsTempFd(cg->ppd_filename, sizeof(cg->ppd_filename))) < 0)
    {
        /*
         * Can't open file; close the server connection and return NULL...
         */

        _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno));

        if (http2 != http)
            httpClose(http2);

        return (NULL);
    }

    /*
     * And send a request to the HTTP server...
     */

    strlcat(resource, ".ppd", sizeof(resource));

    status = cupsGetFd(http2, resource, fd);

    close(fd);

    /*
     * See if we actually got the file or an error...
     */

    if (status != HTTP_OK)
    {
        switch (status)
        {
        case HTTP_NOT_FOUND :
            _cupsSetError(IPP_NOT_FOUND, httpStatus(status));
            break;

        case HTTP_UNAUTHORIZED :
            _cupsSetError(IPP_NOT_AUTHORIZED, httpStatus(status));
            break;

        default :
            DEBUG_printf(("HTTP error %d mapped to IPP_SERVICE_UNAVAILABLE!\n",
                          status));
            _cupsSetError(IPP_SERVICE_UNAVAILABLE, httpStatus(status));
            break;
        }

        unlink(cg->ppd_filename);

        return (NULL);
    }

    if (http2 != http)
        httpClose(http2);

    /*
     * Return the PPD file...
     */

    return (cg->ppd_filename);
}
Example #15
0
int					/* O - 1 on success, 0 on failure */
cupsAdminGetServerSettings(
    http_t        *http,		/* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
    int           *num_settings,	/* O - Number of settings */
    cups_option_t **settings)		/* O - Settings */
{
  int		i;			/* Looping var */
  cups_file_t	*cupsd;			/* cupsd.conf file */
  char		cupsdconf[1024];	/* cupsd.conf filename */
  int		remote;			/* Remote cupsd.conf file? */
  http_status_t	status;			/* Status of getting cupsd.conf */
  char		line[1024],		/* Line from cupsd.conf file */
		*value;			/* Value on line */
  cups_option_t	*setting;		/* Current setting */
  _cups_globals_t *cg = _cupsGlobals();	/* Global data */


 /*
  * Range check input...
  */

  if (!http)
  {
   /*
    * See if we are connected to the same server...
    */

    if (cg->http)
    {
     /*
      * Compare the connection hostname, port, and encryption settings to
      * the cached defaults; these were initialized the first time we
      * connected...
      */

      if (strcmp(cg->http->hostname, cg->server) ||
          cg->ipp_port != httpAddrPort(cg->http->hostaddr) ||
	  (cg->http->encryption != cg->encryption &&
	   cg->http->encryption == HTTP_ENCRYPTION_NEVER))
      {
       /*
	* Need to close the current connection because something has changed...
	*/

	httpClose(cg->http);
	cg->http = NULL;
      }
    }

   /*
    * (Re)connect as needed...
    */

    if (!cg->http)
    {
      if ((cg->http = httpConnect2(cupsServer(), ippPort(), NULL, AF_UNSPEC,
                                   cupsEncryption(), 1, 0, NULL)) == NULL)
      {
	if (errno)
	  _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, NULL, 0);
	else
	  _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE,
			_("Unable to connect to host."), 1);

	if (num_settings)
	  *num_settings = 0;

	if (settings)
	  *settings = NULL;

	return (0);
      }
    }

    http = cg->http;
  }

  if (!http || !num_settings || !settings)
  {
    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);

    if (num_settings)
      *num_settings = 0;

    if (settings)
      *settings = NULL;

    return (0);
  }

  *num_settings = 0;
  *settings     = NULL;

 /*
  * Get the cupsd.conf file...
  */

  if ((status = get_cupsd_conf(http, cg, cg->cupsd_update, cupsdconf,
                               sizeof(cupsdconf), &remote)) == HTTP_STATUS_OK)
  {
    if ((cupsd = cupsFileOpen(cupsdconf, "r")) == NULL)
    {
      char	message[1024];		/* Message string */


      snprintf(message, sizeof(message),
               _cupsLangString(cupsLangDefault(), _("Open of %s failed: %s")),
               cupsdconf, strerror(errno));
      _cupsSetError(IPP_STATUS_ERROR_INTERNAL, message, 0);
    }
  }
  else
    cupsd = NULL;

  if (cupsd)
  {
   /*
    * Read the file, keeping track of what settings are enabled...
    */

    int		remote_access = 0,	/* Remote access allowed? */
		remote_admin = 0,	/* Remote administration allowed? */
		remote_any = 0,		/* Remote access from anywhere allowed? */
		browsing = 1,		/* Browsing enabled? */
		cancel_policy = 1,	/* Cancel-job policy set? */
		debug_logging = 0;	/* LogLevel debug set? */
    int		linenum = 0,		/* Line number in file */
		in_location = 0,	/* In a location section? */
		in_policy = 0,		/* In a policy section? */
		in_cancel_job = 0,	/* In a cancel-job section? */
		in_admin_location = 0;	/* In the /admin location? */


    invalidate_cupsd_cache(cg);

    cg->cupsd_update = time(NULL);
    httpGetHostname(http, cg->cupsd_hostname, sizeof(cg->cupsd_hostname));

    while (cupsFileGetConf(cupsd, line, sizeof(line), &value, &linenum))
    {
      if (!value && strncmp(line, "</", 2))
        value = line + strlen(line);

      if ((!_cups_strcasecmp(line, "Port") || !_cups_strcasecmp(line, "Listen")) && value)
      {
	char	*port;			/* Pointer to port number, if any */


	if ((port = strrchr(value, ':')) != NULL)
	  *port = '\0';
	else if (isdigit(*value & 255))
	{
	 /*
	  * Listen on a port number implies remote access...
	  */

	  remote_access = 1;
	  continue;
	}

	if (_cups_strcasecmp(value, "localhost") && strcmp(value, "127.0.0.1")
#ifdef AF_LOCAL
            && *value != '/'
#endif /* AF_LOCAL */
#ifdef AF_INET6
            && strcmp(value, "[::1]")
#endif /* AF_INET6 */
	    )
	  remote_access = 1;
      }
      else if (!_cups_strcasecmp(line, "Browsing"))
      {
	browsing = !_cups_strcasecmp(value, "yes") ||
	           !_cups_strcasecmp(value, "on") ||
	           !_cups_strcasecmp(value, "true");
      }
      else if (!_cups_strcasecmp(line, "LogLevel"))
      {
	debug_logging = !_cups_strncasecmp(value, "debug", 5);
      }
      else if (!_cups_strcasecmp(line, "<Policy") &&
               !_cups_strcasecmp(value, "default"))
      {
	in_policy = 1;
      }
      else if (!_cups_strcasecmp(line, "</Policy>"))
      {
	in_policy = 0;
      }
      else if (!_cups_strcasecmp(line, "<Limit") && in_policy && value)
      {
       /*
	* See if the policy limit is for the Cancel-Job operation...
	*/

	char	*valptr;		/* Pointer into value */


	while (*value)
	{
	  for (valptr = value; *valptr && !_cups_isspace(*valptr); valptr ++);

	  if (*valptr)
	    *valptr++ = '\0';

          if (!_cups_strcasecmp(value, "cancel-job") ||
              !_cups_strcasecmp(value, "all"))
	  {
	    in_cancel_job = 1;
	    break;
	  }

          for (value = valptr; _cups_isspace(*value); value ++);
	}
      }
      else if (!_cups_strcasecmp(line, "</Limit>"))
      {
	in_cancel_job = 0;
      }
      else if (!_cups_strcasecmp(line, "Require") && in_cancel_job)
      {
	cancel_policy = 0;
      }
      else if (!_cups_strcasecmp(line, "<Location") && value)
      {
        in_admin_location = !_cups_strcasecmp(value, "/admin");
	in_location       = 1;
      }
      else if (!_cups_strcasecmp(line, "</Location>"))
      {
	in_admin_location = 0;
	in_location       = 0;
      }
      else if (!_cups_strcasecmp(line, "Allow") && value &&
               _cups_strcasecmp(value, "localhost") &&
               _cups_strcasecmp(value, "127.0.0.1")
#ifdef AF_LOCAL
	       && *value != '/'
#endif /* AF_LOCAL */
#ifdef AF_INET6
	       && strcmp(value, "::1")
#endif /* AF_INET6 */
	       )
      {
        if (in_admin_location)
	  remote_admin = 1;
        else if (!_cups_strcasecmp(value, "all"))
	  remote_any = 1;
      }
      else if (line[0] != '<' && !in_location && !in_policy &&
	       _cups_strcasecmp(line, "Allow") &&
               _cups_strcasecmp(line, "AuthType") &&
	       _cups_strcasecmp(line, "Deny") &&
	       _cups_strcasecmp(line, "Order") &&
	       _cups_strcasecmp(line, "Require") &&
	       _cups_strcasecmp(line, "Satisfy"))
        cg->cupsd_num_settings = cupsAddOption(line, value,
	                                       cg->cupsd_num_settings,
					       &(cg->cupsd_settings));
    }

    cupsFileClose(cupsd);

    cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_DEBUG_LOGGING,
                                           debug_logging ? "1" : "0",
					   cg->cupsd_num_settings,
					   &(cg->cupsd_settings));

    cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ADMIN,
                                           (remote_access && remote_admin) ?
					       "1" : "0",
					   cg->cupsd_num_settings,
					   &(cg->cupsd_settings));

    cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_REMOTE_ANY,
                                           remote_any ? "1" : "0",
					   cg->cupsd_num_settings,
					   &(cg->cupsd_settings));

    cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_SHARE_PRINTERS,
                                           (remote_access && browsing) ? "1" :
                                                                         "0",
					   cg->cupsd_num_settings,
					   &(cg->cupsd_settings));

    cg->cupsd_num_settings = cupsAddOption(CUPS_SERVER_USER_CANCEL_ANY,
                                           cancel_policy ? "1" : "0",
					   cg->cupsd_num_settings,
					   &(cg->cupsd_settings));
  }
  else if (status != HTTP_STATUS_NOT_MODIFIED)
    invalidate_cupsd_cache(cg);

 /*
  * Remove any temporary files and copy the settings array...
  */

  if (remote)
    unlink(cupsdconf);

  for (i = cg->cupsd_num_settings, setting = cg->cupsd_settings;
       i > 0;
       i --, setting ++)
    *num_settings = cupsAddOption(setting->name, setting->value,
                                  *num_settings, settings);

  return (cg->cupsd_num_settings > 0);
}
Example #16
0
static gss_name_t			/* O - Server name */
cups_gss_getname(
    http_t     *http,			/* I - Connection to server */
    const char *service_name)		/* I - Service name */
{
  gss_buffer_desc token = GSS_C_EMPTY_BUFFER;
					/* Service token */
  OM_uint32	  major_status,		/* Major status code */
		  minor_status;		/* Minor status code */
  gss_name_t	  server_name;		/* Server name */
  char		  buf[1024];		/* Name buffer */


  DEBUG_printf(("7cups_gss_getname(http=%p, service_name=\"%s\")", http,
                service_name));


 /*
  * Get the hostname...
  */

  if (!http->gsshost[0])
  {
    httpGetHostname(http, http->gsshost, sizeof(http->gsshost));

    if (!strcmp(http->gsshost, "localhost"))
    {
      if (gethostname(http->gsshost, sizeof(http->gsshost)) < 0)
      {
	DEBUG_printf(("1cups_gss_getname: gethostname() failed: %s",
		      strerror(errno)));
	http->gsshost[0] = '\0';
	return (NULL);
      }

      if (!strchr(http->gsshost, '.'))
      {
       /*
	* The hostname is not a FQDN, so look it up...
	*/

	struct hostent	*host;		/* Host entry to get FQDN */

	if ((host = gethostbyname(http->gsshost)) != NULL && host->h_name)
	{
	 /*
	  * Use the resolved hostname...
	  */

	  strlcpy(http->gsshost, host->h_name, sizeof(http->gsshost));
	}
	else
	{
	  DEBUG_printf(("1cups_gss_getname: gethostbyname(\"%s\") failed.",
			http->gsshost));
	  http->gsshost[0] = '\0';
	  return (NULL);
	}
      }
    }
  }

 /*
  * Get a service name we can use for authentication purposes...
  */

  snprintf(buf, sizeof(buf), "%s@%s", service_name, http->gsshost);

  DEBUG_printf(("8cups_gss_getname: Looking up \"%s\".", buf));

  token.value  = buf;
  token.length = strlen(buf);
  server_name  = GSS_C_NO_NAME;
  major_status = gss_import_name(&minor_status, &token,
	 			 GSS_C_NT_HOSTBASED_SERVICE,
				 &server_name);

  if (GSS_ERROR(major_status))
  {
    cups_gss_printf(major_status, minor_status,
                    "cups_gss_getname: gss_import_name() failed");
    return (NULL);
  }

  return (server_name);
}
Example #17
0
http_status_t				/* O  - HTTP status */
cupsGetPPD3(http_t     *http,		/* I  - HTTP connection or @code CUPS_HTTP_DEFAULT@ */
            const char *name,		/* I  - Destination name */
	    time_t     *modtime,	/* IO - Modification time */
	    char       *buffer,		/* I  - Filename buffer */
	    size_t     bufsize)		/* I  - Size of filename buffer */
{
  int		http_port;		/* Port number */
  char		http_hostname[HTTP_MAX_HOST];
					/* Hostname associated with connection */
  http_t	*http2;			/* Alternate HTTP connection */
  int		fd;			/* PPD file */
  char		localhost[HTTP_MAX_URI],/* Local hostname */
		hostname[HTTP_MAX_URI],	/* Hostname */
		resource[HTTP_MAX_URI];	/* Resource name */
  int		port;			/* Port number */
  http_status_t	status;			/* HTTP status from server */
  char		tempfile[1024] = "";	/* Temporary filename */
  _cups_globals_t *cg = _cupsGlobals();	/* Pointer to library globals */


 /*
  * Range check input...
  */

  DEBUG_printf(("cupsGetPPD3(http=%p, name=\"%s\", modtime=%p(%d), buffer=%p, "
                "bufsize=%d)", http, name, modtime,
		modtime ? (int)*modtime : 0, buffer, (int)bufsize));

  if (!name)
  {
    _cupsSetError(IPP_INTERNAL_ERROR, _("No printer name"), 1);
    return (HTTP_NOT_ACCEPTABLE);
  }

  if (!modtime)
  {
    _cupsSetError(IPP_INTERNAL_ERROR, _("No modification time"), 1);
    return (HTTP_NOT_ACCEPTABLE);
  }

  if (!buffer || bufsize <= 1)
  {
    _cupsSetError(IPP_INTERNAL_ERROR, _("Bad filename buffer"), 1);
    return (HTTP_NOT_ACCEPTABLE);
  }

#ifndef WIN32
 /*
  * See if the PPD file is available locally...
  */

  if (!cg->servername[0])
    cupsServer();

  if (!_cups_strcasecmp(cg->servername, "localhost"))
  {
    char	ppdname[1024];		/* PPD filename */
    struct stat	ppdinfo;		/* PPD file information */


    snprintf(ppdname, sizeof(ppdname), "%s/ppd/%s.ppd", cg->cups_serverroot,
             name);
    if (!stat(ppdname, &ppdinfo))
    {
     /*
      * OK, the file exists, use it!
      */

      if (buffer[0])
      {
        unlink(buffer);

	if (symlink(ppdname, buffer) && errno != EEXIST)
        {
          _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);

	  return (HTTP_SERVER_ERROR);
	}
      }
      else
      {
        int		tries;		/* Number of tries */
        const char	*tmpdir;	/* TMPDIR environment variable */
	struct timeval	curtime;	/* Current time */

       /*
	* Previously we put root temporary files in the default CUPS temporary
	* directory under /var/spool/cups.  However, since the scheduler cleans
	* out temporary files there and runs independently of the user apps, we
	* don't want to use it unless specifically told to by cupsd.
	*/

	if ((tmpdir = getenv("TMPDIR")) == NULL)
#  ifdef __APPLE__
	  tmpdir = "/private/tmp";	/* /tmp is a symlink to /private/tmp */
#  else
          tmpdir = "/tmp";
#  endif /* __APPLE__ */

       /*
	* Make the temporary name using the specified directory...
	*/

	tries = 0;

	do
	{
	 /*
	  * Get the current time of day...
	  */

	  gettimeofday(&curtime, NULL);

	 /*
	  * Format a string using the hex time values...
	  */

	  snprintf(buffer, bufsize, "%s/%08lx%05lx", tmpdir,
		   (unsigned long)curtime.tv_sec,
		   (unsigned long)curtime.tv_usec);

	 /*
	  * Try to make a symlink...
	  */

	  if (!symlink(ppdname, buffer))
	    break;

	  tries ++;
	}
	while (tries < 1000);

        if (tries >= 1000)
	{
          _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);

	  return (HTTP_SERVER_ERROR);
	}
      }

      if (*modtime >= ppdinfo.st_mtime)
        return (HTTP_NOT_MODIFIED);
      else
      {
        *modtime = ppdinfo.st_mtime;
	return (HTTP_OK);
      }
    }
  }
#endif /* !WIN32 */

 /*
  * Try finding a printer URI for this printer...
  */

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

  if (!cups_get_printer_uri(http, name, hostname, sizeof(hostname), &port,
                            resource, sizeof(resource), 0))
    return (HTTP_NOT_FOUND);

  DEBUG_printf(("2cupsGetPPD3: Printer hostname=\"%s\", port=%d", hostname,
                port));

 /*
  * Remap local hostname to localhost...
  */

  httpGetHostname(NULL, localhost, sizeof(localhost));

  DEBUG_printf(("2cupsGetPPD3: Local hostname=\"%s\"", localhost));

  if (!_cups_strcasecmp(localhost, hostname))
    strcpy(hostname, "localhost");

 /*
  * Get the hostname and port number we are connected to...
  */

  httpGetHostname(http, http_hostname, sizeof(http_hostname));
  http_port = _httpAddrPort(http->hostaddr);

  DEBUG_printf(("2cupsGetPPD3: Connection hostname=\"%s\", port=%d",
                http_hostname, http_port));

 /*
  * Reconnect to the correct server as needed...
  */

  if (!_cups_strcasecmp(http_hostname, hostname) && port == http_port)
    http2 = http;
  else if ((http2 = httpConnectEncrypt(hostname, port,
                                       cupsEncryption())) == NULL)
  {
    DEBUG_puts("1cupsGetPPD3: Unable to connect to server");

    return (HTTP_SERVICE_UNAVAILABLE);
  }

 /*
  * Get a temp file...
  */

  if (buffer[0])
    fd = open(buffer, O_CREAT | O_TRUNC | O_WRONLY, 0600);
  else
    fd = cupsTempFd(tempfile, sizeof(tempfile));

  if (fd < 0)
  {
   /*
    * Can't open file; close the server connection and return NULL...
    */

    _cupsSetError(IPP_INTERNAL_ERROR, NULL, 0);

    if (http2 != http)
      httpClose(http2);

    return (HTTP_SERVER_ERROR);
  }

 /*
  * And send a request to the HTTP server...
  */

  strlcat(resource, ".ppd", sizeof(resource));

  if (*modtime > 0)
    httpSetField(http2, HTTP_FIELD_IF_MODIFIED_SINCE,
                 httpGetDateString(*modtime));

  status = cupsGetFd(http2, resource, fd);

  close(fd);

 /*
  * See if we actually got the file or an error...
  */

  if (status == HTTP_OK)
  {
    *modtime = httpGetDateTime(httpGetField(http2, HTTP_FIELD_DATE));

    if (tempfile[0])
      strlcpy(buffer, tempfile, bufsize);
  }
  else if (status != HTTP_NOT_MODIFIED)
  {
    _cupsSetHTTPError(status);

    if (buffer[0])
      unlink(buffer);
    else if (tempfile[0])
      unlink(tempfile);
  }
  else if (tempfile[0])
    unlink(tempfile);

  if (http2 != http)
    httpClose(http2);

 /*
  * Return the PPD file...
  */

  DEBUG_printf(("1cupsGetPPD3: Returning status %d", status));

  return (status);
}