From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 1006 invoked from network); 29 Sep 2002 19:06:27 -0000 Received: from unknown (HELO monty-python.gnu.org) (199.232.76.173) by sources.redhat.com with SMTP; 29 Sep 2002 19:06:27 -0000 Received: from localhost ([127.0.0.1] helo=monty-python.gnu.org) by monty-python.gnu.org with esmtp (Exim 4.10) id 17vjOI-0004yB-00; Sun, 29 Sep 2002 15:06:06 -0400 Received: from list by monty-python.gnu.org with tmda-scanned (Exim 4.10) id 17vjNj-0004rx-00 for help-gnats@gnu.org; Sun, 29 Sep 2002 15:05:31 -0400 Received: from mail by monty-python.gnu.org with spam-scanned (Exim 4.10) id 17vjNf-0004og-00 for help-gnats@gnu.org; Sun, 29 Sep 2002 15:05:30 -0400 Received: from cluster2.netman.dk ([193.88.72.48]) by monty-python.gnu.org with esmtp (Exim 4.10) id 17vjNf-0004mQ-00 for help-gnats@gnu.org; Sun, 29 Sep 2002 15:05:27 -0400 Received: (from lh@localhost) by cluster2.netman.dk (8.11.4/8.11.4) id g8TJ2hb1305088; Sun, 29 Sep 2002 21:02:43 +0200 (MEST) From: Lars Henriksen To: Yngve Svendsen Cc: Robert Lupton the Good , help-gnats@gnu.org Subject: Re: Patch for gnatsweb.pl Message-ID: <20020929190243.GA1302741@cluster2.netman.dk> References: <20020922184733.GA1071317@cluster2.netman.dk> <15749.57217.976539.558063@wire7.Princeton.EDU> <20020922184733.GA1071317@cluster2.netman.dk> <5.1.0.14.2.20020925174747.044096d0@romulus.holland.sun.com> <20020925181413.GA1154909@cluster2.netman.dk> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="AqsLC8rIMeq19msA" Content-Disposition: inline In-Reply-To: <20020925181413.GA1154909@cluster2.netman.dk> User-Agent: Mutt/1.4i Sender: help-gnats-admin@gnu.org Errors-To: help-gnats-admin@gnu.org X-BeenThere: help-gnats@gnu.org X-Mailman-Version: 2.0.11 Precedence: bulk List-Help: List-Post: List-Subscribe: , List-Id: General discussion about GNU GNATS List-Archive: Date: Mon, 30 Sep 2002 02:07:00 -0000 X-SW-Source: 2002-q3/txt/msg00139.txt.bz2 --AqsLC8rIMeq19msA Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 2118 On Wed, Sep 25, 2002 at 08:14:14PM +0200, Lars Henriksen wrote: > On Wed, Sep 25, 2002 at 05:59:53PM +0200, Yngve Svendsen wrote: > > At 17:39 25.09.2002 +0200, Lars Henriksen wrote: > > >Do we want to (must we) keep backward combatibility? > > > While working with the recent "Sort By" patches, I had occasion to look > > more closely at this. Compatibility with stored Gnatsweb 2 queries is a > > non-issue I think. There are a few sites I know of that use Gnatsweb 3.99.x > > in production (Dirk, this probably concerns you), but if we are ever to rid > > Gnatsweb of this totally unnecessary level of complexity, this is the time. snip.. > > I think I'll use my Supreme Maintainer Authority to decree that field2param > > and param2field must die. > > Fine. That implies that the query expression logic in submitquery() must be > corrected since it depends on case differences. > > > Relevant patches are very welcome, since I have somewhat limited time to > > code right now Attached is my attempt at eliminating the field/parameter/upper-case/lower-case conversions from gnatsweb. Our friends field2param() and param2field() have gone: gnatsweb uses dbconfig field names exclusively (this is somewhat ironic since gnatsd happily accepts category for Category, etc.). With this patch gnatsweb is NOT backwards compatible, neither with versions 2.* nor 3.*: 1) Stored and bookmarked queries may no longer work or may return different results (all field names are now exact dbconfig field names). 2) submitquery() uses anchored regexp searches (^ and $) for enumerated types. For list box selection this leads to the expected result; for regular expression queries (advanced queries) it still leaves the possibility of inserting suitable ".*". This isn't the best possible solution, but one requiring only a small change in the code. I prefer postponing a better one (divide and conquer). 3) Field related callbacks (sendpr() and edit()) must have their "reason" adjusted to use dbconfig field names. The patch is against the current HEAD (revison 1.101). Regards Lars Henriksen --AqsLC8rIMeq19msA Content-Type: text/plain; charset=us-ascii Content-Description: gnatsweb context diff Content-Disposition: attachment; filename=xx Content-length: 23140 Index: gnatsweb.pl =================================================================== RCS file: /cvsroot/gnatsweb/gnatsweb/gnatsweb.pl,v retrieving revision 1.101 diff -c -p -r1.101 gnatsweb.pl *** gnatsweb.pl 24 Sep 2002 20:39:17 -0000 1.101 --- gnatsweb.pl 29 Sep 2002 17:56:01 -0000 *************** sub sendpr *** 1040,1046 **** { next; } - my $lc_fieldname = field2param($_); $field_number++; --- 1040,1045 ---- *************** sub sendpr *** 1051,1057 **** # The "intro" provides a way for the site callback to print something # at the top of a given field. ! my $intro = cb("sendpr_intro_$lc_fieldname", $field_number) || ''; print "$_:
\n", fieldinfo($_, 'desc'), --- 1050,1056 ---- # The "intro" provides a way for the site callback to print something # at the top of a given field. ! my $intro = cb("sendpr_intro_$_", $field_number) || ''; print "$_:
\n", fieldinfo($_, 'desc'), *************** sub edit *** 1525,1531 **** { next; } - my $lc_fieldname = field2param($_); $field_number++; --- 1524,1529 ---- *************** sub edit *** 1533,1539 **** # The "intro" provides a way for the site callback to print something # at the top of a given field. ! my $intro = cb("edit_intro_$lc_fieldname", $field_number) || ''; print "$_:
\n", fieldinfo($_, 'desc'), "\n", $intro, "\n"; --- 1531,1537 ---- # The "intro" provides a way for the site callback to print something # at the top of a given field. ! my $intro = cb("edit_intro_$_", $field_number) || ''; print "$_:
\n", fieldinfo($_, 'desc'), "\n", $intro, "\n"; *************** sub query_page *** 1840,1888 **** -values=>['Originated by You'], -defaults=>[]), "\n\n", ! "\nSynopsis Search:\n", ! $q->textfield(-name=>'synopsis',-size=>25), "\n\n", "\nMulti-line Text Search:\n", $q->textfield(-name=>'multitext',-size=>25), "\n\n", "\nColumn Display:\n"; ! # We operate internally with parameter names, not real-world ! # fieldnames (see dtb's comment in field2param()). This is for ! # backward compatibility and should be dealt with properly at some ! # point by making Gnatsweb use the fieldnames set in dbconfig ! # exclusively (XXX ??? !!! FIXME). We want to use real fieldnames ! # in the query page, so we construct a hash of (param , fieldname) ! # pairs to use in the scrolling_list. We also construct an array of ! # param names (@lcfields) which is fed to the scrolling_list in ! # order to keep the "natural" order of the fields. Merely using ! # keys() would cause fields to be listed in arbitrary order. ! my @lcfields; ! my %labels; ! foreach (@fieldnames) ! { ! if (fieldinfo($_, 'fieldtype') ne 'multitext') ! { ! my $param = field2param($_); ! $labels{$param} = $_; ! push (@lcfields, field2param($_)); } } ! ! my(@columns) = split(' ', $global_prefs{'columns'} || ''); ! @columns = keys(%labels) unless @columns; ! ! # The 'number' field is always first in the @lcfields array. If # users were allowed to select it in this list, the PR number would # appear twice in the Query Results table. We prevent this by # shifting 'number' out of the array. ! my(@sh_lcfields) = @lcfields; ! shift(@sh_lcfields); print $q->scrolling_list(-name=>'columns', ! -values=>\@sh_lcfields, ! -labels=>\%labels, -defaults=>\@columns, -multiple=>1, -size=>5), --- 1838,1868 ---- -values=>['Originated by You'], -defaults=>[]), "\n\n", ! "\n$SYNOPSIS_FIELD Search:\n", ! $q->textfield(-name=>$SYNOPSIS_FIELD,-size=>25), "\n\n", "\nMulti-line Text Search:\n", $q->textfield(-name=>'multitext',-size=>25), "\n\n", "\nColumn Display:\n"; ! my @allcolumns; ! foreach (@fieldnames) { ! if (fieldinfo($_, 'fieldtype') ne 'multitext') { ! push (@allcolumns, $_); } } ! # The 'number' field is always first in the @allcolumns array. If # users were allowed to select it in this list, the PR number would # appear twice in the Query Results table. We prevent this by # shifting 'number' out of the array. ! shift(@allcolumns); ! ! my(@columns) = split(' ', $global_prefs{'columns'} || ''); ! @columns = @allcolumns unless @columns; print $q->scrolling_list(-name=>'columns', ! -values=>\@allcolumns, -defaults=>\@columns, -multiple=>1, -size=>5), *************** sub advanced_query_page *** 1962,1980 **** { if (fieldinfo ($_, 'fieldtype') eq 'date') { ! my $headerstr = $_." after"; ! my $param_name = $headerstr; ! $param_name =~ s/ /_/; ! $param_name = field2param ($param_name); ! print "\n$headerstr:\n", ! $q->textfield(-name=>$param_name, -size=>$width), "\n\n"; ! $headerstr = $_." before"; ! $param_name = $headerstr; ! $param_name =~ s/ /_/; ! $param_name = field2param ($param_name); ! print "\n$headerstr:\n", ! $q->textfield(-name=>$param_name, -size=>$width), "\n\n"; } } --- 1942,1952 ---- { if (fieldinfo ($_, 'fieldtype') eq 'date') { ! print "\n$_ after:\n", ! $q->textfield(-name=>$_."_after", -size=>$width), "\n\n"; ! print "\n$_ before:\n", ! $q->textfield(-name=>$_."_before", -size=>$width), "\n\n"; } } *************** sub advanced_query_page *** 1995,2002 **** "\n"; foreach (@fieldnames) { - my $lc_fieldname = field2param($_); - print "\n"; # 1st column is field name --- 1967,1972 ---- *************** sub advanced_query_page *** 2004,2010 **** # 2nd column is regexp search field print "", ! $q->textfield(-name=>$lc_fieldname, -size=>$width); print "\n"; # XXX ??? !!! FIXME --- 1974,1980 ---- # 2nd column is regexp search field print "", ! $q->textfield(-name=>$_, -size=>$width); print "\n"; # XXX ??? !!! FIXME *************** sub advanced_query_page *** 2026,2032 **** my $ary_ref = fieldinfo($_, 'values'); my $size = scalar(@$ary_ref); $size = 4 if $size > 4; ! print $q->scrolling_list(-name=>$lc_fieldname, -values=>$ary_ref, -multiple=>1, -size=>$size); --- 1996,2002 ---- my $ary_ref = fieldinfo($_, 'values'); my $size = scalar(@$ary_ref); $size = 4 if $size > 4; ! print $q->scrolling_list(-name=>$_, -values=>$ary_ref, -multiple=>1, -size=>$size); *************** sub advanced_query_page *** 2044,2084 **** "Display\n", "\nDisplay these columns:\n"; ! # We operate internally with parameter names, not real-world ! # fieldnames (see dtb's comment in field2param()). This is for ! # backward compatibility and should be dealt with properly at some ! # point by making Gnatsweb use the fieldnames set in dbconfig ! # exclusively (XXX ??? !!! FIXME). We want to use real fieldnames ! # in the query page, so we construct a hash of (param , fieldname) ! # pairs to use in the scrolling_list. We also construct an array of ! # param names (@lcfields) which is fed to the scrolling_list in ! # order to keep the "natural" order of the fields. Merely using ! # keys() would cause fields to be listed in arbitrary order. ! my @lcfields; ! my %labels; ! foreach (@fieldnames) ! { ! if (fieldinfo($_, 'fieldtype') ne 'multitext') ! { ! my $param = field2param($_); ! $labels{$param} = $_; ! push (@lcfields, field2param($_)); } } ! ! my(@columns) = split(' ', $global_prefs{'columns'} || ''); ! @columns = keys(%labels) unless @columns; ! ! # The 'number' field is always first in the @lcfields array. If # users were allowed to select it in this list, the PR number would # appear twice in the Query Results table. We prevent this by # shifting 'number' out of the array. ! my(@sh_lcfields) = @lcfields; ! shift(@sh_lcfields); print $q->scrolling_list(-name=>'columns', ! -values=>\@sh_lcfields, ! -labels=>\%labels, -defaults=>\@columns, -multiple=>1, -size=>5), --- 2014,2036 ---- "Display\n", "\nDisplay these columns:\n"; ! my @allcolumns; ! foreach (@fieldnames) { ! if (fieldinfo($_, 'fieldtype') ne 'multitext') { ! push (@allcolumns, $_); } } ! # The 'number' field is always first in the @allcolumns array. If # users were allowed to select it in this list, the PR number would # appear twice in the Query Results table. We prevent this by # shifting 'number' out of the array. ! shift(@allcolumns); ! ! my(@columns) = split(' ', $global_prefs{'columns'} || ''); ! @columns = @allcolumns unless @columns; print $q->scrolling_list(-name=>'columns', ! -values=>\@allcolumns, -defaults=>\@columns, -multiple=>1, -size=>5), *************** sub submitquery *** 2235,2242 **** page_heading($page, $heading); my $debug = 0; - my @fielddisplaylist = $q->param('columns'); - my $originatedbyme = $q->param('originatedbyme'); my $ignoreclosed = $q->param('ignoreclosed'); --- 2187,2192 ---- *************** sub submitquery *** 2263,2270 **** # Bleah. XXX ??? !!! if ($stringval ne '') { ! my $ucfield = param2field ($field); ! if (isvalidfield ($ucfield)) { my $subexp = ""; my $sval; --- 2213,2219 ---- # Bleah. XXX ??? !!! if ($stringval ne '') { ! if (isvalidfield ($field)) { my $subexp = ""; my $sval; *************** sub submitquery *** 2276,2288 **** { # Most (?) people expect queries on enums to be of the # exact, not the substring type. if (fieldinfo($field, 'fieldtype') =~ "enum|multienum") { ! $subexp = appendexpr ($subexp, '|', "$ucfield==\"$sval\""); } else { ! $subexp = appendexpr ($subexp, '|', "$ucfield~\"$sval\""); } } } --- 2225,2241 ---- { # Most (?) people expect queries on enums to be of the # exact, not the substring type. + # Hence, provide explicit anchoring for enums. This + # still leaves the user the possibility of inserting + # ".*" before and/or after regular expression searches + # on the advanced query page. if (fieldinfo($field, 'fieldtype') =~ "enum|multienum") { ! $subexp = appendexpr ($subexp, '|', "$field~\"^$sval\$\""); } else { ! $subexp = appendexpr ($subexp, '|', "$field~\"$sval\""); } } } *************** sub submitquery *** 2306,2325 **** } # Whack off the trailing _after or _before. $field =~ s/_[^_]*$//; - $field = param2field ($field); $expr = appendexpr ($expr, '&', $field.$op.'"'.$stringval.'"'); } } } my $format="\"%s"; - my @ucfields = map { param2field ($_) } @fielddisplaylist; # We are using ASCII octal 037 (unit separator) to separate the # fields in the query output. Note that the format strings are # interpolated (quoted with ""'s), so make sure to escape any $ or @ # signs. ! foreach (@ucfields) { if (fieldinfo ($_, 'fieldtype') eq 'date') { $format .= "\037%{%Y-%m-%d %H:%M:%S %Z}D"; } elsif (fieldinfo ($_, 'fieldtype') eq 'enum') { --- 2259,2277 ---- } # Whack off the trailing _after or _before. $field =~ s/_[^_]*$//; $expr = appendexpr ($expr, '&', $field.$op.'"'.$stringval.'"'); } } } my $format="\"%s"; + my @columns = $q->param('columns'); # We are using ASCII octal 037 (unit separator) to separate the # fields in the query output. Note that the format strings are # interpolated (quoted with ""'s), so make sure to escape any $ or @ # signs. ! foreach (@columns) { if (fieldinfo ($_, 'fieldtype') eq 'date') { $format .= "\037%{%Y-%m-%d %H:%M:%S %Z}D"; } elsif (fieldinfo ($_, 'fieldtype') eq 'enum') { *************** sub submitquery *** 2329,2335 **** } } ! $format .= "\" ".${NUMBER_FIELD}." ".join (" ", @ucfields); client_cmd("expr $expr") if $expr; client_cmd("qfmt $format"); --- 2281,2287 ---- } } ! $format .= "\" ".${NUMBER_FIELD}." ".join (" ", @columns); client_cmd("expr $expr") if $expr; client_cmd("qfmt $format"); *************** sub nonempty *** 2353,2423 **** } - # dtb - are field2param & param2field really only here for backwards - # compatibility? if so, maybe we should get rid of them. - # unfortunately, all the saved and bookmarked queries, and people's - # column prefs (in their cookies) out there in the world would - # break. sigh, stuck with bad backwards compatibility... - # field2param - - # Convert gnats field name into parameter name, e.g. - # "Submitter-Id" => "submitter_id". It's done this crazy way for - # compatibility with queries stored by gnatsweb 2.1. - # - # used in sendpr(), edit(), query_page(), advanced_query_page() - sub field2param - { - my $name = shift; - $name =~ s/-/_/g; - $name = lc($name); - return $name; - } - - # param2field - - # Find gnats field name corresponding to parameter name, e.g. - # "submitter_id" => "Submitter-Id". - # If not gnats field corresponds, reverse the action of - # field2param(). Note that - # param2field(field2param($val)) != $val - # if $val =~ /_/ or $val =~ /[A-Z]{2,}/ - # - sub param2field - { - my $munged_field; - my $name = shift; - $name =~ s/_/-/g; - foreach my $field (@fieldnames) { - if ($name eq 'PR') { - return 'Number'; - } - else { - ($munged_field = $field) =~ s/_/-/g; - if (lc($name) eq lc($munged_field)) { - return $field; - } - } - } - - # if we get here, $name is not a gnats field, so just - # programmatically un-munge it - my @words = split(/_/, $name); - map { $_ = ucfirst($_); } @words; - $name = join('-', @words); - return $name; - } - - # display_query_results - # Display the query results, and the "store query" form. # The results only have the set of fields that we requested, although # the first field is always the PR number. sub display_query_results { - my ($nooffields); my(@query_results) = @_; - my(@fields) = $q->param('columns'); my $displaydate = $q->param('displaydate'); my $reversesort = $q->param('reversesort'); - my($field, %fields); my $num_matches = scalar(@query_results); my $heading = sprintf("%s %s found", --- 2305,2319 ---- *************** sub display_query_results *** 2433,2477 **** $q->hidden(name=>'cmd', -value=>'view', -override=>1), "\n"; ! # Note that $sortby is the normal uppercased name of the field, and not ! # a "parameterized" version. ! my($sortby) = $q->param('sortby') || 'PR'; my $whichfield = 0; my ($sortbyfieldnum) = 0; # Print table header which allows sorting by columns. # While printing the headers, temporarily override the 'sortby' param # so that self_url() works right. ! ! my @ufields; ! ! for $field ('PR', @fields) { ! my $ufield = param2field ($field); ! if ($field ne 'PR') ! { ! push (@ufields, $ufield); } ! $q->param(-name=>'sortby', -value=>$ufield); # strip empty params out of self_url(). in a gnats db with many # fields, the url query-string will become very long. this is a # problem, since IE5 truncates query-strings at ~2048 characters. my ($query_string) = $q->self_url() =~ m/^[^?]*\?(.*)$/; ! $query_string =~ s/\w+=;//g; ! my $href = $script_name . '?' . $query_string; ! $fields{$field}++; ! if ($ufield eq $sortby) ! { ! $sortbyfieldnum = $whichfield; ! } ! $whichfield++; ! if ($ufield eq 'PR') { ! $ufield='Number'; ! } ! print "\n\n"; ! $nooffields = @ufields; } # finished the header row print "\n"; --- 2329,2360 ---- $q->hidden(name=>'cmd', -value=>'view', -override=>1), "
$ufield
\n"; ! # By default sort by PR number. ! my($sortby) = $q->param('sortby') || $fieldnames[0]; my $whichfield = 0; my ($sortbyfieldnum) = 0; + my @columns = $q->param('columns'); + my $noofcolumns = @columns; # Print table header which allows sorting by columns. # While printing the headers, temporarily override the 'sortby' param # so that self_url() works right. ! for ($fieldnames[0], @columns) { ! $q->param(-name=>'sortby', -value=>$_); ! if ($_ eq $sortby) { ! $sortbyfieldnum = $whichfield; } ! $whichfield++; # strip empty params out of self_url(). in a gnats db with many # fields, the url query-string will become very long. this is a # problem, since IE5 truncates query-strings at ~2048 characters. my ($query_string) = $q->self_url() =~ m/^[^?]*\?(.*)$/; ! $query_string =~ s/(\w|-)+=;//g; ! my $href = $script_name . '?' . $query_string; ! print "\n\n"; } # finished the header row print "\n"; *************** sub display_query_results *** 2485,2492 **** my(@presplit_prs) = map { [ (split /\037/) ] } @query_results; my(@sorted_prs); my $sortby_fieldtype = fieldinfo ($sortby, 'fieldtype') || ''; ! if ($sortby_fieldtype eq 'enum' || $sortby_fieldtype eq 'integer' ! || $sortby eq 'PR') { # sort numerically @sorted_prs = sort({$a->[$sortbyfieldnum] <=> $b->[$sortbyfieldnum]} @presplit_prs); --- 2368,2374 ---- my(@presplit_prs) = map { [ (split /\037/) ] } @query_results; my(@sorted_prs); my $sortby_fieldtype = fieldinfo ($sortby, 'fieldtype') || ''; ! if ($sortby_fieldtype eq 'enum' || $sortby_fieldtype eq 'integer') { # sort numerically @sorted_prs = sort({$a->[$sortbyfieldnum] <=> $b->[$sortbyfieldnum]} @presplit_prs); *************** sub display_query_results *** 2499,2505 **** @sorted_prs = reverse @sorted_prs if $reversesort; # Print the PR's. ! my @fieldtypes = map { fieldinfo ($_, 'fieldtype') } @ufields; foreach (@sorted_prs) { print "\n"; --- 2381,2387 ---- @sorted_prs = reverse @sorted_prs if $reversesort; # Print the PR's. ! my @fieldtypes = map { fieldinfo ($_, 'fieldtype') } @columns; foreach (@sorted_prs) { print "\n"; *************** sub display_query_results *** 2520,2532 **** # map them back into strings. if ($fieldtypes[$whichfield] eq 'enum') { ! my $enumvals = fieldinfo($ufields[$whichfield], 'values'); $fieldcontents = $$enumvals[$fieldcontents - 1] || 'invalid'; } $fieldcontents = $q->escapeHTML($fieldcontents); $fieldcontents = nonempty($fieldcontents); ! if ($ufields[$whichfield] =~ /responsible/i) { $fieldcontents = make_mailto($fieldcontents); } else { # make urls and email addresses into live hrefs --- 2402,2414 ---- # map them back into strings. if ($fieldtypes[$whichfield] eq 'enum') { ! my $enumvals = fieldinfo($columns[$whichfield], 'values'); $fieldcontents = $$enumvals[$fieldcontents - 1] || 'invalid'; } $fieldcontents = $q->escapeHTML($fieldcontents); $fieldcontents = nonempty($fieldcontents); ! if ($columns[$whichfield] =~ /responsible/i) { $fieldcontents = make_mailto($fieldcontents); } else { # make urls and email addresses into live hrefs *************** sub display_query_results *** 2538,2544 **** } # Pad the remaining, empty columns with  's my $n = @{$_}; ! while ($nooffields - $n > 0) { print ""; $n++; --- 2420,2426 ---- } # Pad the remaining, empty columns with  's my $n = @{$_}; ! while ($noofcolumns - $n > 0) { print ""; $n++; *************** sub display_query_results *** 2553,2559 **** # strip empty params out of $url. in a gnats db with many # fields, the url query-string will become very long. this is a # problem, since IE5 truncates query-strings at ~2048 characters. ! $url =~ s/\w+=;//g; print $q->p(qq{View for bookmarking\n}); # Allow the user to store this query. Need to repeat params as hidden --- 2435,2441 ---- # strip empty params out of $url. in a gnats db with many # fields, the url query-string will become very long. this is a # problem, since IE5 truncates query-strings at ~2048 characters. ! $url =~ s/(\w|-)+=;//g; print $q->p(qq{View for bookmarking\n}); # Allow the user to store this query. Need to repeat params as hidden --AqsLC8rIMeq19msA-- _______________________________________________ Help-gnats mailing list Help-gnats@gnu.org http://mail.gnu.org/mailman/listinfo/help-gnats
$_