]> git.donarmstrong.com Git - debbugs.git/blobdiff - cgi/pkgreport.cgi
* Even though it's meaningless, fix the stupid ARRAY(0x...) printout
[debbugs.git] / cgi / pkgreport.cgi
index 734762f8956d7d337c4b1e59b8d8b964438fdb9c..673a2db9cba1891976b0c3c2c8de0f2b8b4a226a 100755 (executable)
 
 package debbugs;
 
+use warnings;
 use strict;
 use POSIX qw(strftime nice);
 
-require './common.pl';
-
 use Debbugs::Config qw(:globals :text :config);
 use Debbugs::User;
 use Debbugs::CGI qw(version_url maint_decode);
-use Debbugs::Common qw(getparsedaddrs :date make_list);
-use Debbugs::Bugs qw(get_bugs);
+use Debbugs::Common qw(getparsedaddrs :date make_list getmaintainers getpseudodesc);
+use Debbugs::Bugs qw(get_bugs bug_filter newest_bug);
 use Debbugs::Packages qw(getsrcpkgs getpkgsrc get_versions);
-use Debbugs::Status qw(get_bug_status);
+use Debbugs::Status qw(:status);
+use Debbugs::CGI qw(:all);
 
 use vars qw($gPackagePages $gWebDomain %gSeverityDisplay @gSeverityList);
 
