Пример #1
0
static void
cups_set_ssl_options(
    _cups_client_conf_t *cc,		/* I - client.conf values */
    const char          *value)		/* I - Value */
{
 /*
  * SSLOptions [AllowRC4] [AllowSSL3] [AllowDH] [DenyTLS1.0] [None]
  */

  int	options = _HTTP_TLS_NONE;	/* SSL/TLS options */
  char	temp[256],			/* Copy of value */
	*start,				/* Start of option */
	*end;				/* End of option */


  strlcpy(temp, value, sizeof(temp));

  for (start = temp; *start; start = end)
  {
   /*
    * Find end of keyword...
    */

    end = start;
    while (*end && !_cups_isspace(*end))
      end ++;

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

   /*
    * Compare...
    */

    if (!_cups_strcasecmp(start, "AllowRC4"))
      options |= _HTTP_TLS_ALLOW_RC4;
    else if (!_cups_strcasecmp(start, "AllowSSL3"))
      options |= _HTTP_TLS_ALLOW_SSL3;
    else if (!_cups_strcasecmp(start, "AllowDH"))
      options |= _HTTP_TLS_ALLOW_DH;
    else if (!_cups_strcasecmp(start, "DenyTLS1.0"))
      options |= _HTTP_TLS_DENY_TLS10;
    else if (!_cups_strcasecmp(start, "None"))
      options = _HTTP_TLS_NONE;
  }

  cc->ssl_options = options;

  DEBUG_printf(("4cups_set_ssl_options(cc=%p, value=\"%s\") options=%x", cc, value, options));
}
Пример #2
0
int					/* O - Number of options found */
cupsParseOptions(
    const char    *arg,			/* I - Argument to parse */
    int           num_options,		/* I - Number of options */
    cups_option_t **options)		/* O - Options found */
{
  char	*copyarg,			/* Copy of input string */
	*ptr,				/* Pointer into string */
	*name,				/* Pointer to name */
	*value,				/* Pointer to value */
	sep,				/* Separator character */
	quote;				/* Quote character */


  DEBUG_printf(("cupsParseOptions(arg=\"%s\", num_options=%d, options=%p)", arg, num_options, (void *)options));

 /*
  * Range check input...
  */

  if (!arg)
  {
    DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
    return (num_options);
  }

  if (!options || num_options < 0)
  {
    DEBUG_puts("1cupsParseOptions: Returning 0");
    return (0);
  }

 /*
  * Make a copy of the argument string and then divide it up...
  */

  if ((copyarg = strdup(arg)) == NULL)
  {
    DEBUG_puts("1cupsParseOptions: Unable to copy arg string");
    DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));
    return (num_options);
  }

  if (*copyarg == '{')
  {
   /*
    * Remove surrounding {} so we can parse "{name=value ... name=value}"...
    */

    if ((ptr = copyarg + strlen(copyarg) - 1) > copyarg && *ptr == '}')
    {
      *ptr = '\0';
      ptr  = copyarg + 1;
    }
    else
      ptr = copyarg;
  }
  else
    ptr = copyarg;

 /*
  * Skip leading spaces...
  */

  while (_cups_isspace(*ptr))
    ptr ++;

 /*
  * Loop through the string...
  */

  while (*ptr != '\0')
  {
   /*
    * Get the name up to a SPACE, =, or end-of-string...
    */

    name = ptr;
    while (!strchr("\f\n\r\t\v =", *ptr) && *ptr)
      ptr ++;

   /*
    * Avoid an empty name...
    */

    if (ptr == name)
      break;

   /*
    * Skip trailing spaces...
    */

    while (_cups_isspace(*ptr))
      *ptr++ = '\0';

    if ((sep = *ptr) == '=')
      *ptr++ = '\0';

    DEBUG_printf(("2cupsParseOptions: name=\"%s\"", name));

    if (sep != '=')
    {
     /*
      * Boolean option...
      */

      if (!_cups_strncasecmp(name, "no", 2))
        num_options = cupsAddOption(name + 2, "false", num_options,
	                            options);
      else
        num_options = cupsAddOption(name, "true", num_options, options);

      continue;
    }

   /*
    * Remove = and parse the value...
    */

    value = ptr;

    while (*ptr && !_cups_isspace(*ptr))
    {
      if (*ptr == ',')
        ptr ++;
      else if (*ptr == '\'' || *ptr == '\"')
      {
       /*
	* Quoted string constant...
	*/

	quote = *ptr;
	_cups_strcpy(ptr, ptr + 1);

	while (*ptr != quote && *ptr)
	{
	  if (*ptr == '\\' && ptr[1])
	    _cups_strcpy(ptr, ptr + 1);

	  ptr ++;
	}

	if (*ptr)
	  _cups_strcpy(ptr, ptr + 1);
      }
      else if (*ptr == '{')
      {
       /*
	* Collection value...
	*/

	int depth;

	for (depth = 0; *ptr; ptr ++)
	{
	  if (*ptr == '{')
	    depth ++;
	  else if (*ptr == '}')
	  {
	    depth --;
	    if (!depth)
	    {
	      ptr ++;
	      break;
	    }
	  }
	  else if (*ptr == '\\' && ptr[1])
	    _cups_strcpy(ptr, ptr + 1);
	}
      }
      else
      {
       /*
	* Normal space-delimited string...
	*/

	while (*ptr && !_cups_isspace(*ptr))
	{
	  if (*ptr == '\\' && ptr[1])
	    _cups_strcpy(ptr, ptr + 1);

	  ptr ++;
	}
      }
    }

    if (*ptr != '\0')
      *ptr++ = '\0';

    DEBUG_printf(("2cupsParseOptions: value=\"%s\"", value));

   /*
    * Skip trailing whitespace...
    */

    while (_cups_isspace(*ptr))
      ptr ++;

   /*
    * Add the string value...
    */

    num_options = cupsAddOption(name, value, num_options, options);
  }

 /*
  * Free the copy of the argument we made and return the number of options
  * found.
  */

  free(copyarg);

  DEBUG_printf(("1cupsParseOptions: Returning %d", num_options));

  return (num_options);
}
Пример #3
0
double					/* O - Number */
_cupsStrScand(const char   *buf,	/* I - Pointer to number */
              char         **bufptr,	/* O - New pointer or NULL on error */
              struct lconv *loc)	/* I - Locale data */
{
  char	temp[1024],			/* Temporary buffer */
	*tempptr;			/* Pointer into temporary buffer */


 /*
  * Range check input...
  */

  if (!buf)
    return (0.0);

 /*
  * Skip leading whitespace...
  */

  while (_cups_isspace(*buf))
    buf ++;

 /*
  * Copy leading sign, numbers, period, and then numbers...
  */

  tempptr = temp;
  if (*buf == '-' || *buf == '+')
    *tempptr++ = *buf++;

  while (isdigit(*buf & 255))
    if (tempptr < (temp + sizeof(temp) - 1))
      *tempptr++ = *buf++;
    else
    {
      if (bufptr)
	*bufptr = NULL;

      return (0.0);
    }

  if (*buf == '.')
  {
   /*
    * Read fractional portion of number...
    */

    buf ++;

    if (loc && loc->decimal_point)
    {
      strlcpy(tempptr, loc->decimal_point, sizeof(temp) - (size_t)(tempptr - temp));
      tempptr += strlen(tempptr);
    }
    else if (tempptr < (temp + sizeof(temp) - 1))
      *tempptr++ = '.';
    else
    {
      if (bufptr)
        *bufptr = NULL;

      return (0.0);
    }

    while (isdigit(*buf & 255))
      if (tempptr < (temp + sizeof(temp) - 1))
	*tempptr++ = *buf++;
      else
      {
	if (bufptr)
	  *bufptr = NULL;

	return (0.0);
      }
  }

  if (*buf == 'e' || *buf == 'E')
  {
   /*
    * Read exponent...
    */

    if (tempptr < (temp + sizeof(temp) - 1))
      *tempptr++ = *buf++;
    else
    {
      if (bufptr)
	*bufptr = NULL;

      return (0.0);
    }

    if (*buf == '+' || *buf == '-')
    {
      if (tempptr < (temp + sizeof(temp) - 1))
	*tempptr++ = *buf++;
      else
      {
	if (bufptr)
	  *bufptr = NULL;

	return (0.0);
      }
    }

    while (isdigit(*buf & 255))
      if (tempptr < (temp + sizeof(temp) - 1))
	*tempptr++ = *buf++;
      else
      {
	if (bufptr)
	  *bufptr = NULL;

	return (0.0);
      }
  }

 /*
  * Nul-terminate the temporary string and return the value...
  */

  if (bufptr)
    *bufptr = (char *)buf;

  *tempptr = '\0';

