Skip to content

Commit

Permalink
Add cupsParseOptions2.
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelrsweet committed Oct 19, 2024
1 parent 37db6e2 commit 5e16813
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 96 deletions.
1 change: 1 addition & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ Changes in CUPS v2.5b1 (TBA)
- Added a systemd slice to the systemd services included with the scheduler
- Added localizations for deprecated IPP attributes/options (Issue #1020)
- Added support for specifying permissions with the `cupsFileOpen` API.
- Added new `cupsParseOptions2` API with "end" argument.
- Updated documents (Issue #984)
- Updated CUPS to require TLS support - OpenSSL, GNUTLS and LibreSSL are
supported.
Expand Down
1 change: 1 addition & 0 deletions cups/cups.h
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ extern char *cupsNotifySubject(cups_lang_t *lang, ipp_t *event) _CUPS_DEPRECATE
extern char *cupsNotifyText(cups_lang_t *lang, ipp_t *event) _CUPS_DEPRECATED_MSG("Use cupsLocalizeNotifyText instead.");

extern int cupsParseOptions(const char *arg, int num_options, cups_option_t **options) _CUPS_PUBLIC;
extern int cupsParseOptions2(const char *arg, const char **end, int num_options, cups_option_t **options) _CUPS_PUBLIC;
extern int cupsPrintFile(const char *name, const char *filename, const char *title, int num_options, cups_option_t *options) _CUPS_PUBLIC;
extern int cupsPrintFile2(http_t *http, const char *name, const char *filename, const char *title, int num_options, cups_option_t *options) _CUPS_PUBLIC;
extern int cupsPrintFiles(const char *name, int num_files, const char **files, const char *title, int num_options, cups_option_t *options) _CUPS_PUBLIC;
Expand Down
17 changes: 17 additions & 0 deletions cups/libcups2.def
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ _cupsCharmapFlush
_cupsConnect
_cupsConvertOptions
_cupsCreateDest
_cupsDirCreate
_cupsEncodeOption
_cupsEncodingName
_cupsFilePeekAhead
Expand Down Expand Up @@ -359,6 +360,7 @@ cupsLangGet
cupsLastError
cupsLastErrorString
cupsLocalizeDestMedia
cupsLocalizeDestMedia2
cupsLocalizeDestOption
cupsLocalizeDestValue
cupsMarkOptions
Expand All @@ -368,7 +370,21 @@ cupsMutexLock
cupsMutexUnlock
cupsNotifySubject
cupsNotifyText
cupsOAuthClearTokens
cupsOAuthCopyAccessToken
cupsOAuthCopyClientId
cupsOAuthCopyRefreshToken
cupsOAuthCopyUserId
cupsOAuthGetAuthorizationCode
cupsOAuthGetClientId
cupsOAuthGetMetadata
cupsOAuthGetTokens
cupsOAuthMakeAuthorizationURL
cupsOAuthMakeBase64Random
cupsOAuthSaveClientData
cupsOAuthSaveTokens
cupsParseOptions
cupsParseOptions2
cupsPrintFile
cupsPrintFile2
cupsPrintFiles
Expand Down Expand Up @@ -481,6 +497,7 @@ httpConnect
httpConnect2
httpConnectAgain
httpConnectEncrypt
httpConnectURI
httpCopyPeerCredentials
httpDecode64
httpDecode64_2
Expand Down
164 changes: 68 additions & 96 deletions cups/options.c
Original file line number Diff line number Diff line change
Expand Up @@ -259,131 +259,115 @@ cupsParseOptions(
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 */
return (cupsParseOptions2(arg, /*end*/NULL, num_options, options));
}


DEBUG_printf("cupsParseOptions(arg=\"%s\", num_options=%d, options=%p)", arg, num_options, (void *)options);
//
// 'cupsParseOptions2()' - Parse options from a command-line argument.
//
// This function converts space-delimited name/value pairs according
// to the PAPI text option ABNF specification. Collection values
// ("name={a=... b=... c=...}") are stored with the curley brackets
// intact - use @code cupsParseOptions@ on the value to extract the
// collection attributes.
//
// The "end" argument, if not `NULL`, receives a pointer to the end of the
// options.
//
// @since CUPS 2.5@
//

int // O - Number of options found
cupsParseOptions2(
const char *arg, // I - Argument to parse
const char **end, // O - Pointer to end of options or `NULL` for "don't care"
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

/*
* Range check input...
*/

// Range check input...
if (end)
*end = NULL;

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

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

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

// 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);
DEBUG_puts("1cupsParseOptions2: Unable to copy arg string");
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;
}
ptr = copyarg + 1;
else
ptr = copyarg;

/*
* Skip leading spaces...
*/

// Skip leading spaces...
while (_cups_isspace(*ptr))
ptr ++;

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

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

// 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...
*/

// Avoid an empty name...
if (ptr == name)
break;

/*
* Skip trailing spaces...
*/
// End after the closing brace...
if (*ptr == '}' && *copyarg == '{')
{
ptr ++;
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...
*/

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

continue;
}

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

// Remove = and parse the value...
value = ptr;

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

// Quoted string constant...
quote = *ptr;
_cups_strcpy(ptr, ptr + 1);

Expand All @@ -400,16 +384,15 @@ cupsParseOptions(
}
else if (*ptr == '{')
{
/*
* Collection value...
*/

int depth;
// Collection value...
int depth; // Nesting depth for braces

for (depth = 0; *ptr; ptr ++)
{
if (*ptr == '{')
{
depth ++;
}
else if (*ptr == '}')
{
depth --;
Expand All @@ -420,15 +403,14 @@ cupsParseOptions(
}
}
else if (*ptr == '\\' && ptr[1])
{
_cups_strcpy(ptr, ptr + 1);
}
}
}
else
{
/*
* Normal space-delimited string...
*/

// Normal space-delimited string...
while (*ptr && !_cups_isspace(*ptr))
{
if (*ptr == '\\' && ptr[1])
Expand All @@ -442,31 +424,21 @@ cupsParseOptions(
if (*ptr != '\0')
*ptr++ = '\0';

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

/*
* Skip trailing whitespace...
*/

// Skip trailing whitespace...
while (_cups_isspace(*ptr))
ptr ++;

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

// 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.
*/
// Save the progress in the input string...
if (end)
*end = arg + (ptr - copyarg);

// 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);
}

Expand Down

0 comments on commit 5e16813

Please sign in to comment.