diff --git a/cups/ipp-file.c b/cups/ipp-file.c index 153cdab0..bd040835 100644 --- a/cups/ipp-file.c +++ b/cups/ipp-file.c @@ -85,7 +85,7 @@ _ippFileParse( { _ippVarsExpand(v, value, temp, sizeof(value)); _ippVarsSet(v, name, value); - } + } } else { @@ -93,6 +93,24 @@ _ippFileParse( break; } } + else if (f.attrs && !_cups_strcasecmp(token, "GROUP")) + { + char syntax[128]; /* Attribute syntax (value tag) */ + ipp_tag_t group_tag; /* Group tag */ + + if (!_ippFileReadToken(&f, syntax, sizeof(syntax))) + { + report_error(&f, v, user_data, "Missing GROUP syntax on line %d of \"%s\".", f.linenum, f.filename); + break; + } + else if ((group_tag = ippTagValue(syntax)) > IPP_TAG_SYSTEM || group_tag < IPP_TAG_ZERO ) + { + report_error(&f, v, user_data, "Bad GROUP syntax \"%s\" on line %d of \"%s\".", syntax, f.linenum, f.filename); + break; + } + f.group_tag = group_tag; + } + else if (f.attrs && !_cups_strcasecmp(token, "ATTR")) { /* @@ -100,7 +118,8 @@ _ippFileParse( */ char syntax[128], /* Attribute syntax (value tag) */ - name[128]; /* Attribute name */ + name[128], /* Attribute name */ + syntax_value[128]; /*Variable Expanded Value*/ ipp_tag_t value_tag; /* Value tag */ attr = NULL; @@ -110,7 +129,9 @@ _ippFileParse( report_error(&f, v, user_data, "Missing ATTR syntax on line %d of \"%s\".", f.linenum, f.filename); break; } - else if ((value_tag = ippTagValue(syntax)) < IPP_TAG_UNSUPPORTED_VALUE) + _ippVarsExpand(v, syntax_value, syntax, sizeof(syntax_value)); + + if ((value_tag = ippTagValue(syntax_value)) < IPP_TAG_UNSUPPORTED_VALUE) { report_error(&f, v, user_data, "Bad ATTR syntax \"%s\" on line %d of \"%s\".", syntax, f.linenum, f.filename); break; @@ -142,7 +163,7 @@ _ippFileParse( attrs = ignored; } - if (value_tag < IPP_TAG_INTEGER) + if (value_tag < IPP_TAG_INTEGER-1) { /* * Add out-of-band attribute - no value string needed... @@ -163,6 +184,7 @@ _ippFileParse( } } + else if (attr && !_cups_strcasecmp(token, ",")) { /* @@ -170,7 +192,7 @@ _ippFileParse( */ if (!parse_value(&f, v, user_data, attrs, &attr, ippGetCount(attr))) - break; + break; } else { @@ -357,15 +379,15 @@ _ippFileReadToken(_ipp_file_t *f, /* I - File to read from */ if ((ch = cupsFileGetChar(f->fp)) == EOF) { - *token = '\0'; - DEBUG_puts("1_ippFileReadToken: EOF"); - return (0); - } - else if (ch == '\n') - { - f->linenum ++; - DEBUG_printf(("1_ippFileReadToken: quoted LF, linenum=%d, pos=%ld", f->linenum, (long)cupsFileTell(f->fp))); - } + *token = '\0'; + DEBUG_puts("1_ippFileReadToken: EOF"); + return (0); + } + else if (ch == '\n') + { + f->linenum ++; + DEBUG_printf(("1_ippFileReadToken: quoted LF, linenum=%d, pos=%ld", f->linenum, (long)cupsFileTell(f->fp))); + } } if (tokptr < tokend) @@ -438,7 +460,8 @@ parse_collection( */ char syntax[128], /* Attribute syntax (value tag) */ - name[128]; /* Attribute name */ + name[128], /* Attribute name */ + syntax_value[128]; /*Variable Expanded Value*/ ipp_tag_t value_tag; /* Value tag */ attr = NULL; @@ -449,8 +472,10 @@ parse_collection( ippDelete(col); col = NULL; break; + } - else if ((value_tag = ippTagValue(syntax)) < IPP_TAG_UNSUPPORTED_VALUE) + _ippVarsExpand(v, syntax_value, syntax, sizeof(syntax_value)); + if ((value_tag = ippTagValue(syntax_value)) < IPP_TAG_UNSUPPORTED_VALUE) { report_error(f, v, user_data, "Bad ATTR syntax \"%s\" on line %d of \"%s\".", syntax, f->linenum, f->filename); ippDelete(col); @@ -466,7 +491,7 @@ parse_collection( break; } - if (value_tag < IPP_TAG_INTEGER) + if (value_tag < IPP_TAG_INTEGER-1) { /* * Add out-of-band attribute - no value string needed... @@ -537,6 +562,7 @@ parse_value(_ipp_file_t *f, /* I - IPP data file */ { char value[1024], /* Value string */ temp[1024]; /* Temporary string */ + ipp_tag_t value_tag; if (!_ippFileReadToken(f, temp, sizeof(temp))) @@ -547,7 +573,22 @@ parse_value(_ipp_file_t *f, /* I - IPP data file */ _ippVarsExpand(v, value, temp, sizeof(value)); - switch (ippGetValueTag(*attr)) +/* value_tag processing to support unassigned tag values */ + value_tag = ippGetValueTag(*attr); + if (value_tag == 0x20 || (value_tag >= 0x24 && value_tag <= 0x2f)) + value_tag = IPP_TAG_INTEGER; + else + if (value_tag >= 0x38 && value_tag <= 0x3f) + value_tag = IPP_TAG_STRING; + else + if (value_tag == 0x40 || (value_tag >= 0x4b && value_tag <= 0x5f)) + value_tag = IPP_TAG_RESERVED_STRING; + else + if (value_tag >= 0x40000000 && value_tag <= 0x7fffffff) + value_tag = IPP_TAG_STRING; + + + switch (value_tag) { case IPP_TAG_BOOLEAN : return (ippSetBoolean(ipp, attr, element, !_cups_strcasecmp(value, "true"))); @@ -587,7 +628,7 @@ parse_value(_ipp_file_t *f, /* I - IPP data file */ { utc_offset = -utc_offset; date[8] = (ipp_uchar_t)'-'; - } + } else { date[8] = (ipp_uchar_t)'+'; @@ -644,19 +685,80 @@ parse_value(_ipp_file_t *f, /* I - IPP data file */ break; case IPP_TAG_STRING : - return (ippSetOctetString(ipp, attr, element, value, (int)strlen(value))); + { + if(value[0]=='<') /* Input is binary(in form of hex) values*/ + { + unsigned char data[32767], *dataptr = data; /*data: decoded hex, dataptr:iterating pointer */ + char *valptr = value + 1; /*Value iterating pointer*/ + while (1) + { + while (isxdigit(valptr[0]) && isxdigit(valptr[1])) + { + char c = tolower(valptr[0]), d=tolower(valptr[1]); + + /*decode hex pair into 8 bit string */ + *dataptr = (d>='a')?(10+d-'a'):(d-'0') | (c>= 'a') ? ((10+c -'a') << 4) : ((c-'0') <<4); + valptr += 2; + dataptr ++; + if (dataptr >= (data + sizeof(data))) + break; + } + if (*valptr == '>') + break; + else if (*valptr) /*If string is not in pairs, or has a non-hex digit*/ + { + report_error(f, v, user_data, "Bad hexadecimal value \"%s\" on line %d of \"%s\".", value+1, f->linenum, f->filename); + return (0); + } + if (!_ippFileReadToken(f, value, sizeof(value))) + { + report_error(f, v, user_data, "Missing value on line %d of \"%s\".", f->linenum, f->filename); + return (0); + } + valptr = value; + } + return (ippSetOctetString(ipp, attr, element, data, (int) (dataptr-data))); + } + + else + { + return (ippSetOctetString(ipp, attr, element, value, (int)strlen(value))); + + } + } + break; case IPP_TAG_TEXTLANG : case IPP_TAG_NAMELANG : + { + (*attr)->values[element].string.text = _cupsStrAlloc(value); + if (!_ippFileReadToken(f, value, sizeof(value))) + { + report_error(f, v, user_data, "No Language Data in line %d of \"%s\".", f->linenum, f->filename); + return (0); + } + if (!(value[0] == '(' && value[strlen(value)-1] == ')')) + { + report_error(f, v, user_data, "Bad Language Value in line %d of \"%s\".", f->linenum, f->filename); + return (0); + } + memmove(value, value+1, strlen(value)); + value[strlen(value)-1]='\0'; /* Purge parenthesis */ + (*attr)->values[element].string.language = _cupsStrAlloc(value); + + } + break; case IPP_TAG_TEXT : case IPP_TAG_NAME : + case IPP_TAG_RESERVED_STRING : case IPP_TAG_KEYWORD : case IPP_TAG_URI : case IPP_TAG_URISCHEME : case IPP_TAG_CHARSET : case IPP_TAG_LANGUAGE : case IPP_TAG_MIMETYPE : + case IPP_TAG_MEMBERNAME : return (ippSetString(ipp, attr, element, value)); break; diff --git a/cups/ipp-support.c b/cups/ipp-support.c index 47a64550..06e65c9f 100644 --- a/cups/ipp-support.c +++ b/cups/ipp-support.c @@ -358,7 +358,28 @@ static const char * const ipp_std_ops[] = "charset", /* 0x47 */ "naturalLanguage", /* 0x48 */ "mimeMediaType", /* 0x49 */ - "memberAttrName" /* 0x4a */ + "memberAttrName", /* 0x4a */ + "0x4b", /* 0x4b */ + "0x4c", /* 0x4c */ + "0x4d", /* 0x4d */ + "0x4e", /* 0x4e */ + "0x4f", /* 0x4f */ + "0x50", /* 0x50 */ + "0x51", /* 0x51 */ + "0x52", /* 0x52 */ + "0x53", /* 0x53 */ + "0x54", /* 0x54 */ + "0x55", /* 0x55 */ + "0x56", /* 0x56 */ + "0x57", /* 0x57 */ + "0x58", /* 0x58 */ + "0x59", /* 0x59 */ + "0x5a", /* 0x5a */ + "0x5b", /* 0x5b */ + "0x5c", /* 0x5c */ + "0x5d", /* 0x5d */ + "0x5e", /* 0x5e */ + "0x5f" /* 0x5f */ }; static const char * const ipp_document_states[] = { /* document-state-enums */ @@ -2461,7 +2482,19 @@ ipp_tag_t /* O - Tag value */ ippTagValue(const char *name) /* I - Tag name */ { size_t i; /* Looping var */ - + int itr, /* Name iterator*/ + flag = 0, /*Integer detector*/ + hex_val = 0; /*Convert hex to int */ + for(itr = 0; itr < strlen(name) ; itr++) + { + if(!(name[itr] >= '0'&& name[itr]<='9')) + { + flag = 1; + break; + } + } + if(flag == 0) + return ((ipp_tag_t)atoi(name)); for (i = 0; i < (sizeof(ipp_tag_names) / sizeof(ipp_tag_names[0])); i ++) if (!_cups_strcasecmp(name, ipp_tag_names[i])) @@ -2489,9 +2522,39 @@ ippTagValue(const char *name) /* I - Tag name */ return (IPP_TAG_TEXT); else if (!_cups_strcasecmp(name, "begCollection")) return (IPP_TAG_BEGIN_COLLECTION); - else - return (IPP_TAG_ZERO); -} + else { + /* Detecting hex string of the form "0x********" between 0x40000000" and 0x7fffffff*/ + flag = 0, itr = 0; + if(strlen(name) == 10 && name[0] == '0' && name [1]== 'x' ) + { + hex_val = 0; + for(itr = 2; itr < strlen(name) ; itr++) + { + char c_flag = tolower(name[itr]); + if (!(( c_flag >= 'a' && c_flag <= 'f' )|| ( c_flag >= '0' && c_flag <= '9'))) + { + flag = 1; + break; + } + else + { + hex_val = hex_val*16 + ((c_flag >= 'a' && c_flag <= 'f') ? (c_flag - 'a') : (c_flag - '0')); + } + } + if( flag == 0 && name[2] >= '4' && name[2] <= '7') + flag = 0; + else + flag = 1; + } + else + flag = 1; + + if(flag == 0) + return hex_val; + else + return (IPP_TAG_ZERO); + } + } /* diff --git a/cups/ipp.c b/cups/ipp.c index 325de02b..09efc2a8 100644 --- a/cups/ipp.c +++ b/cups/ipp.c @@ -547,6 +547,64 @@ ippAddOctetString(ipp_t *ipp, /* I - IPP message */ return (attr); } +/* + * 'ippAddOctetString2()' - Add unspecified format octetString value tag(0x30) to an IPP message. + * Or Add Vendor Extension (0x40000000 to 0x7fffffff) to an IPP message. + * + * The @code ipp@ parameter refers to an IPP message previously created using + * the @link ippNew@, @link ippNewRequest@, or @link ippNewResponse@ functions. + * + * The @code group@ parameter specifies the IPP attribute group tag: none + * (@code IPP_TAG_ZERO@, for member attributes), document (@code IPP_TAG_DOCUMENT@), + * event notification (@code IPP_TAG_EVENT_NOTIFICATION@), operation + * (@code IPP_TAG_OPERATION@), printer (@code IPP_TAG_PRINTER@), subscription + * (@code IPP_TAG_SUBSCRIPTION@), or unsupported (@code IPP_TAG_UNSUPPORTED_GROUP@). + * + * @since CUPS 1.2/macOS 10.5@ + */ + +ipp_attribute_t * /* O - New attribute */ +ippAddOctetString2(ipp_t *ipp, /* I - IPP message */ + ipp_tag_t group, /* I - IPP group */ + ipp_tag_t value_tag, /* I - Type of attribute */ + const char *name, /* I - Name of attribute */ + const void *data, /* I - octetString data */ + int datalen) /* I - Length of data in bytes */ +{ + ipp_attribute_t *attr; /* New attribute */ + + + if (!ipp || !name || group < IPP_TAG_ZERO || + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + datalen < 0 || datalen > IPP_MAX_LENGTH) + return (NULL); + + if ((attr = ipp_add_attr(ipp, name, group, value_tag, 1)) == NULL) + return (NULL); + + /* + * Initialize the attribute data... + */ + + attr->values[0].unknown.length = datalen; + + if (data) + { + if ((attr->values[0].unknown.data = malloc((size_t)datalen)) == NULL) + { + ippDeleteAttribute(ipp, attr); + return (NULL); + } + + memcpy(attr->values[0].unknown.data, data, (size_t)datalen); + } + + /* + * Return the new attribute... + */ + + return (attr); +} /* * 'ippAddOutOfBand()' - Add an out-of-band value to an IPP message. @@ -2311,11 +2369,18 @@ int /* O - Value or 0 on error */ ippGetInteger(ipp_attribute_t *attr, /* I - IPP attribute */ int element) /* I - Value number (0-based) */ { + + /* Support Unassigned Value Tags*/ + + ipp_tag_t pvalue_tag = (attr)->value_tag; + + if (pvalue_tag == 0x20 || (pvalue_tag >= 0x24 && pvalue_tag <= 0x2f)) + pvalue_tag = IPP_TAG_INTEGER; /* * Range check input... */ - if (!attr || (attr->value_tag != IPP_TAG_INTEGER && attr->value_tag != IPP_TAG_ENUM) || + if (!attr || (pvalue_tag != IPP_TAG_INTEGER && pvalue_tag != IPP_TAG_ENUM) || element < 0 || element >= attr->num_values) return (0); @@ -2366,11 +2431,17 @@ ippGetOctetString( int element, /* I - Value number (0-based) */ int *datalen) /* O - Length of octetString data */ { + + /* Support Unassigned Values*/ + ipp_tag_t pvalue_tag = (attr)->value_tag; + + if ((pvalue_tag >= 0x38 && pvalue_tag <= 0x3f)|| (pvalue_tag >= 0x40000000 && pvalue_tag <= 0x7fffffff)) + pvalue_tag = IPP_TAG_STRING; /* * Range check input... */ - if (!attr || attr->value_tag != IPP_TAG_STRING || + if (!attr || pvalue_tag != IPP_TAG_STRING || element < 0 || element >= attr->num_values) { if (datalen) @@ -2593,7 +2664,7 @@ ippGetString(ipp_attribute_t *attr, /* I - IPP attribute */ tag = ippGetValueTag(attr); - if (!attr || element < 0 || element >= attr->num_values || (tag != IPP_TAG_TEXTLANG && tag != IPP_TAG_NAMELANG && (tag < IPP_TAG_TEXT || tag > IPP_TAG_MIMETYPE))) + if (!attr || element < 0 || element >= attr->num_values || tag < 0x40 || tag > 0x5f ) return (NULL); /* @@ -3921,13 +3992,18 @@ ippSetInteger(ipp_t *ipp, /* I - IPP message */ { _ipp_value_t *value; /* Current value */ +/* Support Unassigned Value Tags*/ + + ipp_tag_t pvalue_tag = (*attr)->value_tag; + + if (pvalue_tag == 0x20 || (pvalue_tag >= 0x24 && pvalue_tag <= 0x2f)) + pvalue_tag = IPP_TAG_INTEGER; /* * Range check input... */ - - if (!ipp || !attr || !*attr || - ((*attr)->value_tag != IPP_TAG_INTEGER && (*attr)->value_tag != IPP_TAG_ENUM) || + if (!ipp || !attr || !*attr || + (pvalue_tag != IPP_TAG_INTEGER && pvalue_tag != IPP_TAG_ENUM) || element < 0 || element > (*attr)->num_values) return (0); @@ -4008,12 +4084,17 @@ ippSetOctetString( { _ipp_value_t *value; /* Current value */ + /* Support Unassigned Values*/ + ipp_tag_t pvalue_tag = (*attr)->value_tag; + + if ((pvalue_tag >= 0x38 && pvalue_tag <= 0x3f)|| (pvalue_tag >= 0x40000000 && pvalue_tag <= 0x7fffffff)) + pvalue_tag = IPP_TAG_STRING; /* * Range check input... */ - if (!ipp || !attr || !*attr || (*attr)->value_tag != IPP_TAG_STRING || + if (!ipp || !attr || !*attr || pvalue_tag != IPP_TAG_STRING || element < 0 || element > (*attr)->num_values || datalen < 0 || datalen > IPP_MAX_LENGTH) return (0); @@ -4324,10 +4405,10 @@ ippSetString(ipp_t *ipp, /* I - IPP message */ else value_tag = IPP_TAG_ZERO; + if (!ipp || !attr || !*attr || - (value_tag < IPP_TAG_TEXT && value_tag != IPP_TAG_TEXTLANG && - value_tag != IPP_TAG_NAMELANG) || value_tag > IPP_TAG_MIMETYPE || - !strvalue) + (value_tag < 0x40 || value_tag > 0x5f) || + !strvalue) return (0); /*