@@ -378,6 +378,7 @@ static const _ipp_option_t ipp_options[] =
378378 */
379379
380380static int compare_ipp_options (_ipp_option_t * a , _ipp_option_t * b );
381+ static void encode_options (ipp_t * ipp , int num_options , cups_option_t * options , ipp_tag_t group_tag , int depth );
381382
382383
383384/*
@@ -390,7 +391,8 @@ _cupsEncodeOption(
390391 ipp_tag_t group_tag , /* I - Group tag */
391392 _ipp_option_t * map , /* I - Option mapping, if any */
392393 const char * name , /* I - Attribute name */
393- const char * value ) /* I - Value */
394+ const char * value , /* I - Value */
395+ int depth ) /* I - Depth of values */
394396{
395397 int i , /* Looping var */
396398 count ; /* Number of values */
@@ -643,6 +645,19 @@ _cupsEncodeOption(
643645 * Collection value
644646 */
645647
648+ if (depth >= _CUPS_MAX_OPTION_DEPTH )
649+ {
650+ /*
651+ * Don't allow "infinite" recursion of collection values...
652+ */
653+
654+ if (copy )
655+ free (copy );
656+
657+ ippDeleteAttribute (ipp , attr );
658+ return (NULL );
659+ }
660+
646661 num_cols = cupsParseOptions (val , 0 , & cols );
647662 if ((collection = ippNew ()) == NULL )
648663 {
@@ -656,7 +671,7 @@ _cupsEncodeOption(
656671 }
657672
658673 ippSetCollection (ipp , & attr , i , collection );
659- cupsEncodeOptions2 (collection , num_cols , cols , IPP_TAG_JOB );
674+ encode_options (collection , num_cols , cols , IPP_TAG_JOB , depth + 1 );
660675 cupsFreeOptions (num_cols , cols );
661676 ippDelete (collection );
662677 break ;
@@ -686,7 +701,7 @@ cupsEncodeOption(ipp_t *ipp, /* I - IPP request/response */
686701 const char * name , /* I - Option name */
687702 const char * value ) /* I - Option string value */
688703{
689- return (_cupsEncodeOption (ipp , group_tag , _ippFindOption (name ), name , value ));
704+ return (_cupsEncodeOption (ipp , group_tag , _ippFindOption (name ), name , value , /*depth*/ 0 ));
690705}
691706
692707
@@ -732,11 +747,8 @@ cupsEncodeOptions2(
732747 cups_option_t * options , /* I - Options */
733748 ipp_tag_t group_tag ) /* I - Group to encode */
734749{
735- int i ; /* Looping var */
736750 char * val ; /* Pointer to option value */
737- cups_option_t * option ; /* Current option */
738751 ipp_op_t op ; /* Operation for this request */
739- const ipp_op_t * ops ; /* List of allowed operations */
740752
741753
742754 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 ));
@@ -769,15 +781,100 @@ cupsEncodeOptions2(
769781 }
770782
771783 /*
772- * Then loop through the options...
784+ * Then encode the options...
785+ */
786+
787+ encode_options (ipp , num_options , options , group_tag , /*depth*/ 0 );
788+ }
789+
790+
791+ #ifdef DEBUG
792+ /*
793+ * '_ippCheckOptions()' - Validate that the option array is sorted properly.
794+ */
795+
796+ const char * /* O - First out-of-order option or NULL */
797+ _ippCheckOptions (void )
798+ {
799+ int i ; /* Looping var */
800+
801+
802+ for (i = 0 ; i < (int )(sizeof (ipp_options ) / sizeof (ipp_options [0 ]) - 1 ); i ++ )
803+ if (strcmp (ipp_options [i ].name , ipp_options [i + 1 ].name ) >= 0 )
804+ return (ipp_options [i + 1 ].name );
805+
806+ return (NULL );
807+ }
808+ #endif /* DEBUG */
809+
810+
811+ /*
812+ * '_ippFindOption()' - Find the attribute information for an option.
813+ */
814+
815+ _ipp_option_t * /* O - Attribute information */
816+ _ippFindOption (const char * name ) /* I - Option/attribute name */
817+ {
818+ _ipp_option_t key ; /* Search key */
819+
820+
821+ /*
822+ * Lookup the proper value and group tags for this option...
823+ */
824+
825+ key .name = name ;
826+
827+ return ((_ipp_option_t * )bsearch (& key , ipp_options ,
828+ sizeof (ipp_options ) / sizeof (ipp_options [0 ]),
829+ sizeof (ipp_options [0 ]),
830+ (int (* )(const void * , const void * ))
831+ compare_ipp_options ));
832+ }
833+
834+
835+ /*
836+ * 'compare_ipp_options()' - Compare two IPP options.
837+ */
838+
839+ static int /* O - Result of comparison */
840+ compare_ipp_options (_ipp_option_t * a , /* I - First option */
841+ _ipp_option_t * b ) /* I - Second option */
842+ {
843+ return (strcmp (a -> name , b -> name ));
844+ }
845+
846+
847+ /*
848+ * 'encode_options()' - Encode options to the specified depth.
849+ */
850+
851+ void
852+ encode_options (
853+ ipp_t * ipp , /* I - IPP request/response */
854+ int num_options , /* I - Number of options */
855+ cups_option_t * options , /* I - Options */
856+ ipp_tag_t group_tag , /* I - Group to encode */
857+ int depth ) /* I - Depth of options/collections */
858+ {
859+ int i ; /* Looping var */
860+ cups_option_t * option ; /* Current option */
861+ ipp_op_t op = ippGetOperation (ipp );
862+ /* Operation for this request */
863+ const ipp_op_t * ops ; /* List of allowed operations */
864+
865+
866+ 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 ));
867+
868+ /*
869+ * Loop through the options...
773870 */
774871
775872 for (i = num_options , option = options ; i > 0 ; i -- , option ++ )
776873 {
777874 _ipp_option_t * match ; /* Matching attribute */
778875
779876 /*
780- * Skip document format options that are handled above ...
877+ * Skip document format options that are handled in cupsEncodeOptions2 ...
781878 */
782879
783880 if (!_cups_strcasecmp (option -> name , "raw" ) || !_cups_strcasecmp (option -> name , "document-format" ) || !option -> name [0 ])
@@ -804,7 +901,7 @@ cupsEncodeOptions2(
804901 ops = ipp_set_printer ;
805902 else
806903 {
807- DEBUG_printf (("2cupsEncodeOptions2 : Skipping \"%s\"." , option -> name ));
904+ DEBUG_printf (("5encode_options : Skipping \"%s\"." , option -> name ));
808905 continue ;
809906 }
810907 }
@@ -818,13 +915,13 @@ cupsEncodeOptions2(
818915 {
819916 if (group_tag != IPP_TAG_JOB && group_tag != IPP_TAG_DOCUMENT )
820917 {
821- DEBUG_printf (("2cupsEncodeOptions2 : Skipping \"%s\"." , option -> name ));
918+ DEBUG_printf (("5encode_options : Skipping \"%s\"." , option -> name ));
822919 continue ;
823920 }
824921 }
825922 else if (group_tag != IPP_TAG_PRINTER )
826923 {
827- DEBUG_printf (("2cupsEncodeOptions2 : Skipping \"%s\"." , option -> name ));
924+ DEBUG_printf (("5encode_options : Skipping \"%s\"." , option -> name ));
828925 continue ;
829926 }
830927
@@ -848,66 +945,10 @@ cupsEncodeOptions2(
848945
849946 if (* ops == IPP_OP_CUPS_NONE && op != IPP_OP_CUPS_NONE )
850947 {
851- DEBUG_printf (("2cupsEncodeOptions2 : Skipping \"%s\"." , option -> name ));
948+ DEBUG_printf (("5encode_options : Skipping \"%s\"." , option -> name ));
852949 continue ;
853950 }
854951
855- _cupsEncodeOption (ipp , group_tag , match , option -> name , option -> value );
952+ _cupsEncodeOption (ipp , group_tag , match , option -> name , option -> value , depth );
856953 }
857954}
858-
859-
860- #ifdef DEBUG
861- /*
862- * '_ippCheckOptions()' - Validate that the option array is sorted properly.
863- */
864-
865- const char * /* O - First out-of-order option or NULL */
866- _ippCheckOptions (void )
867- {
868- int i ; /* Looping var */
869-
870-
871- for (i = 0 ; i < (int )(sizeof (ipp_options ) / sizeof (ipp_options [0 ]) - 1 ); i ++ )
872- if (strcmp (ipp_options [i ].name , ipp_options [i + 1 ].name ) >= 0 )
873- return (ipp_options [i + 1 ].name );
874-
875- return (NULL );
876- }
877- #endif /* DEBUG */
878-
879-
880- /*
881- * '_ippFindOption()' - Find the attribute information for an option.
882- */
883-
884- _ipp_option_t * /* O - Attribute information */
885- _ippFindOption (const char * name ) /* I - Option/attribute name */
886- {
887- _ipp_option_t key ; /* Search key */
888-
889-
890- /*
891- * Lookup the proper value and group tags for this option...
892- */
893-
894- key .name = name ;
895-
896- return ((_ipp_option_t * )bsearch (& key , ipp_options ,
897- sizeof (ipp_options ) / sizeof (ipp_options [0 ]),
898- sizeof (ipp_options [0 ]),
899- (int (* )(const void * , const void * ))
900- compare_ipp_options ));
901- }
902-
903-
904- /*
905- * 'compare_ipp_options()' - Compare two IPP options.
906- */
907-
908- static int /* O - Result of comparison */
909- compare_ipp_options (_ipp_option_t * a , /* I - First option */
910- _ipp_option_t * b ) /* I - Second option */
911- {
912- return (strcmp (a -> name , b -> name ));
913- }
0 commit comments