@@ -34,23 +34,20 @@ if (defined $ENV{REQUEST_METHOD} and $ENV{REQUEST_METHOD} eq 'HEAD') {
 
 nice(5);
 
-my $userAgent = detect_user_agent();
-
 use CGI::Simple;
 my $q = new CGI::Simple;
-#my %param = readparse();
-
-my %param = cgi_parameters(query => $q,
-                          single => [qw(ordering archive repeatmerged),
-                                     qw(bug-rev pend-rev sev-rev),
-                                     qw(maxdays mindays version),
-                                     qw(data which dist),
-                                    ],
-                          default => {ordering => 'normal',
-                                      archive  => 0,
-                                      repeatmerged => 1,
-                                     },
-                         );
+
+our %param = cgi_parameters(query => $q,
+                           single => [qw(ordering archive repeatmerged),
+                                      qw(bug-rev pend-rev sev-rev),
+                                      qw(maxdays mindays version),
+                                      qw(data which dist newest),
+                                     ],
+                           default => {ordering => 'normal',
+                                       archive  => 0,
+                                       repeatmerged => 1,
+                                      },
+                          );
 
 # map from yes|no to 1|0
 for my $key (qw(repeatmerged bug-rev pend-rev sev-rev)) {
@@ -72,7 +69,6 @@ elsif (lc($param{archive}) eq 'yes') {
 }
 
 
-my $repeatmerged = ($param{'repeatmerged'} || "yes") eq "yes";
 my $archive = ($param{'archive'} || "no") eq "yes";
 my $include = $param{'&include'} || $param{'include'} || "";
 my $exclude = $param{'&exclude'} || $param{'exclude'} || "";
@@ -89,44 +85,50 @@ unless (defined $ordering) {
    $ordering = "raw" if $raw_sort;
    $ordering = 'age' if $age_sort;
 }
-my ($bug_order) = $ordering =~ /(age(?:rev)?)/;
+our ($bug_order) = $ordering =~ /(age(?:rev)?)/;
 $bug_order = '' if not defined $bug_order;
 
 my $bug_rev = ($param{'bug-rev'} || "no") eq "yes";
 my $pend_rev = ($param{'pend-rev'} || "no") eq "yes";
 my $sev_rev = ($param{'sev-rev'} || "no") eq "yes";
-my $pend_exc = $param{'&pend-exc'} || $param{'pend-exc'} || "";
-my $pend_inc = $param{'&pend-inc'} || $param{'pend-inc'} || "";
-my $sev_exc = $param{'&sev-exc'} || $param{'sev-exc'} || "";
-my $sev_inc = $param{'&sev-inc'} || $param{'sev-inc'} || "";
-my $maxdays = ($param{'maxdays'} || -1);
-my $mindays = ($param{'mindays'} || 0);
-my $version = $param{'version'} || undef;
-my $dist = $param{'dist'} || undef;
-my $arch = $param{'arch'} || undef;
-my $show_list_header = ($param{'show_list_header'} || $userAgent->{'show_list_header'} || "yes" ) eq "yes";
-my $show_list_footer = ($param{'show_list_footer'} || $userAgent->{'show_list_footer'} || "yes" ) eq "yes";
 
-{
-    if (defined $param{'vt'}) {
-        my $vt = $param{'vt'};
-        if ($vt eq "none") { $dist = undef; $arch = undef; $version = undef; }
-        if ($vt eq "bysuite") {
-            $version = undef;
-            $arch = undef if ($arch eq "any");
-        }
-        if ($vt eq "bypkg" || $vt eq "bysrc") { $dist = undef; $arch = undef; }
-    }
-    if (defined $param{'includesubj'}) {
-        my $is = $param{'includesubj'};
-        $include .= "," . join(",", map { "subj:$_" } (split /[\s,]+/, $is));
-    }
-    if (defined $param{'excludesubj'}) {
-        my $es = $param{'excludesubj'};
-        $exclude .= "," . join(",", map { "subj:$_" } (split /[\s,]+/, $es));
-    }
+my @inc_exc_mapping = ({name   => 'pending',
+                       incexc => 'include',
+                       key    => 'pend-inc',
+                      },
+                      {name   => 'pending',
+                       incexc => 'exclude',
+                       key    => 'pend-exc',
+                      },
+                      {name   => 'severity',
+                       incexc => 'include',
+                       key    => 'sev-inc',
+                      },
+                      {name   => 'severity',
+                       incexc => 'exclude',
+                       key    => 'sev-exc',
+                      },
+                      {name   => 'subject',
+                       incexc => 'include',
+                       key    => 'includesubj',
+                      },
+                      {name   => 'subject',
+                       incexc => 'exclude',
+                       key    => 'excludesubj',
+                      },
+                     );
+for my $incexcmap (@inc_exc_mapping) {
+     push @{$param{$incexcmap->{incexc}}}, map {"$incexcmap->{name}:$_"}
+         map{split /\s*,\s*/} make_list($param{$incexcmap->{key}})
+              if exists $param{$incexcmap->{key}};
+     delete $param{$incexcmap->{key}};
 }
 
+my $maxdays = ($param{'maxdays'} || -1);
+my $mindays = ($param{'mindays'} || 0);
+my $version = $param{'version'} || undef;
+# XXX Once the options/selection is rewritten, this should go away
+my $dist = $param{dist} || undef;
 
 our %hidden = map { $_, 1 } qw(status severity classification);
 our %cats = (
@@ -163,7 +165,7 @@ our %cats = (
 );
 
 my @select_key = (qw(submitter maint pkg package src usertag),
-                 qw(status tag maintenc owner)
+                 qw(status tag maintenc owner severity newest)
                 );
 
 if (exists $param{which} and exists $param{data}) {
@@ -199,20 +201,23 @@ for my $user (map {split /[\s*,\s*]+/} make_list($param{users}||[])) {
 }
 
 if (defined $param{usertag}) {
-    my %select_ut = ();
-    my ($u, $t) = split /:/, $param{usertag}, 2;
-    Debbugs::User::read_usertags(\%select_ut, $u);
-    unless (defined $t && $t ne "") {
-        $t = join(",", keys(%select_ut));
-    }
-
-    add_user($u);
-    push @{$param{tag}}, split /,/, $t;
+     for my $usertag (make_list($param{usertag})) {
+         my %select_ut = ();
+         my ($u, $t) = split /:/, $usertag, 2;
+         Debbugs::User::read_usertags(\%select_ut, $u);
+         unless (defined $t && $t ne "") {
+              $t = join(",", keys(%select_ut));
+         }
+         add_user($u);
+         push @{$param{tag}}, split /,/, $t;
+     }
 }
 
 my $Archived = $archive ? " Archived" : "";
 
-my $this = "";
+our $this = munge_url('pkgreport.cgi?',
+                     %param,
+                    );
 
 my %indexentry;
 my %strings = ();
@@ -250,7 +255,7 @@ sub add_user {
             push @{$bugusertags{$b}}, $t;
         }
     }
-    set_option("bugusertags", \%bugusertags);
+#    set_option("bugusertags", \%bugusertags);
 }
 
 my @bugs;
@@ -292,8 +297,6 @@ my %search_keys = @search_key_order;
 
 # Set the title sanely and clean up parameters
 my @title;
-use Data::Dumper;
-print STDERR Dumper(\%param);
 while (my ($key,$value) = splice @search_key_order, 0, 2) {
      next unless exists $param{$key};
      my @entries = ();
@@ -305,6 +308,7 @@ while (my ($key,$value) = splice @search_key_order, 0, 2) {
                                           (exists $param{dist}?(dist => $param{dist}):()),
                                           (exists $param{arch}?(arch => $param{arch}):()),
                                           ($key eq 'src'?(arch => q(source)):()),
+                                          no_source_arch => 1,
                                          );
               my $verdesc = join(', ',@versions);
               $verdesc = 'version'.(@versions>1?'s ':' ').$verdesc;
@@ -314,11 +318,11 @@ while (my ($key,$value) = splice @search_key_order, 0, 2) {
      }
      push @title,$value.' '.join(' or ', @entries);
 }
-my $title = join(' and ', map {/ or /?"($_)":$_} @title);
+my $title = $gBugs.' '.join(' and ', map {/ or /?"($_)":$_} @title);
 @title = ();
 
 # we have to special case the maint="" search, unfortunatly.
-if (defined $param{maint} and $param{maint} eq "") {
+if (defined $param{maint} and $param{maint} eq "" or ref($param{maint}) and not @{$param{maint}}) {
      my %maintainers = %{getmaintainers()};
      @bugs = get_bugs(function =>
                      sub {my %d=@_;
@@ -328,23 +332,29 @@ if (defined $param{maint} and $param{maint} eq "") {
                           return 0;
                      }
                     );
-     $title = 'in packages with no maintainer';
+     $title = $gBugs.' in packages with no maintainer';
+}
+elsif (defined $param{newest}) {
+     my $newest_bug = newest_bug();
+     @bugs = ($newest_bug - $param{newest} + 1) .. $newest_bug;
+     $title = @bugs.' newest '.$gBugs;
 }
 else {
      #yeah for magick!
-     @bugs = get_bugs(map {exists $param{$_}?($_,$param{$_}):()}
-                     keys %search_keys, 'archive'
+     @bugs = get_bugs((map {exists $param{$_}?($_,$param{$_}):()}
+                      keys %search_keys, 'archive'),
+                     usertags => \%ut,
                     );
 }
 
 if (defined $param{version}) {
-     $title .= " at version $version";
+     $title .= " at version $param{version}";
 }
 elsif (defined $param{dist}) {
-     $title .= " in $dist";
+     $title .= " in $param{dist}";
 }
 
-$title = htmlsanit($title);
+$title = html_escape($title);
 
 my @names; my @prior; my @order;
 determine_ordering();
@@ -365,7 +375,7 @@ print "<HTML><HEAD>\n" .
     "</HEAD>\n" .
     '<BODY onload="pagemain();">' .
     "\n";
-print "<H1>" . "$gProject$Archived $gBug report logs: $gBugs $title" .
+print "<H1>" . "$gProject$Archived $gBug report logs: $title" .
       "</H1>\n";
 
 my $showresult = 1;
@@ -389,12 +399,20 @@ for my $package (make_list($param{src}||[])) {
 
 sub output_package_info{
     my ($srcorbin,$package) = @_;
-    my $showpkg = htmlsanit($package);
+
+    my %pkgsrc = %{getpkgsrc()};
+    my $srcforpkg = $package;
+    if ($srcorbin eq 'binary') {
+        $srcforpkg = $pkgsrc{$package};
+        defined $srcforpkg or $srcforpkg = $package;
+    }
+
+    my $showpkg = html_escape($package);
     my $maintainers = getmaintainers();
-    my $maint = $maintainers->{$package};
+    my $maint = $maintainers->{$srcforpkg};
     if (defined $maint) {
         print '<p>';
-        print htmlmaintlinks(sub { $_[0] == 1 ? "Maintainer for $showpkg is "
+        print htmlize_maintlinks(sub { $_[0] == 1 ? "Maintainer for $showpkg is "
                                         : "Maintainers for $showpkg are "
                                    },
                              $maint);
@@ -402,12 +420,6 @@ sub output_package_info{
     } else {
         print "<p>No maintainer for $showpkg. Please do not report new bugs against this package.</p>\n";
     }
-    my %pkgsrc = %{getpkgsrc()};
-    my $srcforpkg = $package;
-    if ($srcorbin eq 'binary') {
-        $srcforpkg = $pkgsrc{$package};
-        defined $srcforpkg or $srcforpkg = $package;
-    }
     my @pkgs = getsrcpkgs($srcforpkg);
     @pkgs = grep( !/^\Q$package\E$/, @pkgs );
     if ( @pkgs ) {
@@ -418,7 +430,7 @@ sub output_package_info{
              print "<p>You may want to refer to the following individual bug pages:\n";
         }
         #push @pkgs, $src if ( $src && !grep(/^\Q$src\E$/, @pkgs) );
-        print join( ", ", map( "<A href=\"" . pkgurl($_) . "\">$_</A>", @pkgs ) );
+        print join( ", ", map( "<A href=\"" . html_escape(munge_url($this,package=>$_,src=>[],newest=>[])) . "\">$_</A>", @pkgs ) );
         print ".\n";
     }
     my @references;
@@ -429,7 +441,7 @@ sub output_package_info{
     } else {
         if ($package and defined $gPackagePages) {
              push @references, sprintf "to the <a href=\"%s\">%s package page</a>",
-                  urlsanit("http://${debbugs::gPackagePages}/$package"), htmlsanit("$package");
+                  html_escape("http://${debbugs::gPackagePages}/$package"), html_escape("$package");
         }
         if (defined $gSubscriptionDomain) {
              my $ptslink = $package ? $srcforpkg : $src;
@@ -437,7 +449,7 @@ sub output_package_info{
         }
         # Only output this if the source listing is non-trivial.
         if ($srcorbin eq 'binary' and $srcforpkg) {
-             push @references, sprintf "to the source package <a href=\"%s\">%s</a>'s bug page", srcurl($srcforpkg), htmlsanit($srcforpkg);
+             push @references, sprintf "to the source package <a href=\"%s\">%s</a>'s bug page", html_escape(munge_url($this,src=>$srcforpkg,package=>[],newest=>[])), html_escape($srcforpkg);
         }
     }
     if (@references) {
@@ -447,12 +459,11 @@ sub output_package_info{
     if (defined $param{maint} || defined $param{maintenc}) {
         print "<p>If you find a bug not listed here, please\n";
         printf "<a href=\"%s\">report it</a>.</p>\n",
-             urlsanit("http://${debbugs::gWebDomain}/Reporting${debbugs::gHTMLSuffix}");
+             html_escape("http://${debbugs::gWebDomain}/Reporting${debbugs::gHTMLSuffix}");
     }
     if (not $maint and not @bugs) {
-        print "<p>There is no record of the " .
-             ($srcorbin eq 'binary' ? htmlsanit($package) . " package"
-              : htmlsanit($src) . " source package").
+        print "<p>There is no record of the " . html_escape($package) .
+             ($srcorbin eq 'binary' ? " package" : " source package") .
                    ", and no bugs have been filed against it.</p>";
         $showresult = 0;
     }
@@ -478,7 +489,7 @@ my %archive_values = (both => 'archived and unarchived',
 while (my ($key,$value) = each %archive_values) {
      next if $key eq lc($param{archive});
      push @archive_links, qq(<a href=").
-         urlsanit(pkg_url((
+         html_escape(pkg_url((
                       map {
                            $_ eq 'archive'?():($_,$param{$_})
                       } keys %param),
@@ -511,27 +522,27 @@ print "<tr><td></td>";
 print "    <td><input id=\"b_1_2\" name=vt value=bysuite type=radio onchange=\"enable(1);\" $checked_sui>" . pkg_htmlselectsuite(1,2,1) . " for " . pkg_htmlselectarch(1,2,2) . "</td></tr>\n";
 
 if (defined $pkg) {
-    my $v = htmlsanit($version) || "";
-    my $pkgsane = htmlsanit($pkg);
+    my $v = html_escape($version) || "";
+    my $pkgsane = html_escape($pkg->[0]);
     print "<tr><td></td>";
     print "    <td><input id=\"b_1_3\" name=vt value=bypkg type=radio onchange=\"enable(1);\" $checked_ver>$pkgsane version <input id=\"b_1_3_1\" name=version value=\"$v\"></td></tr>\n";
 } elsif (defined $src) {
-    my $v = htmlsanit($version) || "";
-    my $srcsane = htmlsanit($src);
+    my $v = html_escape($version) || "";
+    my $srcsane = html_escape($src->[0]);
     print "<tr><td></td>";
     print "    <td><input name=vt value=bysrc type=radio onchange=\"enable(1);\" $checked_ver>$srcsane version <input id=\"b_1_3_1\" name=version value=\"$v\"></td></tr>\n";
 }
 print "<tr><td>&nbsp;</td></tr>\n";
 
-my $includetags = htmlsanit(join(" ", grep { !m/^subj:/i } map {split /[\s,]+/} ref($include)?@{$include}:$include));
-my $excludetags = htmlsanit(join(" ", grep { !m/^subj:/i } map {split /[\s,]+/} ref($exclude)?@{$exclude}:$exclude));
-my $includesubj = htmlsanit(join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } map {split /[\s,]+/} ref($include)?@{$include}:$include));
-my $excludesubj = htmlsanit(join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } map {split /[\s,]+/} ref($exclude)?@{$exclude}:$exclude));
+my $includetags = html_escape(join(" ", grep { !m/^subj:/i } map {split /[\s,]+/} ref($include)?@{$include}:$include));
+my $excludetags = html_escape(join(" ", grep { !m/^subj:/i } map {split /[\s,]+/} ref($exclude)?@{$exclude}:$exclude));
+my $includesubj = html_escape(join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } map {split /[\s,]+/} ref($include)?@{$include}:$include));
+my $excludesubj = html_escape(join(" ", map { s/^subj://i; $_ } grep { m/^subj:/i } map {split /[\s,]+/} ref($exclude)?@{$exclude}:$exclude));
 my $vismindays = ($mindays == 0 ? "" : $mindays);
 my $vismaxdays = ($maxdays == -1 ? "" : $maxdays);
 
-my $sel_rmy = ($repeatmerged ? " selected" : "");
-my $sel_rmn = ($repeatmerged ? "" : " selected");
+my $sel_rmy = ($param{repeatmerged} ? " selected" : "");
+my $sel_rmn = ($param{repeatmerged} ? "" : " selected");
 my $sel_ordraw = ($ordering eq "raw" ? " selected" : "");
 my $sel_ordold = ($ordering eq "oldview" ? " selected" : "");
 my $sel_ordnor = ($ordering eq "normal" ? " selected" : "");
@@ -623,13 +634,13 @@ sub pkg_htmlindexentrystatus {
     my $showversions = '';
     if (@{$status{found_versions}}) {
         my @found = @{$status{found_versions}};
-        $showversions .= join ', ', map {s{/}{ }; htmlsanit($_)} @found;
+        $showversions .= join ', ', map {s{/}{ }; html_escape($_)} @found;
     }
     if (@{$status{fixed_versions}}) {
         $showversions .= '; ' if length $showversions;
         $showversions .= '<strong>fixed</strong>: ';
         my @fixed = @{$status{fixed_versions}};
-        $showversions .= join ', ', map {s{/}{ }; htmlsanit($_)} @fixed;
+        $showversions .= join ', ', map {s{/}{ }; html_escape($_)} @fixed;
     }
     $result .= ' (<a href="'.
         version_url($status{package},
@@ -641,10 +652,10 @@ sub pkg_htmlindexentrystatus {
     $result .= $showseverity;
     $result .= pkg_htmladdresslinks("Reported by: ", \&submitterurl,
                                 $status{originator});
-    $result .= ";\nOwned by: " . htmlsanit($status{owner})
+    $result .= ";\nOwned by: " . html_escape($status{owner})
                if length $status{owner};
     $result .= ";\nTags: <strong>" 
-                 . htmlsanit(join(", ", sort(split(/\s+/, $status{tags}))))
+                 . html_escape(join(", ", sort(split(/\s+/, $status{tags}))))
                  . "</strong>"
                        if (length($status{tags}));
 
@@ -656,7 +667,7 @@ sub pkg_htmlindexentrystatus {
         split(/ /,$status{blocks}));
 
     if (length($status{done})) {
-        $result .= "<br><strong>Done:</strong> " . htmlsanit($status{done});
+        $result .= "<br><strong>Done:</strong> " . html_escape($status{done});
         my $days = bug_archiveable(bug => $status{id},
                                   status => \%status,
                                   days_until => 1,
@@ -737,16 +748,46 @@ sub pkg_htmlizebugs {
     );
 
     my %section = ();
+    # Make the include/exclude map
+    my %include;
+    my %exclude;
+    for my $include (make_list($param{include})) {
+        next unless defined $include;
+        my ($key,$value) = split /\s*:\s*/,$include,2;
+        unless (defined $value) {
+            $key = 'tags';
+            $value = $include;
+        }
+        push @{$include{$key}}, split /\s*,\s*/, $value;
+    }
+    for my $exclude (make_list($param{exclude})) {
+        next unless defined $exclude;
+        my ($key,$value) = split /\s*:\s*/,$exclude,2;
+        unless (defined $value) {
+            $key = 'tags';
+            $value = $exclude;
+        }
+        push @{$exclude{$key}}, split /\s*,\s*/, $value;
+    }
 
     foreach my $bug (@bugs) {
         my %status = %{get_bug_status(bug=>$bug,
                                      (exists $param{dist}?(dist => $param{dist}):()),
+                                     bugusertags => \%bugusertags,
+                                     (exists $param{version}?(version => $param{version}):()),
+                                     (exists $param{arch}?(arch => $param{arch}):()),
                                     )};
         next unless %status;
-        next if bugfilter($bug, %status);
+        next if bug_filter(bug => $bug,
+                          status => \%status,
+                          (exists $param{repeatmerged}?(repeat_merged => $param{repeatmerged}):()),
+                          seen_merged => \%seenmerged,
+                          (keys %include ? (include => \%include):()),
+                          (keys %exclude ? (exclude => \%exclude):()),
+                         );
 
        my $html = sprintf "<li><a href=\"%s\">#%d: %s</a>\n<br>",
-            bugurl($bug), $bug, htmlsanit($status{subject});
+            bug_url($bug), $bug, html_escape($status{subject});
         $html .= pkg_htmlindexentrystatus(\%status) . "\n";
        push @status, [ $bug, \%status, $html ];
     }
@@ -792,7 +833,7 @@ sub pkg_htmlizebugs {
                $title .= join("; ", grep {($_ || "") ne ""}
                        map { $title[$_]->[$ttl[$_]] } 1..$#ttl);
            }
-           $title = htmlsanit($title);
+           $title = html_escape($title);
 
             my $count = $count{"_$order"};
             my $bugs = $count == 1 ? "bug" : "bugs";
@@ -846,8 +887,8 @@ sub pkg_htmlpackagelinks {
     return 'Package' . (@pkglist > 1 ? 's' : '') . ': ' .
            join(', ',
                 map {
-                    '<a class="submitter" href="' . pkgurl($_) . '">' .
-                    $openstrong . htmlsanit($_) . $closestrong . '</a>'
+                    '<a class="submitter" href="' . munge_url($this,src=>[],package=>$_,newest=>[]) . '">' .
+                    $openstrong . html_escape($_) . $closestrong . '</a>'
                 } @pkglist
            );
 }
@@ -976,7 +1017,7 @@ sub pkg_htmlselectarch {
 }
 
 sub myurl {
-     return urlsanit(pkg_url(map {exists $param{$_}?($_,$param{$_}):()}
+     return html_escape(pkg_url(map {exists $param{$_}?($_,$param{$_}):()}
                             qw(archive repeatmerged mindays maxdays),
                             qw(version dist arch pkg src tag maint submitter)
                            )
@@ -1055,7 +1096,7 @@ sub determine_ordering {
         while (defined $param{"pri$i"}) {
             my $h = {};
 
-            my $pri = $param{"pri$i"};
+            my ($pri) = make_list($param{"pri$i"});
             if ($pri =~ m/^([^:]*):(.*)$/) {
               $h->{"nam"} = $1;  # overridden later if necesary
               $h->{"pri"} = [ map { "$1=$_" } (split /,/, $2) ];
@@ -1063,12 +1104,12 @@ sub determine_ordering {
               $h->{"pri"} = [ split /,/, $pri ];
             }
 
-           $h->{"nam"} = $param{"nam$i"}
-                if (defined $param{"nam$i"}); 
-            $h->{"ord"} = [ split /\s*,\s*/, $param{"ord$i"} ]
-                if (defined $param{"ord$i"}); 
-            $h->{"ttl"} = [ split /\s*,\s*/, $param{"ttl$i"} ]
-                if (defined $param{"ttl$i"}); 
+           ($h->{"nam"}) = make_list($param{"nam$i"})
+                if (defined $param{"nam$i"});
+            $h->{"ord"} = [ map {split /\s*,\s*/} make_list($param{"ord$i"}) ]
+                if (defined $param{"ord$i"});
+           $h->{"ttl"} = [ map {split /\s*,\s*/} make_list($param{"ttl$i"}) ]
+                if (defined $param{"ttl$i"});
 
             push @c, $h;
            $i++;