@@ -376,6 +376,7 @@ static const _ipp_option_t ipp_options[] =
376376 */
377377
378378static int compare_ipp_options (_ipp_option_t * a , _ipp_option_t * b );
379+ static void encode_options (ipp_t * ipp , int num_options , cups_option_t * options , ipp_tag_t group_tag , int depth );
379380
380381
381382/*
@@ -388,7 +389,8 @@ _cupsEncodeOption(
388389 ipp_tag_t group_tag , /* I - Group tag */
389390 _ipp_option_t * map , /* I - Option mapping, if any */
390391 const char * name , /* I - Attribute name */
391- const char * value ) /* I - Value */
392+ const char * value , /* I - Value */
393+ int depth ) /* I - Depth of values */
392394{
393395 int i , /* Looping var */
394396 count ; /* Number of values */
@@ -659,6 +661,19 @@ _cupsEncodeOption(
659661 * Collection value
660662 */
661663
664+ if (depth >= _CUPS_MAX_OPTION_DEPTH )
665+ {
666+ /*
667+ * Don't allow "infinite" recursion of collection values...
668+ */
669+
670+ if (copy )
671+ free (copy );
672+
673+ ippDeleteAttribute (ipp , attr );
674+ return (NULL );
675+ }
676+
662677 num_cols = cupsParseOptions (val , 0 , & cols );
663678 if ((collection = ippNew ()) == NULL )
664679 {
@@ -672,7 +687,7 @@ _cupsEncodeOption(
672687 }
673688
674689 ippSetCollection (ipp , & attr , i , collection );
675- cupsEncodeOptions2 (collection , num_cols , cols , IPP_TAG_JOB );
690+ encode_options (collection , num_cols , cols , IPP_TAG_JOB , depth + 1 );
676691 cupsFreeOptions (num_cols , cols );
677692 ippDelete (collection );
678693 break ;
@@ -701,7 +716,7 @@ cupsEncodeOption(ipp_t *ipp, /* I - IPP request/response */
701716 const char * name , /* I - Option name */
702717 const char * value ) /* I - Option string value */
703718{
704- return (_cupsEncodeOption (ipp , group_tag , _ippFindOption (name ), name , value ));
719+ return (_cupsEncodeOption (ipp , group_tag , _ippFindOption (name ), name , value , /*depth*/ 0 ));
705720}
706721
707722
@@ -747,11 +762,8 @@ cupsEncodeOptions2(
747762 cups_option_t * options , /* I - Options */
748763 ipp_tag_t group_tag ) /* I - Group to encode */
749764{
750- int i ; /* Looping var */
751765 char * val ; /* Pointer to option value */
752- cups_option_t * option ; /* Current option */
753766 ipp_op_t op ; /* Operation for this request */
754- const ipp_op_t * ops ; /* List of allowed operations */
755767
756768
757769 DEBUG_printf ("cupsEncodeOptions2(ipp=%p(%s), num_options=%d, options=%p, group_tag=%x)" , (void * )ipp , ipp ? ippOpString (ippGetOperation (ipp )) : "" , num_options , (void * )options , group_tag );
@@ -784,15 +796,100 @@ cupsEncodeOptions2(
784796 }
785797
786798 /*
787- * Then loop through the options...
799+ * Then encode the options...
800+ */
801+
802+ encode_options (ipp , num_options , options , group_tag , /*depth*/ 0 );
803+ }
804+
805+
806+ #ifdef DEBUG
807+ /*
808+ * '_ippCheckOptions()' - Validate that the option array is sorted properly.
809+ */
810+
811+ const char * /* O - First out-of-order option or NULL */
812+ _ippCheckOptions (void )
813+ {
814+ int i ; /* Looping var */
815+
816+
817+ for (i = 0 ; i < (int )(sizeof (ipp_options ) / sizeof (ipp_options [0 ]) - 1 ); i ++ )
818+ if (strcmp (ipp_options [i ].name , ipp_options [i + 1 ].name ) >= 0 )
819+ return (ipp_options [i + 1 ].name );
820+
821+ return (NULL );
822+ }
823+ #endif /* DEBUG */
824+
825+
826+ /*
827+ * '_ippFindOption()' - Find the attribute information for an option.
828+ */
829+
830+ _ipp_option_t * /* O - Attribute information */
831+ _ippFindOption (const char * name ) /* I - Option/attribute name */
832+ {
833+ _ipp_option_t key ; /* Search key */
834+
835+
836+ /*
837+ * Lookup the proper value and group tags for this option...
838+ */
839+
840+ key .name = name ;
841+
842+ return ((_ipp_option_t * )bsearch (& key , ipp_options ,
843+ sizeof (ipp_options ) / sizeof (ipp_options [0 ]),
844+ sizeof (ipp_options [0 ]),
845+ (int (* )(const void * , const void * ))
846+ compare_ipp_options ));
847+ }
848+
849+
850+ /*
851+ * 'compare_ipp_options()' - Compare two IPP options.
852+ */
853+
854+ static int /* O - Result of comparison */
855+ compare_ipp_options (_ipp_option_t * a , /* I - First option */
856+ _ipp_option_t * b ) /* I - Second option */
857+ {
858+ return (strcmp (a -> name , b -> name ));
859+ }
860+
861+
862+ /*
863+ * 'encode_options()' - Encode options to the specified depth.
864+ */
865+
866+ void
867+ encode_options (
868+ ipp_t * ipp , /* I - IPP request/response */
869+ int num_options , /* I - Number of options */
870+ cups_option_t * options , /* I - Options */
871+ ipp_tag_t group_tag , /* I - Group to encode */
872+ int depth ) /* I - Depth of options/collections */
873+ {
874+ int i ; /* Looping var */
875+ cups_option_t * option ; /* Current option */
876+ ipp_op_t op = ippGetOperation (ipp );
877+ /* Operation for this request */
878+ const ipp_op_t * ops ; /* List of allowed operations */
879+
880+
881+ DEBUG_printf ("4encode_options(ipp=%p(%s), num_options=%d, options=%p, group_tag=%x, depth=%d)" , (void * )ipp , ipp ? ippOpString (ippGetOperation (ipp )) : "" , num_options , (void * )options , group_tag , depth );
882+
883+ /*
884+ * Loop through the options...
788885 */
789886
790887 for (i = num_options , option = options ; i > 0 ; i -- , option ++ )
791888 {
792889 _ipp_option_t * match ; /* Matching attribute */
793890
794891 /*
795- * Skip document format options that are handled above ...
892+ * Skip document format options that are handled in cupsEncodeOptions2 ...
796893 */
797894
798895 if (!_cups_strcasecmp (option -> name , "raw" ) || !_cups_strcasecmp (option -> name , "document-format" ) || !option -> name [0 ])
@@ -819,7 +916,7 @@ cupsEncodeOptions2(
819916 ops = ipp_set_printer ;
820917 else
821918 {
822- DEBUG_printf ("2cupsEncodeOptions2 : Skipping \"%s\"." , option -> name );
919+ DEBUG_printf ("5encode_options : Skipping \"%s\"." , option -> name );
823920 continue ;
824921 }
825922 }
@@ -833,13 +930,13 @@ cupsEncodeOptions2(
833930 {
834931 if (group_tag != IPP_TAG_JOB && group_tag != IPP_TAG_DOCUMENT )
835932 {
836- DEBUG_printf ("2cupsEncodeOptions2 : Skipping \"%s\"." , option -> name );
933+ DEBUG_printf ("5encode_options : Skipping \"%s\"." , option -> name );
837934 continue ;
838935 }
839936 }
840937 else if (group_tag != IPP_TAG_PRINTER )
841938 {
842- DEBUG_printf ("2cupsEncodeOptions2 : Skipping \"%s\"." , option -> name );
939+ DEBUG_printf ("5encode_options : Skipping \"%s\"." , option -> name );
843940 continue ;
844941 }
845942
@@ -863,66 +960,10 @@ cupsEncodeOptions2(
863960
864961 if (* ops == IPP_OP_CUPS_NONE && op != IPP_OP_CUPS_NONE )
865962 {
866- DEBUG_printf ("2cupsEncodeOptions2 : Skipping \"%s\"." , option -> name );
963+ DEBUG_printf ("5encode_options : Skipping \"%s\"." , option -> name );
867964 continue ;
868965 }
869966
870- _cupsEncodeOption (ipp , group_tag , match , option -> name , option -> value );
967+ _cupsEncodeOption (ipp , group_tag , match , option -> name , option -> value , depth );
871968 }
872969}
873-
874-
875- #ifdef DEBUG
876- /*
877- * '_ippCheckOptions()' - Validate that the option array is sorted properly.
878- */
879-
880- const char * /* O - First out-of-order option or NULL */
881- _ippCheckOptions (void )
882- {
883- int i ; /* Looping var */
884-
885-
886- for (i = 0 ; i < (int )(sizeof (ipp_options ) / sizeof (ipp_options [0 ]) - 1 ); i ++ )
887- if (strcmp (ipp_options [i ].name , ipp_options [i + 1 ].name ) >= 0 )
888- return (ipp_options [i + 1 ].name );
889-
890- return (NULL );
891- }
892- #endif /* DEBUG */
893-
894-
895- /*
896- * '_ippFindOption()' - Find the attribute information for an option.
897- */
898-
899- _ipp_option_t * /* O - Attribute information */
900- _ippFindOption (const char * name ) /* I - Option/attribute name */
901- {
902- _ipp_option_t key ; /* Search key */
903-
904-
905- /*
906- * Lookup the proper value and group tags for this option...
907- */
908-
909- key .name = name ;
910-
911- return ((_ipp_option_t * )bsearch (& key , ipp_options ,
912- sizeof (ipp_options ) / sizeof (ipp_options [0 ]),
913- sizeof (ipp_options [0 ]),
914- (int (* )(const void * , const void * ))
915- compare_ipp_options ));
916- }
917-
918-
919- /*
920- * 'compare_ipp_options()' - Compare two IPP options.
921- */
922-
923- static int /* O - Result of comparison */
924- compare_ipp_options (_ipp_option_t * a , /* I - First option */
925- _ipp_option_t * b ) /* I - Second option */
926- {
927- return (strcmp (a -> name , b -> name ));
928- }
0 commit comments