  return (strtod(temp, NULL));
}
Пример #4
0
static void
ppd_load_constraints(ppd_file_t *ppd)	/* I - PPD file */
{
  int		i;			/* Looping var */
  ppd_const_t	*oldconst;		/* Current UIConstraints data */
  ppd_attr_t	*constattr;		/* Current cupsUIConstraints attribute */
  _ppd_cups_uiconsts_t	*consts;	/* Current cupsUIConstraints data */
  _ppd_cups_uiconst_t	*constptr;	/* Current constraint */
  ppd_group_t	*installable;		/* Installable options group */
  const char	*vptr;			/* Pointer into constraint value */
  char		option[PPD_MAX_NAME],	/* Option name/MainKeyword */
		choice[PPD_MAX_NAME],	/* Choice/OptionKeyword */
		*ptr;			/* Pointer into option or choice */


  DEBUG_printf(("7ppd_load_constraints(ppd=%p)", ppd));

 /*
  * Create an array to hold the constraint data...
  */

  ppd->cups_uiconstraints = cupsArrayNew(NULL, NULL);

 /*
  * Find the installable options group if it exists...
  */

  for (i = ppd->num_groups, installable = ppd->groups;
       i > 0;
       i --, installable ++)
    if (!_cups_strcasecmp(installable->name, "InstallableOptions"))
      break;

  if (i <= 0)
    installable = NULL;

 /*
  * Load old-style [Non]UIConstraints data...
  */

  for (i = ppd->num_consts, oldconst = ppd->consts; i > 0; i --, oldconst ++)
  {
   /*
    * Weed out nearby duplicates, since the PPD spec requires that you
    * define both "*Foo foo *Bar bar" and "*Bar bar *Foo foo"...
    */

    if (i > 1 &&
	!_cups_strcasecmp(oldconst[0].option1, oldconst[1].option2) &&
	!_cups_strcasecmp(oldconst[0].choice1, oldconst[1].choice2) &&
	!_cups_strcasecmp(oldconst[0].option2, oldconst[1].option1) &&
	!_cups_strcasecmp(oldconst[0].choice2, oldconst[1].choice1))
      continue;

   /*
    * Allocate memory...
    */

    if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL)
    {
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "UIConstraints!");
      return;
    }

    if ((constptr = calloc(2, sizeof(_ppd_cups_uiconst_t))) == NULL)
    {
      free(consts);
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "UIConstraints!");
      return;
    }

   /*
    * Fill in the information...
    */

    consts->num_constraints = 2;
    consts->constraints     = constptr;

    if (!_cups_strncasecmp(oldconst->option1, "Custom", 6) &&
	!_cups_strcasecmp(oldconst->choice1, "True"))
    {
      constptr[0].option      = ppdFindOption(ppd, oldconst->option1 + 6);
      constptr[0].choice      = ppdFindChoice(constptr[0].option, "Custom");
      constptr[0].installable = 0;
    }
    else
    {
      constptr[0].option      = ppdFindOption(ppd, oldconst->option1);
      constptr[0].choice      = ppdFindChoice(constptr[0].option,
					      oldconst->choice1);
      constptr[0].installable = ppd_is_installable(installable,
						   oldconst->option1);
    }

    if (!constptr[0].option || (!constptr[0].choice && oldconst->choice1[0]))
    {
      DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
		    oldconst->option1, oldconst->choice1));
      free(consts->constraints);
      free(consts);
      continue;
    }

    if (!_cups_strncasecmp(oldconst->option2, "Custom", 6) &&
	!_cups_strcasecmp(oldconst->choice2, "True"))
    {
      constptr[1].option      = ppdFindOption(ppd, oldconst->option2 + 6);
      constptr[1].choice      = ppdFindChoice(constptr[1].option, "Custom");
      constptr[1].installable = 0;
    }
    else
    {
      constptr[1].option      = ppdFindOption(ppd, oldconst->option2);
      constptr[1].choice      = ppdFindChoice(constptr[1].option,
					      oldconst->choice2);
      constptr[1].installable = ppd_is_installable(installable,
						   oldconst->option2);
    }

    if (!constptr[1].option || (!constptr[1].choice && oldconst->choice2[0]))
    {
      DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
		    oldconst->option2, oldconst->choice2));
      free(consts->constraints);
      free(consts);
      continue;
    }

    consts->installable = constptr[0].installable || constptr[1].installable;

   /*
    * Add it to the constraints array...
    */

    cupsArrayAdd(ppd->cups_uiconstraints, consts);
  }

 /*
  * Then load new-style constraints...
  */

  for (constattr = ppdFindAttr(ppd, "cupsUIConstraints", NULL);
       constattr;
       constattr = ppdFindNextAttr(ppd, "cupsUIConstraints", NULL))
  {
    if (!constattr->value)
    {
      DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!");
      continue;
    }

    for (i = 0, vptr = strchr(constattr->value, '*');
	 vptr;
	 i ++, vptr = strchr(vptr + 1, '*'));

    if (i == 0)
    {
      DEBUG_puts("8ppd_load_constraints: Bad cupsUIConstraints value!");
      continue;
    }

    if ((consts = calloc(1, sizeof(_ppd_cups_uiconsts_t))) == NULL)
    {
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "cupsUIConstraints!");
      return;
    }

    if ((constptr = calloc((size_t)i, sizeof(_ppd_cups_uiconst_t))) == NULL)
    {
      free(consts);
      DEBUG_puts("8ppd_load_constraints: Unable to allocate memory for "
		 "cupsUIConstraints!");
      return;
    }

    consts->num_constraints = i;
    consts->constraints     = constptr;

    strlcpy(consts->resolver, constattr->spec, sizeof(consts->resolver));

    for (i = 0, vptr = strchr(constattr->value, '*');
	 vptr;
	 i ++, vptr = strchr(vptr, '*'), constptr ++)
    {
     /*
      * Extract "*Option Choice" or just "*Option"...
      */

      for (vptr ++, ptr = option; *vptr && !_cups_isspace(*vptr); vptr ++)
	if (ptr < (option + sizeof(option) - 1))
	  *ptr++ = *vptr;

      *ptr = '\0';

      while (_cups_isspace(*vptr))
	vptr ++;

      if (*vptr == '*')
	choice[0] = '\0';
      else
      {
	for (ptr = choice; *vptr && !_cups_isspace(*vptr); vptr ++)
	  if (ptr < (choice + sizeof(choice) - 1))
	    *ptr++ = *vptr;

	*ptr = '\0';
      }

      if (!_cups_strncasecmp(option, "Custom", 6) && !_cups_strcasecmp(choice, "True"))
      {
	_cups_strcpy(option, option + 6);
	strlcpy(choice, "Custom", sizeof(choice));
      }

      constptr->option      = ppdFindOption(ppd, option);
      constptr->choice      = ppdFindChoice(constptr->option, choice);
      constptr->installable = ppd_is_installable(installable, option);
      consts->installable   |= constptr->installable;

      if (!constptr->option || (!constptr->choice && choice[0]))
      {
	DEBUG_printf(("8ppd_load_constraints: Unknown option *%s %s!",
		      option, choice));
	break;
      }
    }

    if (!vptr)
      cupsArrayAdd(ppd->cups_uiconstraints, consts);
    else
    {
      free(consts->constraints);
      free(consts);
    }
  }
}
Пример #5
0
int					/* O  - 1 on success, 0 on failure */
cupsResolveConflicts(
    ppd_file_t    *ppd,			/* I  - PPD file */
    const char    *option,		/* I  - Newly selected option or @code NULL@ for none */
    const char    *choice,		/* I  - Newly selected choice or @code NULL@ for none */
    int           *num_options,		/* IO - Number of additional selected options */
    cups_option_t **options)		/* IO - Additional selected options */
{
  int			i,		/* Looping var */
			tries,		/* Number of tries */
			num_newopts;	/* Number of new options */
  cups_option_t		*newopts;	/* New options */
  cups_array_t		*active = NULL,	/* Active constraints */
			*pass,		/* Resolvers for this pass */
			*resolvers,	/* Resolvers we have used */
			*test;		/* Test array for conflicts */
  _ppd_cups_uiconsts_t	*consts;	/* Current constraints */
  _ppd_cups_uiconst_t	*constptr;	/* Current constraint */
  ppd_attr_t		*resolver;	/* Current resolver */
  const char		*resval;	/* Pointer into resolver value */
  char			resoption[PPD_MAX_NAME],
					/* Current resolver option */
			reschoice[PPD_MAX_NAME],
					/* Current resolver choice */
			*resptr,	/* Pointer into option/choice */
			firstpage[255];	/* AP_FIRSTPAGE_Keyword string */
  const char		*value;		/* Selected option value */
  int			changed;	/* Did we change anything? */
  ppd_choice_t		*marked;	/* Marked choice */


 /*
  * Range check input...
  */

  if (!ppd || !num_options || !options || (option == NULL) != (choice == NULL))
    return (0);

 /*
  * Build a shadow option array...
  */

  num_newopts = 0;
  newopts     = NULL;

  for (i = 0; i < *num_options; i ++)
    num_newopts = cupsAddOption((*options)[i].name, (*options)[i].value,
                                num_newopts, &newopts);
  if (option && _cups_strcasecmp(option, "Collate"))
    num_newopts = cupsAddOption(option, choice, num_newopts, &newopts);

 /*
  * Loop until we have no conflicts...
  */

  cupsArraySave(ppd->sorted_attrs);

  resolvers = NULL;
  pass      = cupsArrayNew((cups_array_func_t)_cups_strcasecmp, NULL);
  tries     = 0;

  while (tries < 100 &&
         (active = ppd_test_constraints(ppd, NULL, NULL, num_newopts, newopts,
                                        _PPD_ALL_CONSTRAINTS)) != NULL)
  {
    tries ++;

    if (!resolvers)
      resolvers = cupsArrayNew((cups_array_func_t)_cups_strcasecmp, NULL);

    for (consts = (_ppd_cups_uiconsts_t *)cupsArrayFirst(active), changed = 0;
         consts;
	 consts = (_ppd_cups_uiconsts_t *)cupsArrayNext(active))
    {
      if (consts->resolver[0])
      {
       /*
        * Look up the resolver...
	*/

        if (cupsArrayFind(pass, consts->resolver))
	  continue;			/* Already applied this resolver... */

        if (cupsArrayFind(resolvers, consts->resolver))
	{
	 /*
	  * Resolver loop!
	  */

	  DEBUG_printf(("1cupsResolveConflicts: Resolver loop with %s!",
	                consts->resolver));
          goto error;
	}

        if ((resolver = ppdFindAttr(ppd, "cupsUIResolver",
	                            consts->resolver)) == NULL)
        {
	  DEBUG_printf(("1cupsResolveConflicts: Resolver %s not found!",
	                consts->resolver));
	  goto error;
	}

        if (!resolver->value)
	{
	  DEBUG_printf(("1cupsResolveConflicts: Resolver %s has no value!",
	                consts->resolver));
	  goto error;
	}

       /*
        * Add the options from the resolver...
	*/

        cupsArrayAdd(pass, consts->resolver);
	cupsArrayAdd(resolvers, consts->resolver);

        for (resval = resolver->value; *resval && !changed;)
	{
	  while (_cups_isspace(*resval))
	    resval ++;

	  if (*resval != '*')
	    break;

	  for (resval ++, resptr = resoption;
	       *resval && !_cups_isspace(*resval);
	       resval ++)
            if (resptr < (resoption + sizeof(resoption) - 1))
	      *resptr++ = *resval;

          *resptr = '\0';

	  while (_cups_isspace(*resval))
	    resval ++;

	  for (resptr = reschoice;
	       *resval && !_cups_isspace(*resval);
	       resval ++)
            if (resptr < (reschoice + sizeof(reschoice) - 1))
	      *resptr++ = *resval;

          *resptr = '\0';

          if (!resoption[0] || !reschoice[0])
	    break;

         /*
	  * Is this the option we are changing?
	  */

          snprintf(firstpage, sizeof(firstpage), "AP_FIRSTPAGE_%s", resoption);

	  if (option &&
	      (!_cups_strcasecmp(resoption, option) ||
	       !_cups_strcasecmp(firstpage, option) ||
	       (!_cups_strcasecmp(option, "PageSize") &&
		!_cups_strcasecmp(resoption, "PageRegion")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") &&
		!_cups_strcasecmp(resoption, "PageSize")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageSize") &&
		!_cups_strcasecmp(resoption, "PageRegion")) ||
	       (!_cups_strcasecmp(option, "PageRegion") &&
	        !_cups_strcasecmp(resoption, "PageSize")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion") &&
	        !_cups_strcasecmp(resoption, "PageSize")) ||
	       (!_cups_strcasecmp(option, "AP_FIRSTPAGE_PageRegion") &&
	        !_cups_strcasecmp(resoption, "PageRegion"))))
	    continue;

	 /*
	  * Try this choice...
	  */

          if ((test = ppd_test_constraints(ppd, resoption, reschoice,
					   num_newopts, newopts,
					   _PPD_ALL_CONSTRAINTS)) == NULL)
	  {
	   /*
	    * That worked...
	    */

            changed = 1;
	  }
	  else
            cupsArrayDelete(test);

	 /*
	  * Add the option/choice from the resolver regardless of whether it
	  * worked; this makes sure that we can cascade several changes to
	  * make things resolve...
	  */

	  num_newopts = cupsAddOption(resoption, reschoice, num_newopts,
				      &newopts);
        }
      }
      else
      {
       /*
        * Try resolving by choosing the default values for non-installable
	* options, then by iterating through the possible choices...
	*/

        int		j;		/* Looping var */
	ppd_choice_t	*cptr;		/* Current choice */
        ppd_size_t	*size;		/* Current page size */


        for (i = consts->num_constraints, constptr = consts->constraints;
	     i > 0 && !changed;
	     i --, constptr ++)
	{
	 /*
	  * Can't resolve by changing an installable option...
	  */

	  if (constptr->installable)
	    continue;

         /*
	  * Is this the option we are changing?
	  */

	  if (option &&
	      (!_cups_strcasecmp(constptr->option->keyword, option) ||
	       (!_cups_strcasecmp(option, "PageSize") &&
		!_cups_strcasecmp(constptr->option->keyword, "PageRegion")) ||
	       (!_cups_strcasecmp(option, "PageRegion") &&
		!_cups_strcasecmp(constptr->option->keyword, "PageSize"))))
	    continue;

         /*
	  * Get the current option choice...
	  */

          if ((value = cupsGetOption(constptr->option->keyword, num_newopts,
	                             newopts)) == NULL)
          {
	    if (!_cups_strcasecmp(constptr->option->keyword, "PageSize") ||
	        !_cups_strcasecmp(constptr->option->keyword, "PageRegion"))
	    {
	      if ((value = cupsGetOption("PageSize", num_newopts,
	                                 newopts)) == NULL)
                value = cupsGetOption("PageRegion", num_newopts, newopts);

              if (!value)
	      {
	        if ((size = ppdPageSize(ppd, NULL)) != NULL)
		  value = size->name;
		else
		  value = "";
	      }
	    }
	    else
	    {
	      marked = ppdFindMarkedChoice(ppd, constptr->option->keyword);
	      value  = marked ? marked->choice : "";
	    }
	  }

	  if (!_cups_strncasecmp(value, "Custom.", 7))
	    value = "Custom";

         /*
	  * Try the default choice...
	  */

          test = NULL;

          if (_cups_strcasecmp(value, constptr->option->defchoice) &&
	      (test = ppd_test_constraints(ppd, constptr->option->keyword,
	                                   constptr->option->defchoice,
					   num_newopts, newopts,
					   _PPD_OPTION_CONSTRAINTS)) == NULL)
	  {
	   /*
	    * That worked...
	    */

	    num_newopts = cupsAddOption(constptr->option->keyword,
	                                constptr->option->defchoice,
					num_newopts, &newopts);
            changed     = 1;
	  }
	  else
	  {
	   /*
	    * Try each choice instead...
	    */

            for (j = constptr->option->num_choices,
	             cptr = constptr->option->choices;
		 j > 0;
		 j --, cptr ++)
            {
	      cupsArrayDelete(test);
	      test = NULL;

	      if (_cups_strcasecmp(value, cptr->choice) &&
	          _cups_strcasecmp(constptr->option->defchoice, cptr->choice) &&
		  _cups_strcasecmp("Custom", cptr->choice) &&
	          (test = ppd_test_constraints(ppd, constptr->option->keyword,
	                                       cptr->choice, num_newopts,
					       newopts,
					       _PPD_OPTION_CONSTRAINTS)) == NULL)
	      {
	       /*
		* This choice works...
		*/

		num_newopts = cupsAddOption(constptr->option->keyword,
					    cptr->choice, num_newopts,
					    &newopts);
		changed     = 1;
		break;
	      }
	    }

	    cupsArrayDelete(test);
          }
        }
      }
    }

    if (!changed)
    {
      DEBUG_puts("1cupsResolveConflicts: Unable to automatically resolve "
		 "constraint!");
      goto error;
    }

    cupsArrayClear(pass);
    cupsArrayDelete(active);
    active = NULL;
  }

  if (tries >= 100)
    goto error;

 /*
  * Free the caller's option array...
  */

  cupsFreeOptions(*num_options, *options);

 /*
  * If Collate is the option we are testing, add it here.  Otherwise, remove
  * any Collate option from the resolve list since the filters automatically
  * handle manual collation...
  */

  if (option && !_cups_strcasecmp(option, "Collate"))
    num_newopts = cupsAddOption(option, choice, num_newopts, &newopts);
  else
    num_newopts = cupsRemoveOption("Collate", num_newopts, &newopts);

 /*
  * Return the new list of options to the caller...
  */

  *num_options = num_newopts;
  *options     = newopts;

  cupsArrayDelete(pass);
  cupsArrayDelete(resolvers);

  cupsArrayRestore(ppd->sorted_attrs);

  DEBUG_printf(("1cupsResolveConflicts: Returning %d options:", num_newopts));
#ifdef DEBUG
  for (i = 0; i < num_newopts; i ++)
    DEBUG_printf(("1cupsResolveConflicts: options[%d]: %s=%s", i,
                  newopts[i].name, newopts[i].value));
#endif /* DEBUG */

  return (1);

 /*
  * If we get here, we failed to resolve...
  */

  error:

  cupsFreeOptions(num_newopts, newopts);

  cupsArrayDelete(active);
  cupsArrayDelete(pass);
  cupsArrayDelete(resolvers);

  cupsArrayRestore(ppd->sorted_attrs);

  DEBUG_puts("1cupsResolveConflicts: Unable to resolve conflicts!");

  return (0);
}
Пример #6
0
Файл: attr.c Проект: ezeep/cups
char *					/* O - Normalized make-and-model string or NULL on error */
_ppdNormalizeMakeAndModel(
    const char *make_and_model,		/* I - Original make-and-model string */
    char       *buffer,			/* I - String buffer */
    size_t     bufsize)			/* I - Size of string buffer */
{
  char	*bufptr;			/* Pointer into buffer */


  if (!make_and_model || !buffer || bufsize < 1)
  {
    if (buffer)
      *buffer = '\0';

    return (NULL);
  }

 /*
  * Skip leading whitespace...
  */

  while (_cups_isspace(*make_and_model))
    make_and_model ++;

 /*
  * Remove parenthesis and add manufacturers as needed...
  */

  if (make_and_model[0] == '(')
  {
    strlcpy(buffer, make_and_model + 1, bufsize);

    if ((bufptr = strrchr(buffer, ')')) != NULL)
      *bufptr = '\0';
  }
  else if (!_cups_strncasecmp(make_and_model, "XPrint", 6))
  {
   /*
    * Xerox XPrint...
    */

    snprintf(buffer, bufsize, "Xerox %s", make_and_model);
  }
  else if (!_cups_strncasecmp(make_and_model, "Eastman", 7))
  {
   /*
    * Kodak...
    */

    snprintf(buffer, bufsize, "Kodak %s", make_and_model + 7);
  }
  else if (!_cups_strncasecmp(make_and_model, "laserwriter", 11))
  {
   /*
    * Apple LaserWriter...
    */

    snprintf(buffer, bufsize, "Apple LaserWriter%s", make_and_model + 11);
  }
  else if (!_cups_strncasecmp(make_and_model, "colorpoint", 10))
  {
   /*
    * Seiko...
    */

    snprintf(buffer, bufsize, "Seiko %s", make_and_model);
  }
  else if (!_cups_strncasecmp(make_and_model, "fiery", 5))
  {
   /*
    * EFI...
    */

    snprintf(buffer, bufsize, "EFI %s", make_and_model);
  }
  else if (!_cups_strncasecmp(make_and_model, "ps ", 3) ||
	   !_cups_strncasecmp(make_and_model, "colorpass", 9))
  {
   /*
    * Canon...
    */

    snprintf(buffer, bufsize, "Canon %s", make_and_model);
  }
  else if (!_cups_strncasecmp(make_and_model, "primera", 7))
  {
   /*
    * Fargo...
    */

    snprintf(buffer, bufsize, "Fargo %s", make_and_model);
  }
  else if (!_cups_strncasecmp(make_and_model, "designjet", 9) ||
           !_cups_strncasecmp(make_and_model, "deskjet", 7))
  {
   /*
    * HP...
    */

    snprintf(buffer, bufsize, "HP %s", make_and_model);
  }
  else
    strlcpy(buffer, make_and_model, bufsize);

 /*
  * Clean up the make...
  */

  if (!_cups_strncasecmp(buffer, "agfa", 4))
  {
   /*
    * Replace with AGFA (all uppercase)...
    */

    buffer[0] = 'A';
    buffer[1] = 'G';
    buffer[2] = 'F';
    buffer[3] = 'A';
  }
  else if (!_cups_strncasecmp(buffer, "Hewlett-Packard hp ", 19))
  {
   /*
    * Just put "HP" on the front...
    */

    buffer[0] = 'H';
    buffer[1] = 'P';
    _cups_strcpy(buffer + 2, buffer + 18);
  }
  else if (!_cups_strncasecmp(buffer, "Hewlett-Packard ", 16))
  {
   /*
    * Just put "HP" on the front...
    */

    buffer[0] = 'H';
    buffer[1] = 'P';
    _cups_strcpy(buffer + 2, buffer + 15);
  }
  else if (!_cups_strncasecmp(buffer, "Lexmark International", 21))
  {
   /*
    * Strip "International"...
    */

    _cups_strcpy(buffer + 8, buffer + 21);
  }
  else if (!_cups_strncasecmp(buffer, "herk", 4))
  {
   /*
    * Replace with LHAG...
    */

    buffer[0] = 'L';
    buffer[1] = 'H';
    buffer[2] = 'A';
    buffer[3] = 'G';
  }
  else if (!_cups_strncasecmp(buffer, "linotype", 8))
  {
   /*
    * Replace with LHAG...
    */

    buffer[0] = 'L';
    buffer[1] = 'H';
    buffer[2] = 'A';
    buffer[3] = 'G';
    _cups_strcpy(buffer + 4, buffer + 8);
  }

 /*
  * Remove trailing whitespace and return...
  */

  for (bufptr = buffer + strlen(buffer) - 1;
       bufptr >= buffer && _cups_isspace(*bufptr);
       bufptr --);

  bufptr[1] = '\0';

  return (buffer[0] ? buffer : NULL);
}
Пример #7
0
static void
add_ppd_filter(mime_t      *mime,	/* I - MIME database */
               mime_type_t *filtertype,	/* I - Filter or prefilter MIME type */
	       const char  *filter)	/* I - Filter to add */
{
  char		super[MIME_MAX_SUPER],	/* Super-type for filter */
		type[MIME_MAX_TYPE],	/* Type for filter */
		dsuper[MIME_MAX_SUPER],	/* Destination super-type for filter */
		dtype[MIME_MAX_TYPE],	/* Destination type for filter */
		dest[MIME_MAX_SUPER + MIME_MAX_TYPE + 2],
					/* Destination super/type */
		program[1024];		/* Program/filter name */
  int		cost;			/* Cost of filter */
  size_t	maxsize = 0;		/* Maximum supported file size */
  mime_type_t	*temptype,		/* MIME type looping var */
		*desttype;		/* Destination MIME type */
  mime_filter_t	*filterptr;		/* MIME filter */


  DEBUG_printf(("add_ppd_filter(mime=%p, filtertype=%p(%s/%s), filter=\"%s\")",
                mime, filtertype, filtertype->super, filtertype->type, filter));

 /*
  * Parse the filter string; it should be in one of the following formats:
  *
  *     source/type cost program
  *     source/type cost maxsize(nnnn) program
  *     source/type dest/type cost program
  *     source/type dest/type cost maxsize(nnnn) program
  */

  if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
             super, type, dsuper, dtype, &cost, program) == 6)
  {
    snprintf(dest, sizeof(dest), "test/%s/%s", dsuper, dtype);

    if ((desttype = mimeType(mime, "printer", dest)) == NULL)
      desttype = mimeAddType(mime, "printer", dest);
  }
  else
  {
    if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost,
               program) == 4)
    {
      desttype = filtertype;
    }
    else
    {
      printf("testmime: Invalid filter string \"%s\".\n", filter);
      return;
    }
  }

  if (!strncmp(program, "maxsize(", 8))
  {
    char	*ptr;			/* Pointer into maxsize(nnnn) program */

    maxsize = strtoll(program + 8, &ptr, 10);

    if (*ptr != ')')
    {
      printf("testmime: Invalid filter string \"%s\".\n", filter);
      return;
    }

    ptr ++;
    while (_cups_isspace(*ptr))
      ptr ++;

    _cups_strcpy(program, ptr);
  }

 /*
  * Add the filter to the MIME database, supporting wildcards as needed...
  */

  for (temptype = mimeFirstType(mime);
       temptype;
       temptype = mimeNextType(mime))
    if (((super[0] == '*' && _cups_strcasecmp(temptype->super, "printer")) ||
         !_cups_strcasecmp(temptype->super, super)) &&
        (type[0] == '*' || !_cups_strcasecmp(temptype->type, type)))
    {
      if (desttype != filtertype)
      {
        DEBUG_printf(("add_ppd_filter: Adding filter %s/%s %s/%s %d %s",
		      temptype->super, temptype->type, desttype->super,
		      desttype->type, cost, program));
        filterptr = mimeAddFilter(mime, temptype, desttype, cost, program);

        if (!mimeFilterLookup(mime, desttype, filtertype))
        {
          DEBUG_printf(("add_printer_filter: Adding filter %s/%s %s/%s 0 -",
	                desttype->super, desttype->type, filtertype->super,
	                filtertype->type));
          mimeAddFilter(mime, desttype, filtertype, 0, "-");
        }
      }
      else
      {
        DEBUG_printf(("add_printer_filter: Adding filter %s/%s %s/%s %d %s",
		      temptype->super, temptype->type, filtertype->super,
		      filtertype->type, cost, program));
        filterptr = mimeAddFilter(mime, temptype, filtertype, cost, program);
      }

      if (filterptr)
	filterptr->maxsize = maxsize;
    }
}
Пример #8
0
cups_array_t *				/* O - Languages array */
_ppdGetLanguages(ppd_file_t *ppd)	/* I - PPD file */
{
  cups_array_t	*languages;		/* Languages array */
  ppd_attr_t	*attr;			/* cupsLanguages attribute */
  char		*value,			/* Copy of attribute value */
		*start,			/* Start of current language */
		*ptr;			/* Pointer into languages */


 /*
  * See if we have a cupsLanguages attribute...
  */

  if ((attr = ppdFindAttr(ppd, "cupsLanguages", NULL)) == NULL || !attr->value)
    return (NULL);

 /*
  * Yes, load the list...
  */

  if ((languages = cupsArrayNew((cups_array_func_t)strcmp, NULL)) == NULL)
    return (NULL);

  if ((value = strdup(attr->value)) == NULL)
  {
    cupsArrayDelete(languages);
    return (NULL);
  }

  for (ptr = value; *ptr;)
  {
   /*
    * Skip leading whitespace...
    */

    while (_cups_isspace(*ptr))
      ptr ++;

    if (!*ptr)
      break;

   /*
    * Find the end of this language name...
    */

    for (start = ptr; *ptr && !_cups_isspace(*ptr); ptr ++);

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

    if (!strcmp(start, "en"))
      continue;

    cupsArrayAdd(languages, strdup(start));
  }

 /*
  * Free the temporary string and return either an array with one or more
  * values or a NULL pointer...
  */

  free(value);

  if (cupsArrayCount(languages) == 0)
  {
    cupsArrayDelete(languages);
    return (NULL);
  }
  else
    return (languages);
}
Пример #9
0
size_t					/* O - Number of bytes less nul */
_ippAttrString(ipp_attribute_t *attr,	/* I - Attribute */
               char            *buffer,	/* I - String buffer or NULL */
               size_t          bufsize)	/* I - Size of string buffer */
{
    int		i;			/* Looping var */
    char		*bufptr,		/* Pointer into buffer */
                *bufend,		/* End of buffer */
                temp[256];		/* Temporary string */
    const char	*ptr;			/* Pointer into string */
    ipp_value_t	*val;			/* Current value */


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

        return (0);
    }

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

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

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

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

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

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

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

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

                bufptr += strlen(ptr);
                break;
            }

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

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

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

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

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

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

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

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

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

            bufptr += strlen(temp);
        }
        break;

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

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

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

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

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

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

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

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

    return (bufptr - buffer);
}
Пример #10
0
char *					/* O  - Line read or @code NULL@ on end of file or error */
cupsFileGetConf(cups_file_t *fp,	/* I  - CUPS file */
                char        *buf,	/* O  - String buffer */
		size_t      buflen,	/* I  - Size of string buffer */
                char        **value,	/* O  - Pointer to value */
		int         *linenum)	/* IO - Current line number */
{
  char	*ptr;				/* Pointer into line */


 /*
  * Range check input...
  */

  DEBUG_printf(("2cupsFileGetConf(fp=%p, buf=%p, buflen=" CUPS_LLFMT
                ", value=%p, linenum=%p)", fp, buf, CUPS_LLCAST buflen,
		value, linenum));

  if (!fp || (fp->mode != 'r' && fp->mode != 's') ||
      !buf || buflen < 2 || !value)
  {
    if (value)
      *value = NULL;

    return (NULL);
  }

 /*
  * Read the next non-comment line...
  */

  *value = NULL;

  while (cupsFileGets(fp, buf, buflen))
  {
    (*linenum) ++;

   /*
    * Strip any comments...
    */

    if ((ptr = strchr(buf, '#')) != NULL)
    {
      if (ptr > buf && ptr[-1] == '\\')
      {
        // Unquote the #...
	_cups_strcpy(ptr - 1, ptr);
      }
      else
      {
        // Strip the comment and any trailing whitespace...
	while (ptr > buf)
	{
	  if (!_cups_isspace(ptr[-1]))
	    break;

	  ptr --;
	}

	*ptr = '\0';
      }
    }

   /*
    * Strip leading whitespace...
    */

    for (ptr = buf; _cups_isspace(*ptr); ptr ++);

    if (ptr > buf)
      _cups_strcpy(buf, ptr);

   /*
    * See if there is anything left...
    */

    if (buf[0])
    {
     /*
      * Yes, grab any value and return...
      */

      for (ptr = buf; *ptr; ptr ++)
        if (_cups_isspace(*ptr))
	  break;

      if (*ptr)
      {
       /*
        * Have a value, skip any other spaces...
	*/

        while (_cups_isspace(*ptr))
	  *ptr++ = '\0';

        if (*ptr)
	  *value = ptr;

       /*
        * Strip trailing whitespace and > for lines that begin with <...
	*/

        ptr += strlen(ptr) - 1;

        if (buf[0] == '<' && *ptr == '>')
	  *ptr-- = '\0';
	else if (buf[0] == '<' && *ptr != '>')
        {
	 /*
	  * Syntax error...
	  */

	  *value = NULL;
	  return (buf);
	}

        while (ptr > *value && _cups_isspace(*ptr))
	  *ptr-- = '\0';
      }

     /*
      * Return the line...
      */

      return (buf);
    }
  }

  return (NULL);
}
Пример #11
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);
}
Пример #12
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);
}
Пример #13
0
static void
add_printer_filter(
    const char  *command,		/* I - Command name */
    mime_t      *mime,			/* I - MIME database */
    mime_type_t *filtertype,		/* I - Printer or prefilter MIME type */
    const char  *filter)		/* I - Filter to add */
{
  char		super[MIME_MAX_SUPER],	/* Super-type for filter */
		type[MIME_MAX_TYPE],	/* Type for filter */
		dsuper[MIME_MAX_SUPER],	/* Destination super-type for filter */
		dtype[MIME_MAX_TYPE],	/* Destination type for filter */
		dest[MIME_MAX_SUPER + MIME_MAX_TYPE + 2],
					/* Destination super/type */
		program[1024];		/* Program/filter name */
  int		cost;			/* Cost of filter */
  size_t	maxsize = 0;		/* Maximum supported file size */
  mime_type_t	*temptype,		/* MIME type looping var */
		*desttype;		/* Destination MIME type */
  mime_filter_t	*filterptr;		/* MIME filter */


 /*
  * Parse the filter string; it should be in one of the following formats:
  *
  *     source/type cost program
  *     source/type cost maxsize(nnnn) program
  *     source/type dest/type cost program
  *     source/type dest/type cost maxsize(nnnn) program
  */

  if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]",
             super, type, dsuper, dtype, &cost, program) == 6)
  {
    snprintf(dest, sizeof(dest), "%s/%s/%s", filtertype->type, dsuper, dtype);

    if ((desttype = mimeType(mime, "printer", dest)) == NULL)
      desttype = mimeAddType(mime, "printer", dest);
  }
  else
  {
    if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost,
               program) == 4)
    {
      desttype = filtertype;
    }
    else
    {
      _cupsLangPrintf(stderr, _("%s: Invalid filter string \"%s\"."), command,
		      filter);
      return;
    }
  }

  if (!strncmp(program, "maxsize(", 8))
  {
    char	*ptr;			/* Pointer into maxsize(nnnn) program */

    maxsize = (size_t)strtoll(program + 8, &ptr, 10);

    if (*ptr != ')')
    {
      printf("testmime: Invalid filter string \"%s\".\n", filter);
      return;
    }

    ptr ++;
    while (_cups_isspace(*ptr))
      ptr ++;

    _cups_strcpy(program, ptr);
  }

 /*
  * See if the filter program exists; if not, stop the printer and flag
  * the error!
  */

  if (strcmp(program, "-"))
  {
    char filename[1024];		/* Full path to program */

    if (program[0] == '/')
      strlcpy(filename, program, sizeof(filename));
    else
      snprintf(filename, sizeof(filename), "%s/filter/%s", ServerBin, program);

    if (_cupsFileCheck(filename, _CUPS_FILE_CHECK_PROGRAM, !geteuid(), check_cb,
                       (void *)command))
      return;
  }

 /*
  * Add the filter to the MIME database, supporting wildcards as needed...
  */

  for (temptype = mimeFirstType(mime);
       temptype;
       temptype = mimeNextType(mime))
    if (((super[0] == '*' && _cups_strcasecmp(temptype->super, "printer")) ||
         !_cups_strcasecmp(temptype->super, super)) &&
        (type[0] == '*' || !_cups_strcasecmp(temptype->type, type)))
    {
      if (desttype != filtertype)
      {
        filterptr = mimeAddFilter(mime, temptype, desttype, cost, program);

        if (!mimeFilterLookup(mime, desttype, filtertype))
          mimeAddFilter(mime, desttype, filtertype, 0, "-");
      }
      else
        filterptr = mimeAddFilter(mime, temptype, filtertype, cost, program);

      if (filterptr)
	filterptr->maxsize = maxsize;
    }
}
Пример #14
0
int					/* O - 0 on success, -1 on failure */
backendGetDeviceID(
    int        fd,			/* I - File descriptor */
    char       *device_id,		/* O - 1284 device ID */
    int        device_id_size,		/* I - Size of buffer */
    char       *make_model,		/* O - Make/model */
    int        make_model_size,		/* I - Size of buffer */
    const char *scheme,			/* I - URI scheme */
    char       *uri,			/* O - Device URI */
    int        uri_size)		/* I - Size of buffer */
{
#ifdef __APPLE__ /* This function is a no-op */
  (void)fd;
  (void)device_id;
  (void)device_id_size;
  (void)make_model;
  (void)make_model_size;
  (void)scheme;
  (void)uri;
  (void)uri_size;

  return (-1);

#else /* Get the device ID from the specified file descriptor... */
#  ifdef __linux
  int	length;				/* Length of device ID info */
  int   got_id = 0;
#  endif /* __linux */
#  if defined(__sun) && defined(ECPPIOC_GETDEVID)
  struct ecpp_device_id did;		/* Device ID buffer */
#  endif /* __sun && ECPPIOC_GETDEVID */
  char	*ptr;				/* Pointer into device ID */


  DEBUG_printf(("backendGetDeviceID(fd=%d, device_id=%p, device_id_size=%d, "
                "make_model=%p, make_model_size=%d, scheme=\"%s\", "
		"uri=%p, uri_size=%d)\n", fd, device_id, device_id_size,
		make_model, make_model_size, scheme ? scheme : "(null)",
		uri, uri_size));

 /*
  * Range check input...
  */

  if (!device_id || device_id_size < 32)
  {
    DEBUG_puts("backendGetDeviceID: Bad args!");
    return (-1);
  }

  if (make_model)
    *make_model = '\0';

  if (fd >= 0)
  {
   /*
    * Get the device ID string...
    */

    *device_id = '\0';

#  ifdef __linux
    if (ioctl(fd, LPIOC_GET_DEVICE_ID(device_id_size), device_id))
    {
     /*
      * Linux has to implement things differently for every device it seems.
      * Since the standard parallel port driver does not provide a simple
      * ioctl() to get the 1284 device ID, we have to open the "raw" parallel
      * device corresponding to this port and do some negotiation trickery
      * to get the current device ID.
      */

      if (uri && !strncmp(uri, "parallel:/dev/", 14))
      {
	char	devparport[16];		/* /dev/parportN */
	int	devparportfd,		/* File descriptor for raw device */
		  mode;			/* Port mode */


       /*
	* Since the Linux parallel backend only supports 4 parallel port
	* devices, just grab the trailing digit and use it to construct a
	* /dev/parportN filename...
	*/

	snprintf(devparport, sizeof(devparport), "/dev/parport%s",
		 uri + strlen(uri) - 1);

	if ((devparportfd = open(devparport, O_RDWR | O_NOCTTY)) != -1)
	{
	 /*
	  * Claim the device...
	  */

	  if (!ioctl(devparportfd, PPCLAIM))
	  {
	    fcntl(devparportfd, F_SETFL, fcntl(devparportfd, F_GETFL) | O_NONBLOCK);

	    mode = IEEE1284_MODE_COMPAT;

	    if (!ioctl(devparportfd, PPNEGOT, &mode))
	    {
	     /*
	      * Put the device into Device ID mode...
	      */

	      mode = IEEE1284_MODE_NIBBLE | IEEE1284_DEVICEID;

	      if (!ioctl(devparportfd, PPNEGOT, &mode))
	      {
	       /*
		* Read the 1284 device ID...
		*/

		if ((length = read(devparportfd, device_id, (size_t)device_id_size - 1)) >= 2)
		{
		  device_id[length] = '\0';
		  got_id = 1;
		}
	      }
	    }

	   /*
	    * Release the device...
	    */

	    ioctl(devparportfd, PPRELEASE);
	  }

	  close(devparportfd);
	}
      }
    }
    else
      got_id = 1;

    if (got_id)
    {
     /*
      * Extract the length of the device ID string from the first two
      * bytes.  The 1284 spec says the length is stored MSB first...
      */

      length = (int)((((unsigned)device_id[0] & 255) << 8) + ((unsigned)device_id[1] & 255));

     /*
      * Check to see if the length is larger than our buffer; first
      * assume that the vendor incorrectly implemented the 1284 spec,
      * and then limit the length to the size of our buffer...
      */

      if (length > device_id_size || length < 14)
	length = (int)((((unsigned)device_id[1] & 255) << 8) + ((unsigned)device_id[0] & 255));

      if (length > device_id_size)
	length = device_id_size;

     /*
      * The length field counts the number of bytes in the string
      * including the length field itself (2 bytes).  The minimum
      * length for a valid/usable device ID is 14 bytes:
      *
      *     <LENGTH> MFG: <MFG> ;MDL: <MDL> ;
      *        2  +   4  +  1  +  5 +  1 +  1
      */

      if (length < 14)
      {
       /*
	* Can't use this device ID, so don't try to copy it...
	*/

	device_id[0] = '\0';
	got_id       = 0;
      }
      else
      {
       /*
	* Copy the device ID text to the beginning of the buffer and
	* nul-terminate.
	*/

	length -= 2;

	memmove(device_id, device_id + 2, (size_t)length);
	device_id[length] = '\0';
      }
    }
    else
    {
      DEBUG_printf(("backendGetDeviceID: ioctl failed - %s\n",
                    strerror(errno)));
      *device_id = '\0';
    }
#  endif /* __linux */

#   if defined(__sun) && defined(ECPPIOC_GETDEVID)
    did.mode = ECPP_CENTRONICS;
    did.len  = device_id_size - 1;
    did.rlen = 0;
    did.addr = device_id;

    if (!ioctl(fd, ECPPIOC_GETDEVID, &did))
    {
     /*
      * Nul-terminate the device ID text.
      */

      if (did.rlen < (device_id_size - 1))
	device_id[did.rlen] = '\0';
      else
	device_id[device_id_size - 1] = '\0';
    }
#    ifdef DEBUG
    else
      DEBUG_printf(("backendGetDeviceID: ioctl failed - %s\n",
                    strerror(errno)));
#    endif /* DEBUG */
#  endif /* __sun && ECPPIOC_GETDEVID */
  }

 /*
  * Check whether device ID is valid. Turn line breaks and tabs to spaces and
  * reject device IDs with non-printable characters.
  */

  for (ptr = device_id; *ptr; ptr ++)
    if (_cups_isspace(*ptr))
      *ptr = ' ';
    else if ((*ptr & 255) < ' ' || *ptr == 127)
    {
      DEBUG_printf(("backendGetDeviceID: Bad device_id character %d.",
                    *ptr & 255));
      *device_id = '\0';
      break;
    }

  DEBUG_printf(("backendGetDeviceID: device_id=\"%s\"\n", device_id));

  if (scheme && uri)
    *uri = '\0';

  if (!*device_id)
    return (-1);

 /*
  * Get the make and model...
  */

  if (make_model)
    backendGetMakeModel(device_id, make_model, (size_t)make_model_size);

 /*
  * Then generate a device URI...
  */

  if (scheme && uri && uri_size > 32)
  {
    int			num_values;	/* Number of keys and values */
    cups_option_t	*values;	/* Keys and values in device ID */
    const char		*mfg,		/* Manufacturer */
			*mdl,		/* Model */
			*sern;		/* Serial number */
    char		temp[256],	/* Temporary manufacturer string */
			*tempptr;	/* Pointer into temp string */


   /*
    * Get the make, model, and serial numbers...
    */

    num_values = _cupsGet1284Values(device_id, &values);

    if ((sern = cupsGetOption("SERIALNUMBER", num_values, values)) == NULL)
      if ((sern = cupsGetOption("SERN", num_values, values)) == NULL)
        sern = cupsGetOption("SN", num_values, values);

    if ((mfg = cupsGetOption("MANUFACTURER", num_values, values)) == NULL)
      mfg = cupsGetOption("MFG", num_values, values);

    if ((mdl = cupsGetOption("MODEL", num_values, values)) == NULL)
      mdl = cupsGetOption("MDL", num_values, values);

    if (mfg)
    {
      if (!_cups_strcasecmp(mfg, "Hewlett-Packard"))
        mfg = "HP";
      else if (!_cups_strcasecmp(mfg, "Lexmark International"))
        mfg = "Lexmark";
    }
    else
    {
      strlcpy(temp, make_model, sizeof(temp));

      if ((tempptr = strchr(temp, ' ')) != NULL)
        *tempptr = '\0';

      mfg = temp;
    }

    if (!mdl)
      mdl = "";

    if (!_cups_strncasecmp(mdl, mfg, strlen(mfg)))
    {
      mdl += strlen(mfg);

      while (isspace(*mdl & 255))
        mdl ++;
    }

   /*
    * Generate the device URI from the manufacturer, make_model, and
    * serial number strings.
    */

    httpAssembleURIf(HTTP_URI_CODING_ALL, uri, uri_size, scheme, NULL, mfg, 0,
                     "/%s%s%s", mdl, sern ? "?serial=" : "", sern ? sern : "");

    cupsFreeOptions(num_values, values);
  }

  return (0);
#endif /* __APPLE__ */
}
Пример #15
0
int					/* O - Number of key/value pairs */
_cupsGet1284Values(
    const char *device_id,		/* I - IEEE-1284 device ID string */
    cups_option_t **values)		/* O - Array of key/value pairs */
{
  int		num_values;		/* Number of values */
  char		key[256],		/* Key string */
		value[256],		/* Value string */
		*ptr;			/* Pointer into key/value */


 /*
  * Range check input...
  */

  if (values)
    *values = NULL;

  if (!device_id || !values)
    return (0);

 /*
  * Parse the 1284 device ID value into keys and values.  The format is
  * repeating sequences of:
  *
  *   [whitespace]key:value[whitespace];
  */

  num_values = 0;
  while (*device_id)
  {
    while (_cups_isspace(*device_id))
      device_id ++;

    if (!*device_id)
      break;

    for (ptr = key; *device_id && *device_id != ':'; device_id ++)
      if (ptr < (key + sizeof(key) - 1))
        *ptr++ = *device_id;

    if (!*device_id)
      break;

    while (ptr > key && _cups_isspace(ptr[-1]))
      ptr --;

    *ptr = '\0';
    device_id ++;

    while (_cups_isspace(*device_id))
      device_id ++;

    if (!*device_id)
      break;

    for (ptr = value; *device_id && *device_id != ';'; device_id ++)
      if (ptr < (value + sizeof(value) - 1))
        *ptr++ = *device_id;

    if (!*device_id)
      break;

    while (ptr > value && _cups_isspace(ptr[-1]))
      ptr --;

    *ptr = '\0';
    device_id ++;

    num_values = cupsAddOption(key, value, num_values, values);
  }

  return (num_values);
}
Пример #16
0
const char *				/* O - Value or NULL if not found */
ppdLocalizeIPPReason(
    ppd_file_t *ppd,			/* I - PPD file */
    const char *reason,			/* I - IPP reason keyword to look up */
    const char *scheme,			/* I - URI scheme or NULL for text */
    char       *buffer,			/* I - Value buffer */
    size_t     bufsize)			/* I - Size of value buffer */
{
  cups_lang_t	*lang;			/* Current language */
  ppd_attr_t	*locattr;		/* Localized attribute */
  char		ll_CC[6],		/* Language + country locale */
		*bufptr,		/* Pointer into buffer */
		*bufend,		/* Pointer to end of buffer */
		*valptr;		/* Pointer into value */
  int		ch;			/* Hex-encoded character */
  size_t	schemelen;		/* Length of scheme name */


 /*
  * Range check input...
  */

  if (buffer)
    *buffer = '\0';

  if (!ppd || !reason || (scheme && !*scheme) ||
      !buffer || bufsize < PPD_MAX_TEXT)
    return (NULL);

 /*
  * Get the default language...
  */

  lang = ppd_ll_CC(ll_CC, sizeof(ll_CC));

 /*
  * Find the localized attribute...
  */

  if ((locattr = _ppdLocalizedAttr(ppd, "cupsIPPReason", reason,
                                   ll_CC)) == NULL)
    locattr = ppdFindAttr(ppd, "cupsIPPReason", reason);

  if (!locattr)
  {
    if (lang && (!scheme || !strcmp(scheme, "text")))
    {
     /*
      * Try to localize a standard printer-state-reason keyword...
      */

      const char *message = NULL;	/* Localized message */

      if (!strncmp(reason, "media-needed", 12))
	message = _("Load paper.");
      else if (!strncmp(reason, "media-jam", 9))
	message = _("Paper jam.");
      else if (!strncmp(reason, "offline", 7) ||
		       !strncmp(reason, "shutdown", 8))
	message = _("The printer is not connected.");
      else if (!strncmp(reason, "toner-low", 9))
	message = _("The printer is low on toner.");
      else if (!strncmp(reason, "toner-empty", 11))
	message = _("The printer may be out of toner.");
      else if (!strncmp(reason, "cover-open", 10))
	message = _("The printer's cover is open.");
      else if (!strncmp(reason, "interlock-open", 14))
	message = _("The printer's interlock is open.");
      else if (!strncmp(reason, "door-open", 9))
	message = _("The printer's door is open.");
      else if (!strncmp(reason, "input-tray-missing", 18))
	message = _("Paper tray is missing.");
      else if (!strncmp(reason, "media-low", 9))
	message = _("Paper tray is almost empty.");
      else if (!strncmp(reason, "media-empty", 11))
	message = _("Paper tray is empty.");
      else if (!strncmp(reason, "output-tray-missing", 19))
	message = _("Output bin is missing.");
      else if (!strncmp(reason, "output-area-almost-full", 23))
	message = _("Output bin is almost full.");
      else if (!strncmp(reason, "output-area-full", 16))
	message = _("Output bin is full.");
      else if (!strncmp(reason, "marker-supply-low", 17))
	message = _("The printer is low on ink.");
      else if (!strncmp(reason, "marker-supply-empty", 19))
	message = _("The printer may be out of ink.");
      else if (!strncmp(reason, "marker-waste-almost-full", 24))
	message = _("The printer's waste bin is almost full.");
      else if (!strncmp(reason, "marker-waste-full", 17))
	message = _("The printer's waste bin is full.");
      else if (!strncmp(reason, "fuser-over-temp", 15))
	message = _("The fuser's temperature is high.");
      else if (!strncmp(reason, "fuser-under-temp", 16))
	message = _("The fuser's temperature is low.");
      else if (!strncmp(reason, "opc-near-eol", 12))
	message = _("The optical photoconductor will need to be replaced soon.");
      else if (!strncmp(reason, "opc-life-over", 13))
	message = _("The optical photoconductor needs to be replaced.");
      else if (!strncmp(reason, "developer-low", 13))
	message = _("The developer unit will need to be replaced soon.");
      else if (!strncmp(reason, "developer-empty", 15))
	message = _("The developer unit needs to be replaced.");

      if (message)
      {
        strlcpy(buffer, _cupsLangString(lang, message), bufsize);
	return (buffer);
      }
    }

    return (NULL);
  }

 /*
  * Now find the value we need...
  */

  bufend = buffer + bufsize - 1;

  if (!scheme || !strcmp(scheme, "text"))
  {
   /*
    * Copy a text value (either the translation text or text:... URIs from
    * the value...
    */

    strlcpy(buffer, locattr->text, bufsize);

    for (valptr = locattr->value, bufptr = buffer; *valptr && bufptr < bufend;)
    {
      if (!strncmp(valptr, "text:", 5))
      {
       /*
        * Decode text: URI and add to the buffer...
	*/

	valptr += 5;

        while (*valptr && !_cups_isspace(*valptr) && bufptr < bufend)
	{
	  if (*valptr == '%' && isxdigit(valptr[1] & 255) &&
	      isxdigit(valptr[2] & 255))
	  {
	   /*
	    * Pull a hex-encoded character from the URI...
	    */

            valptr ++;

	    if (isdigit(*valptr & 255))
	      ch = (*valptr - '0') << 4;
	    else
	      ch = (tolower(*valptr) - 'a' + 10) << 4;
	    valptr ++;

	    if (isdigit(*valptr & 255))
	      *bufptr++ = (char)(ch | (*valptr - '0'));
	    else
	      *bufptr++ = (char)(ch | (tolower(*valptr) - 'a' + 10));
	    valptr ++;
	  }
	  else if (*valptr == '+')
	  {
	    *bufptr++ = ' ';
	    valptr ++;
	  }
	  else
	    *bufptr++ = *valptr++;
        }
      }
      else
      {
       /*
        * Skip this URI...
	*/

        while (*valptr && !_cups_isspace(*valptr))
          valptr++;
      }

     /*
      * Skip whitespace...
      */

      while (_cups_isspace(*valptr))
	valptr ++;
    }

    if (bufptr > buffer)
      *bufptr = '\0';

    return (buffer);
  }
  else
  {
   /*
    * Copy a URI...
    */

    schemelen = strlen(scheme);
    if (scheme[schemelen - 1] == ':')	/* Force scheme to be just the name */
      schemelen --;

    for (valptr = locattr->value, bufptr = buffer; *valptr && bufptr < bufend;)
    {
      if ((!strncmp(valptr, scheme, schemelen) && valptr[schemelen] == ':') ||
          (*valptr == '/' && !strcmp(scheme, "file")))
      {
       /*
        * Copy URI...
	*/

        while (*valptr && !_cups_isspace(*valptr) && bufptr < bufend)
	  *bufptr++ = *valptr++;

	*bufptr = '\0';

	return (buffer);
      }
      else
      {
       /*
        * Skip this URI...
	*/

	while (*valptr && !_cups_isspace(*valptr))
	  valptr++;
      }

     /*
      * Skip whitespace...
      */

      while (_cups_isspace(*valptr))
	valptr ++;
    }

    return (NULL);
  }
}
Пример #17
0
int					/* O - 0 on success, -1 on failure */
ppdEmitJCL(ppd_file_t *ppd,		/* I - PPD file record */
           FILE       *fp,		/* I - File to write to */
           int        job_id,		/* I - Job ID */
	   const char *user,		/* I - Username */
	   const char *title)		/* I - Title */
{
  char		*ptr;			/* Pointer into JCL string */
  char		temp[65],		/* Local title string */
		displaymsg[33];		/* Local display string */


 /*
  * Range check the input...
  */

  if (!ppd || !ppd->jcl_begin || !ppd->jcl_ps)
    return (0);

 /*
  * See if the printer supports HP PJL...
  */

  if (!strncmp(ppd->jcl_begin, "\033%-12345X@", 10))
  {
   /*
    * This printer uses HP PJL commands for output; filter the output
    * so that we only have a single "@PJL JOB" command in the header...
    *
    * To avoid bugs in the PJL implementation of certain vendors' products
    * (Xerox in particular), we add a dummy "@PJL" command at the beginning
    * of the PJL commands to initialize PJL processing.
    */

    ppd_attr_t	*charset;		/* PJL charset */
    ppd_attr_t	*display;		/* PJL display command */


    if ((charset = ppdFindAttr(ppd, "cupsPJLCharset", NULL)) != NULL)
    {
      if (!charset->value || _cups_strcasecmp(charset->value, "UTF-8"))
        charset = NULL;
    }

    if ((display = ppdFindAttr(ppd, "cupsPJLDisplay", NULL)) != NULL)
    {
      if (!display->value)
        display = NULL;
    }

    fputs("\033%-12345X@PJL\n", fp);
    for (ptr = ppd->jcl_begin + 9; *ptr;)
      if (!strncmp(ptr, "@PJL JOB", 8))
      {
       /*
        * Skip job command...
	*/

        for (;*ptr; ptr ++)
	  if (*ptr == '\n')
	    break;

	if (*ptr)
	  ptr ++;
      }
      else
      {
       /*
        * Copy line...
	*/

        for (;*ptr; ptr ++)
	{
	  putc(*ptr, fp);
	  if (*ptr == '\n')
	    break;
	}

	if (*ptr)
	  ptr ++;
      }

   /*
    * Clean up the job title...
    */

    if ((ptr = strrchr(title, '/')) != NULL)
    {
     /*
      * Only show basename of file path...
      */

      title = ptr + 1;
    }

    if (!strncmp(title, "smbprn.", 7))
    {
     /*
      * Skip leading smbprn.######## from Samba jobs...
      */

      for (title += 7; *title && isdigit(*title & 255); title ++);
      while (_cups_isspace(*title))
        title ++;

      if ((ptr = strstr(title, " - ")) != NULL)
      {
       /*
	* Skip application name in "Some Application - Title of job"...
	*/

	title = ptr + 3;
      }
    }

   /*
    * Replace double quotes with single quotes and UTF-8 characters with
    * question marks so that the title does not cause a PJL syntax error.
    */

    strlcpy(temp, title, sizeof(temp));

    for (ptr = temp; *ptr; ptr ++)
      if (*ptr == '\"')
        *ptr = '\'';
      else if (!charset && (*ptr & 128))
        *ptr = '?';

   /*
    * CUPS STR #3125: Long PJL JOB NAME causes problems with some printers
    *
    * Generate the display message, truncating at 32 characters + nul to avoid
    * issues with some printer's PJL implementations...
    */

    snprintf(displaymsg, sizeof(displaymsg), "%d %s %s", job_id, user, temp);

   /*
    * Send PJL JOB and PJL RDYMSG commands before we enter PostScript mode...
    */

    if (display && strcmp(display->value, "job"))
      fprintf(fp, "@PJL JOB NAME = \"%s\"\n", temp);
    else if (display && !strcmp(display->value, "rdymsg"))
      fprintf(fp, "@PJL RDYMSG DISPLAY = \"%s\"\n", displaymsg);
    else
      fprintf(fp, "@PJL JOB NAME = \"%s\" DISPLAY = \"%s\"\n", temp,
	      displaymsg);

   /*
    * Replace double quotes with single quotes and UTF-8 characters with
    * question marks so that the user does not cause a PJL syntax error.
    */

    strlcpy(temp, user, sizeof(temp));

    for (ptr = temp; *ptr; ptr ++)
      if (*ptr == '\"')
        *ptr = '\'';
      else if (!charset && (*ptr & 128))
        *ptr = '?';

    fprintf(fp, "@PJL SET USERNAME = \"%s\"\n", temp);
  }
  else
    fputs(ppd->jcl_begin, fp);

  ppdEmit(ppd, fp, PPD_ORDER_JCL);
  fputs(ppd->jcl_ps, fp);

  return (0);
}
Пример #18
0
int					/* O  - Number of options */
_ppdParseOptions(
    const char    *s,			/* I  - String to parse */
    int           num_options,		/* I  - Number of options */
    cups_option_t **options,		/* IO - Options */
    _ppd_parse_t  which)		/* I  - What to parse */
{
  char	option[PPD_MAX_NAME * 2 + 1],	/* Current option/property */
	choice[PPD_MAX_NAME],		/* Current choice/value */
	*ptr;				/* Pointer into option or choice */


  if (!s)
    return (num_options);

 /*
  * Read all of the "*Option Choice" and "property value" pairs from the
  * string, add them to an options array as we go...
  */

  while (*s)
  {
   /*
    * Skip leading whitespace...
    */

    while (_cups_isspace(*s))
      s ++;

   /*
    * Get the option/property name...
    */

    ptr = option;
    while (*s && !_cups_isspace(*s) && ptr < (option + sizeof(option) - 1))
      *ptr++ = *s++;

    if (ptr == s || !_cups_isspace(*s))
      break;

    *ptr = '\0';

   /*
    * Get the choice...
    */

    while (_cups_isspace(*s))
      s ++;

    if (!*s)
      break;

    ptr = choice;
    while (*s && !_cups_isspace(*s) && ptr < (choice + sizeof(choice) - 1))
      *ptr++ = *s++;

    if (*s && !_cups_isspace(*s))
      break;

    *ptr = '\0';

   /*
    * Add it to the options array...
    */

    if (option[0] == '*' && which != _PPD_PARSE_PROPERTIES)
      num_options = cupsAddOption(option + 1, choice, num_options, options);
    else if (option[0] != '*' && which != _PPD_PARSE_OPTIONS)
      num_options = cupsAddOption(option, choice, num_options, options);
  }

  return (num_options);
}
Пример #19
0
static void
cups_set_ssl_options(
    _cups_client_conf_t *cc,		/* I - client.conf values */
    const char          *value)		/* I - Value */
{
 /*
  * SSLOptions [AllowRC4] [AllowSSL3] [AllowDH] [DenyTLS1.0] [None]
  */

  int	options = _HTTP_TLS_NONE,	/* SSL/TLS options */
	min_version = _HTTP_TLS_1_0,	/* Minimum SSL/TLS version */
	max_version = _HTTP_TLS_MAX;	/* Maximum SSL/TLS version */
  char	temp[256],			/* Copy of value */
	*start,				/* Start of option */
	*end;				/* End of option */


  strlcpy(temp, value, sizeof(temp));

  for (start = temp; *start; start = end)
  {
   /*
    * Find end of keyword...
    */

    end = start;
    while (*end && !_cups_isspace(*end))
      end ++;

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

   /*
    * Compare...
    */

    if (!_cups_strcasecmp(start, "AllowRC4"))
      options |= _HTTP_TLS_ALLOW_RC4;
    else if (!_cups_strcasecmp(start, "AllowSSL3"))
      min_version = _HTTP_TLS_SSL3;
    else if (!_cups_strcasecmp(start, "AllowDH"))
      options |= _HTTP_TLS_ALLOW_DH;
    else if (!_cups_strcasecmp(start, "DenyCBC"))
      options |= _HTTP_TLS_DENY_CBC;
    else if (!_cups_strcasecmp(start, "DenyTLS1.0"))
      min_version = _HTTP_TLS_1_1;
    else if (!_cups_strcasecmp(start, "MaxTLS1.0"))
      max_version = _HTTP_TLS_1_0;
    else if (!_cups_strcasecmp(start, "MaxTLS1.1"))
      max_version = _HTTP_TLS_1_1;
    else if (!_cups_strcasecmp(start, "MaxTLS1.2"))
      max_version = _HTTP_TLS_1_2;
    else if (!_cups_strcasecmp(start, "MaxTLS1.3"))
      max_version = _HTTP_TLS_1_3;
    else if (!_cups_strcasecmp(start, "MinTLS1.0"))
      min_version = _HTTP_TLS_1_0;
    else if (!_cups_strcasecmp(start, "MinTLS1.1"))
      min_version = _HTTP_TLS_1_1;
    else if (!_cups_strcasecmp(start, "MinTLS1.2"))
      min_version = _HTTP_TLS_1_2;
    else if (!_cups_strcasecmp(start, "MinTLS1.3"))
      min_version = _HTTP_TLS_1_3;
    else if (!_cups_strcasecmp(start, "None"))
      options = _HTTP_TLS_NONE;
  }

  cc->ssl_options     = options;
  cc->ssl_max_version = max_version;
  cc->ssl_min_version = min_version;

  DEBUG_printf(("4cups_set_ssl_options(cc=%p, value=\"%s\") options=%x, min_version=%d, max_version=%d", (void *)cc, value, options, min_version, max_version));
}