]> git.donarmstrong.com Git - debbugs.git/commitdiff
Merge branch 'master' into don/libravatar
authorDon Armstrong <don@donarmstrong.com>
Tue, 1 Oct 2013 19:40:37 +0000 (12:40 -0700)
committerDon Armstrong <don@donarmstrong.com>
Tue, 1 Oct 2013 19:40:37 +0000 (12:40 -0700)
Conflicts:
Debbugs/CGI/Bugreport.pm
debian/control

20 files changed:
Debbugs/CGI/Bugreport.pm
Debbugs/Control.pm
Debbugs/Estraier.pm
Debbugs/MIME.pm
Debbugs/Recipients.pm
Debbugs/SOAP.pm
Debbugs/Status.pm
Debbugs/UTF8.pm
Makefile
bin/debbugs-rebuild-index.db [new file with mode: 0755]
debian/changelog
debian/control
debian/rules
debian/source/format [new file with mode: 0644]
examples/debian/postpa/21bugclosers
html/bugs.css
t/01_pod.t
t/15_rebuild_indexdb.t [new file with mode: 0644]
t/lib/DebbugsTest.pm
templates/en_US/cgi/bugreport.tmpl

index 8d3452db06985287f465c8fa63580bd821e6b640..2e53892ca5ced8e019b24b5bf291640a45556432 100644 (file)
@@ -148,10 +148,10 @@ sub display_entity {
                    if ($_ eq 'From' and $param{avatars}) {
                        my $libravatar_url = __libravatar_url(decode_rfc1522($head_field));
                        if (defined $libravatar_url and length $libravatar_url) {
-                           push @headers,q(<img src="http://).$libravatar_url.qq(">\n);
+                           push @headers,q(<img src="http://).$libravatar_url.qq(" alt="">\n);
                        }
                    }
-                  push @headers, qq(<p><span class="header">$_:</span> ) . html_escape(decode_rfc1522($head_field))."</p>\n";
+                  push @headers, qq(<div class="header"><span class="headerfield">$_:</span> ) . html_escape(decode_rfc1522($head_field))."</div>\n";
              }
              print {$output} join(qq(), @headers);
         } else {
@@ -172,7 +172,6 @@ sub display_entity {
            my $body = $entity->stringify_body;
            # this attachment has its own content type, so we must not
            # try to convert it to UTF-8 or do anything funky.
-           my @layers = PerlIO::get_layers($output);
            binmode($output,':raw');
            print {$output} "Content-Type: $type";
            my ($charset) = $head->get('Content-Type:') =~ m/charset\s*=\s*\"?([\w-]+)\"?/i;
@@ -187,10 +186,10 @@ sub display_entity {
            print {$output} "\n";
            my $decoder = MIME::Decoder->new($head->mime_encoding);
            $decoder->decode(IO::Scalar->new(\$body), $output);
-           if (grep {/utf8/} @layers) {
-               binmode($output,':utf8');
-           }
-           return;
+            # we don't reset the layers here, because it makes no
+            # sense to add anything to the output handle after this
+            # point.
+           return(1);
        }
        elsif (not exists $param{att}) {
             my @dlargs = (msg=>$xmessage, att=>$#$attachments);
@@ -206,26 +205,30 @@ sub display_entity {
        }
     }
 
-    return if not $param{outer} and $disposition eq 'attachment' and not exists $param{att};
-    return unless ($type =~ m[^text/?] and
-                  $type !~ m[^text/(?:html|enriched)(?:;|$)]) or
-                 $type =~ m[^application/pgp(?:;|$)] or
-                 $entity->parts;
+    return if not $param{outer} and $disposition eq 'attachment' and not exists $param{att};
+    return 0 unless (($type =~ m[^text/?] and
+                      $type !~ m[^text/(?:html|enriched)(?:;|$)]) or
+                     $type =~ m[^application/pgp(?:;|$)] or
+                     $entity->parts);
 
     if ($entity->is_multipart) {
        my @parts = $entity->parts;
        foreach my $part (@parts) {
-           display_entity(entity => $part,
-                          bug_num => $ref,
-                          outer => 0,
-                          msg_num => $xmessage,
-                          output => $output,
-                          attachments => $attachments,
-                          terse => $param{terse},
-                          exists $param{msg}?(msg=>$param{msg}):(),
-                          exists $param{att}?(att=>$param{att}):(),
-                           exists $param{avatars}?(avatars=>$param{avatars}):(),
-                         );
+           my $raw_output =
+                display_entity(entity => $part,
+                               bug_num => $ref,
+                               outer => 0,
+                               msg_num => $xmessage,
+                               output => $output,
+                               attachments => $attachments,
+                               terse => $param{terse},
+                               exists $param{msg}?(msg=>$param{msg}):(),
+                               exists $param{att}?(att=>$param{att}):(),
+                               exists $param{avatars}?(avatars=>$param{avatars}):(),
+                              );
+            if ($raw_output) {
+                return $raw_output;
+            }
            # print {$output} "\n";
        }
     } elsif ($entity->parts) {
@@ -286,6 +289,7 @@ sub display_entity {
              print {$output} qq(<pre class="message">$body</pre>\n);
         }
     }
+    return 0;
 }
 
 
@@ -314,19 +318,20 @@ sub handle_email_message{
      $parser->output_to_core(1);
      my $entity = $parser->parse_data( $email);
      my @attachments = ();
-     display_entity(entity  => $entity,
-                   bug_num => $param{ref},
-                   outer   => 1,
-                   msg_num => $param{msg_num},
-                   output => $output_fh,
-                   attachments => \@attachments,
-                   terse       => $param{terse},
-                   exists $param{msg}?(msg=>$param{msg}):(),
-                   exists $param{att}?(att=>$param{att}):(),
-                   exists $param{trim_headers}?(trim_headers=>$param{trim_headers}):(),
-                   exists $param{avatars}?(avatars=>$param{avatars}):(),
-                  );
-     return decode_utf8($output);
+     my $raw_output =
+         display_entity(entity  => $entity,
+                        bug_num => $param{ref},
+                        outer   => 1,
+                        msg_num => $param{msg_num},
+                        output => $output_fh,
+                        attachments => \@attachments,
+                        terse       => $param{terse},
+                        exists $param{msg}?(msg=>$param{msg}):(),
+                        exists $param{att}?(att=>$param{att}):(),
+                        exists $param{trim_headers}?(trim_headers=>$param{trim_headers}):(),
+                        exists $param{avatars}?(avatars=>$param{avatars}):(),
+                       );
+     return $raw_output?$output:decode_utf8($output);
 }
 
 =head2 handle_record
index 0390ba72cc6290a7da86ad382c05819bf215311c..44d0062e9a9bc4ae1ccc21cb2d46d97451f4211b 100644 (file)
@@ -2663,7 +2663,7 @@ Handles all setting of summary fields
 
 If summary is undef, unsets the summary
 
-If summary is 0, sets the summary to the first paragraph contained in
+If summary is 0 or -1, sets the summary to the first paragraph contained in
 the message passed.
 
 If summary is a positive integer, sets the summary to the message specified.
@@ -2751,7 +2751,7 @@ sub _summary {
     elsif ($param{$cmd} =~ /^\d+$/) {
         my $log = [];
         my @records = Debbugs::Log::read_log_records(bug_num => $param{bug});
-        if ($param{$cmd} == 0) {
+        if ($param{$cmd} == 0 or $param{$cmd} == -1) {
              $log = $param{message};
              $summary_msg = @records + 1;
         }
@@ -2785,7 +2785,7 @@ sub _summary {
              }
              # skip a paragraph if it looks like it's control or
              # pseudo-headers
-             if ($line =~ m{^\s*(?:Package|Source|Version|User|Tag|Severity)\:\s+\S}xi or #pseudo headers
+             if ($line =~ m{^\s*(?:Package|Source|Version|User|Tag|Severity|Control)\:\s+\S}xi or #pseudo headers
                  $line =~ m{^(?:package:?|(?:no|)owner|severity|tags?|summary| #control
                                 \#|reopen|close|(?:not|)(?:fixed|found)|clone|
                                 debug|(?:not|)forwarded|priority|
index e3c89a1d6ce074c92c6d6b67c69609b4b50a6f23..5987fe9ec5ddf1f5485157fa407b5444573fb0c1 100644 (file)
@@ -30,12 +30,11 @@ use strict;
 use vars qw($VERSION $DEBUG %EXPORT_TAGS @EXPORT_OK @EXPORT);
 use base qw(Exporter);
 use Debbugs::Log;
-#use Params::Validate;
 use Search::Estraier;
-use Date::Manip;
 use Debbugs::Common qw(getbuglocation getbugcomponent make_list);
 use Debbugs::Status qw(readbug);
 use Debbugs::MIME qw(parse);
+use Encode qw(encode_utf8);
 
 BEGIN{
      ($VERSION) = q$Revision: 1.3 $ =~ /^Revision:\s+([^\s+])/;
@@ -121,7 +120,7 @@ sub add_bug_message{
      $doc = new Search::Estraier::Document if not defined $doc;
 
      my $message = parse($bug_message);
-     $doc->add_text(join("\n",make_list(values %{$message})));
+     $doc->add_text(encode_utf8(join("\n",make_list(values %{$message}))));
 
      # * @id : the ID number determined automatically when the document is registered.
      # * @uri : the location of a document which any document should have.
@@ -140,17 +139,17 @@ sub add_bug_message{
      my @attr = qw(status subject date submitter package tags severity);
      # parse the date
      my ($date) = $bug_message =~ /^Date:\s+(.+?)\s*$/mi;
-     $doc->add_attr('@cdate' => $date) if defined $date;
+     $doc->add_attr('@cdate' => encode_utf8($date)) if defined $date;
      # parse the title
      my ($subject) = $bug_message =~ /^Subject:\s+(.+?)\s*$/mi;
-     $doc->add_attr('@title' => $subject) if defined $subject;
+     $doc->add_attr('@title' => encode_utf8($subject)) if defined $subject;
      # parse the author
      my ($author) = $bug_message =~ /^From:\s+(.+?)\s*$/mi;
-     $doc->add_attr('@author' => $author) if defined $author;
+     $doc->add_attr('@author' => encode_utf8($author)) if defined $author;
      # create the uri
-     $doc->add_attr('@uri' => $uri);
+     $doc->add_attr('@uri' => encode_utf8($uri));
      foreach my $attr (@attr) {
-         $doc->add_attr($attr => $status->{$attr}) if defined $status->{$attr};
+         $doc->add_attr($attr => encode_utf8($status->{$attr})) if defined $status->{$attr};
      }
      print STDERR "adding $uri\n" if $DEBUG;
      # Try a bit harder if estraier is returning timeouts
index afc077649939784e4cedf95a81d7b75efb04ded8..15078f2c18929f535e8ff83da7958c053f7e522a 100644 (file)
@@ -10,6 +10,8 @@
 
 package Debbugs::MIME;
 
+=encoding utf8
+
 =head1 NAME
 
 Debbugs::MIME -- Mime handling routines for debbugs
index 47c648541044c8cf3f3a4ee2b7923ba2f37225ac..ae739e973647ef74d2641dfe60b61dacf666093d 100644 (file)
@@ -245,7 +245,7 @@ Using the recipient hashref, determines the set of recipients.
 If you specify one of C<bcc>, C<cc>, or C<to>, you will receive only a
 LIST of recipients which the main should be Bcc'ed, Cc'ed, or To'ed
 respectively. By default, a LIST with keys bcc, cc, and to is returned
-with ARRAYREF values correponding to the users to whom a message
+with ARRAYREF values corresponding to the users to whom a message
 should be sent.
 
 =over
index c1fc85f9b84fb5465bbab56ab916b4b445f1073b..f87581e60c07af74150cacce8a633be362afb79d 100644 (file)
@@ -343,7 +343,7 @@ architectures are at which versions.
 
 =back
 
-This function correponds to L<Debbugs::Packages::get_versions>
+This function corresponds to L<Debbugs::Packages::get_versions>
 
 =cut
 
index 9c9551b3ca262b419743021f58291ad49d408707..b28ff5355658e4a24dc17bc29bc06da172334e39 100644 (file)
@@ -70,6 +70,7 @@ BEGIN{
                                  qw(removefoundversions removefixedversions)
                                 ],
                     hook     => [qw(bughook bughook_archive)],
+                     indexdb  => [qw(generate_index_db_line)],
                     fields   => [qw(%fields)],
                    );
      @EXPORT_OK = ();
@@ -207,6 +208,7 @@ sub read_bug{
         $log = $status;
         $log =~ s/\.summary$/.log/;
         ($location) = $status =~ m/(db-h|db|archive)/;
+         ($param{bug}) = $status =~ m/(\d+)\.summary$/;
     }
     if ($param{lock}) {
        filelock("$config{spool_dir}/lock/$param{bug}",exists $param{locks}?$param{locks}:());
@@ -274,7 +276,7 @@ sub read_bug{
 
     my $status_modified = (stat($status))[9];
     # Add log last modified time
-    $data{log_modified} = (stat($log))[9];
+    $data{log_modified} = (stat($log))[9] // (stat("${log}.gz"))[9];
     $data{last_modified} = max($status_modified,$data{log_modified});
     $data{location} = $location;
     $data{archived} = (defined($location) and ($location eq 'archive'))?1:0;
@@ -510,12 +512,14 @@ sub lock_read_all_merged_bugs {
            push @data,$newdata;
            # perform a sanity check to make sure that the merged bugs
            # are all merged with eachother
-           my $expectmerge= join(' ',grep {$_ != $bug } sort { $a <=> $b } @bugs);
+        # We do a cmp sort instead of an <=> sort here, because that's
+        # what merge does
+           my $expectmerge= join(' ',grep {$_ != $bug } sort @bugs);
            if ($newdata->{mergedwith} ne $expectmerge) {
                for (1..$locks) {
                    unfilelock(exists $param{locks}?$param{locks}:());
                }
-               die "Bug $param{bug} differs from bug $bug: ($newdata->{bug_num}: '$newdata->{mergedwith}') vs. ('$expectmerge') (".join(' ',@bugs).")";
+               die "Bug $param{bug} mergedwith differs from bug $bug: ($newdata->{bug_num}: '$newdata->{mergedwith}') vs. ('$expectmerge') (".join(' ',@bugs).")";
            }
        }
     }
@@ -655,7 +659,7 @@ sub makestatus {
 
 Writes the bug status and summary files out.
 
-Skips writting out a status file if minversion is 2
+Skips writing out a status file if minversion is 2
 
 Does not call bughook if disablebughook is true.
 
@@ -773,7 +777,7 @@ exactly are removed. Otherwise, all versions matching the version
 number are removed.
 
 Currently $package and $isbinary are entirely ignored, but accepted
-for backwards compatibilty.
+for backwards compatibility.
 
 =cut
 
@@ -1599,6 +1603,39 @@ sub isstrongseverity {
     return grep { $_ eq $severity } @{$config{strong_severities}};
 }
 
+=head1 indexdb
+
+=head2 generate_index_db_line
+
+       my $data = read_bug(bug => $bug,
+                           location => $initialdir);
+        # generate_index_db_line hasn't been written yet at all.
+        my $line = generate_index_db_line($data);
+
+Returns a line for a bug suitable to be written out to index.db.
+
+=cut
+
+sub generate_index_db_line {
+    my ($data,$bug) = @_;
+
+    # just in case someone has given us a split out data
+    $data = join_status_fields($data);
+
+    my $whendone = "open";
+    my $severity = $config{default_severity};
+    (my $pkglist = $data->{package}) =~ s/[,\s]+/,/g;
+    $pkglist =~ s/^,+//;
+    $pkglist =~ s/,+$//;
+    $whendone = "forwarded" if defined $data->{forwarded} and length $data->{forwarded};
+    $whendone = "done" if defined $data->{done} and length $data->{done};
+    $severity = $data->{severity} if length $data->{severity};
+    return sprintf "%s %d %d %s [%s] %s %s\n",
+        $pkglist, $data->{bug_num}//$bug, $data->{date}, $whendone,
+            $data->{originator}, $severity, $data->{keywords};
+}
+
+
 
 =head1 PRIVATE FUNCTIONS
 
@@ -1681,19 +1718,7 @@ sub bughook {
             my $data = $bugs_temp{$bug};
             appendfile("$config{spool_dir}/debbugs.trace","$type $bug\n",makestatus($data, 1));
 
-            my $whendone = "open";
-            my $severity = $config{default_severity};
-            (my $pkglist = $data->{package}) =~ s/[,\s]+/,/g;
-            $pkglist =~ s/^,+//;
-            $pkglist =~ s/,+$//;
-            $whendone = "forwarded" if defined $data->{forwarded} and length $data->{forwarded};
-            $whendone = "done" if defined $data->{done} and length $data->{done};
-            $severity = $data->{severity} if length $data->{severity};
-
-            my $k = sprintf "%s %d %d %s [%s] %s %s\n",
-                 $pkglist, $bug, $data->{date}, $whendone,
-                      $data->{originator}, $severity, $data->{keywords};
-            $bugs{$bug} = $k;
+            $bugs{$bug} = generate_index_db_line($data,$bug);
        }
        update_realtime("$config{spool_dir}/index.db.realtime", %bugs);
 
index 45da58fa7acdb4956e0aa27cff2313a609027836..0ad284df16a6d37794098c5c67de37b70613b835 100644 (file)
@@ -68,7 +68,7 @@ our $depth = 0;
 sub encode_utf8_structure {
     ++$depth;
     my @ret;
-    for my $_ (@_) {
+    for $_ (@_) {
        if (ref($_) eq 'HASH') {
            push @ret, {encode_utf8_structure(%{$depth == 1 ? dclone($_):$_})};
        }
@@ -143,10 +143,9 @@ sub decode_utf8_safely{
 
 =cut
 
-our %iconv_converters;
-
 sub convert_to_utf8 {
-    my ($data,$charset) = @_;
+    my ($data,$charset,$internal_call) = @_;
+    $internal_call //= 0;
     if (is_utf8($data)) {
         cluck("utf8 flag is set when calling convert_to_utf8");
         return $data;
@@ -155,30 +154,36 @@ sub convert_to_utf8 {
     if ($charset eq 'RAW') {
         croak("Charset must not be raw when calling convert_to_utf8");
     }
-    if (not defined $iconv_converters{$charset}) {
-        eval {
-            $iconv_converters{$charset} = Text::Iconv->new($charset,"UTF-8") or
-                die "Unable to create converter for '$charset'";
-        };
-        if ($@) {
-            warn $@;
-            # We weren't able to create the converter, so use Encode
-            # instead
-            return __fallback_convert_to_utf8($data,$charset);
-        }
-    }
-    if (not defined $iconv_converters{$charset}) {
-        warn "The converter for $charset wasn't created properly somehow!";
+    my $iconv_converter;
+    eval {
+        $iconv_converter = Text::Iconv->new($charset,"UTF-8") or
+            die "Unable to create converter for '$charset'";
+    };
+    if ($@) {
+        return undef if $internal_call;
+        warn $@;
+        # We weren't able to create the converter, so use Encode
+        # instead
         return __fallback_convert_to_utf8($data,$charset);
     }
-    my $converted_data = $iconv_converters{$charset}->convert($data);
+    my $converted_data = $iconv_converter->convert($data);
     # if the conversion failed, retval will be undefined or perhaps
     # -1.
-    my $retval = $iconv_converters{$charset}->retval();
+    my $retval = $iconv_converter->retval();
     if (not defined $retval or
         $retval < 0
        ) {
-        warn "failed to convert to utf8";
+        # try iso8559-1 first
+        if (not $internal_call) {
+            my $call_back_data = convert_to_utf8($data,'ISO8859-1',1);
+            # if there's an Ã (0xC3), it's probably something
+            # horrible, and we shouldn't try to convert it.
+            if (defined $call_back_data and $call_back_data !~ /\x{C3}/) {
+                warn "failed to convert to utf8 (charset: $charset, data: $data), but succeeded with ISO8859-1: ".encode_utf8($call_back_data);
+                return $call_back_data;
+            }
+        }
+        warn "failed to convert to utf8 (charset: $charset, data: $data)";
         # Fallback to encode, which will probably also fail.
         return __fallback_convert_to_utf8($data,$charset);
     }
@@ -199,7 +204,7 @@ sub __fallback_convert_to_utf8 {
      $charset //= 'utf8';
      my $result;
      eval {
-        $result = decode($charset,$data);
+        $result = decode($charset,$data,0);
      };
      if ($@) {
          warn "Unable to decode charset; '$charset' and '$data': $@";
index 587670406b9eb7578055036259ac1741152e58e5..19a074bb0abba18683d8e3c56cc5b2028c94b58f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -56,6 +56,7 @@ install_mostfiles:
        # create the directories if they aren't there
        for dir in $(sbin_dir) $(etc_dir)/html $(etc_dir)/indices \
 $(var_dir)/indices $(var_dir)/www/cgi $(var_dir)/www/db $(var_dir)/www/txt \
+$(var_dir)/www/css \
 $(var_dir)/spool/lock $(var_dir)/spool/archive $(var_dir)/spool/incoming \
 $(var_dir)/spool/db-h $(scripts_dir) $(examples_dir) $(man8_dir); \
           do test -d $$dir || $(install_exec) -d $$dir; done
@@ -82,7 +83,7 @@ $(var_dir)/spool/db-h $(scripts_dir) $(examples_dir) $(man8_dir); \
        # install the HTML pages etc
        $(foreach html, $(htmls_in), $(install_data) $(html) $(etc_dir)/html;)
        $(install_data) html/htaccess $(var_dir)/www/db/.htaccess
-       $(install_data) html/bugs.css $(var_dir)/www/bugs.css
+       $(install_data) html/bugs.css $(var_dir)/www/css/bugs.css
 
        # install the CGIs
        for cgi in $(cgis); do $(install_exec) $$cgi $(var_dir)/www/cgi; done
diff --git a/bin/debbugs-rebuild-index.db b/bin/debbugs-rebuild-index.db
new file mode 100755 (executable)
index 0000000..c44bc32
--- /dev/null
@@ -0,0 +1,157 @@
+#! /usr/bin/perl
+# debbugs-rebuild-index.db is part of debbugs, and is released
+# under the terms of the GPL version 2, or any later version, at your
+# option. See the file README and COPYING for more information.
+# Copyright 2012 by Don Armstrong <don@donarmstrong.com>.
+
+
+use warnings;
+use strict;
+
+use Getopt::Long qw(:config no_ignore_case);
+use Pod::Usage;
+
+=head1 NAME
+
+debbugs-rebuild-index.db -- rebuild Debbug's index.db
+
+=head1 SYNOPSIS
+
+debbugs-rebuild-index.db [options]
+
+ Options:
+  --spool-dir debbugs spool directory
+  --debug, -d debugging level (Default 0)
+  --help, -h display this help
+  --man, -m display manual
+
+=head1 OPTIONS
+
+=over
+
+=item B<--spool-dir>
+
+Debbugs spool directory; defaults to the value configured in the
+debbugs configuration file.
+
+=item B<--debug, -d>
+
+Debug verbosity.
+
+=item B<--help, -h>
+
+Display brief useage information.
+
+=item B<--man, -m>
+
+Display this manual.
+
+=back
+
+=head1 EXAMPLES
+
+Rebuild the index.db for db-h.
+
+ debbugs-rebuild-index.db;
+
+Rebuild the index.db for archive
+
+ debbugs-rebuild-index.db archive;
+
+
+=cut
+
+
+use vars qw($DEBUG);
+
+use Debbugs::Common qw(checkpid lockpid get_hashname getparsedaddrs getbugcomponent make_list);
+use Debbugs::Config qw(:config);
+use Debbugs::Status qw(read_bug split_status_fields generate_index_db_line);
+
+my %options = (debug           => 0,
+              help            => 0,
+              man             => 0,
+              verbose         => 0,
+              quiet           => 0,
+              quick           => 0,
+              service         => 'debbugs',
+             );
+
+
+GetOptions(\%options,
+          'quick|q',
+          'service|s',
+          'sysconfdir|c',
+          'spool_dir|spool-dir=s',
+          'debug|d+','help|h|?','man|m');
+
+pod2usage() if $options{help};
+pod2usage({verbose=>2}) if $options{man};
+
+$DEBUG = $options{debug};
+
+my @USAGE_ERRORS;
+$options{verbose} = $options{verbose} - $options{quiet};
+
+pod2usage(join("\n",@USAGE_ERRORS)) if @USAGE_ERRORS;
+
+if (exists $options{spool_dir} and defined $options{spool_dir}) {
+    $config{spool_dir} = $options{spool_dir};
+}
+chdir($config{spool_dir}) or die "chdir $config{spool_dir} failed: $!";
+
+my $verbose = $options{debug};
+
+my $initialdir = "db-h";
+
+if (defined $ARGV[0] and $ARGV[0] eq "archive") {
+    $initialdir = "archive";
+}
+
+if (not lockpid($config{spool_dir}.'/lock/debbugs-rebuild-index.db')) {
+     print STDERR "Another debbugs-rebuild-index.db is running; stopping\n";
+     exit 1;
+}
+
+my $fh_type = $initialdir;
+# if initaldir is db-h, the file is db.
+$fh_type = 'db' if $initialdir eq 'db-h';
+
+my $file = "index.${fh_type}.realtime";
+my $idx_rebuild = IO::File->new($file.'.rebuild','w')
+    or die "Couldn't open ${file}.rebuild: $!";
+
+
+my @dirs = ($initialdir);
+my $cnt = 0;
+my %bugs;
+while (my $dir = shift @dirs) {
+    printf "Doing dir %s ...\n", $dir if $verbose;
+
+    opendir(DIR, "$dir/.") or die "opendir $dir: $!";
+    my @subdirs = readdir(DIR);
+    closedir(DIR);
+
+    my @list = map { m/^(\d+)\.summary$/?($1):() } @subdirs;
+    push @dirs, map { m/^(\d+)$/ && -d "$dir/$1"?("$dir/$1"):() } @subdirs;
+
+    for my $bug (@list) {
+       print "Up to $cnt bugs...\n" if (++$cnt % 100 == 0 && $verbose);
+       my $stat = stat(getbugcomponent($bug,'summary',$initialdir));
+       if (not defined $stat) {
+           print STDERR "Unable to stat $bug $!\n";
+           next;
+       }
+       my $data = read_bug(bug => $bug,
+                           location => $initialdir);
+        my $line = generate_index_db_line($data);
+        $bugs{$bug} = $line;
+    }
+}
+binmode($idx_rebuild,':raw:encoding(UTF-8)');
+print {$idx_rebuild} $bugs{$_} foreach sort {$a <=> $b} keys %bugs;
+close($idx_rebuild);
+rename("$file.rebuild", $file);
+
+
+__END__
index 14a0d66a3676296aabf245a153cbe094226dceb8..e2ab47d747421578d94d64abdbfd0d9fdfaa441f 100644 (file)
@@ -17,6 +17,7 @@ debbugs (2.4.2~exp2) UNRELEASED; urgency=low
   * Fix failure to forcibly merge/merge when found/fixed is not qualified
     (closes: #670456). Thanks to Jonathan Nieder and Bernhard Schmidt.
   * Add libravatar support.
+  * Fix double encoding of attachments (closes: #703300)
 
   [Thanks to Arnout Engelen: ]
   * Add Homepage (closes: #670555).
@@ -52,9 +53,25 @@ debbugs (2.4.2~exp2) UNRELEASED; urgency=low
     a site admin aware of its existence (closes: #688345).
   * Make sure that mails to gSubscriptionDomain and gBugSubscriptionDomain
     are only sent out if the variables in config are defined and
-    have a lenght < 0 (closes: #688344).
+    have a length < 0 (closes: #688344).
   * Use locale independent date format for mail processing and service mail
     generation (closes: #688745).
+  * Fix spelling error in /debian/changelog.
+  * Fix lintian issue: description-synopsis-starts-with-article.
+  * Fix lintian issues: debian-rules-missing-recommended-target build-arch,
+    debian-rules-missing-recommended-target build-indep.
+  * Switch to debian/source/format: 3.0 (native).
+  * Fix lintian issue: debbugs source: duplicate-in-relation-field in
+    libdebbugs-perl depends: libtext-template-perl, libtext-template-perl.
+  * Fix lintian issues: debbugs source:
+    debian-rules-makemaker-prefix-is-deprecated line 44,
+    debian-rules-makemaker-prefix-is-deprecated line 56.
+  * Fix lintian issues: libdebbugs-perl: spelling-error-in-manpage for:
+    + usr/share/man/man3/Debbugs::Recipients.3pm.gz
+    + usr/share/man/man3/Debbugs::SOAP.3pm.gz
+    + usr/share/man/man3/Debbugs::Status.3pm.gz
+  * Raise Standards to 3.9.4 (after fixing several lintian issues).
+  * Pass param bug=<NNN> to bugreport.html call in bugreport.cgi.
 
  -- Don Armstrong <don@debian.org>  Wed, 25 Aug 2010 01:57:38 -0700
 
index d8499aedcb57acded7ba7f99e3a6d7b4acd28ce2..3b0a7671bf846f3ce91bda5426fa3c27dcb49fc3 100644 (file)
@@ -3,7 +3,7 @@ Section: misc
 Priority: extra
 Maintainer: Debbugs developers <debian-debbugs@lists.debian.org>
 Uploaders: Colin Watson <cjwatson@debian.org>, Don Armstrong <don@debian.org>
-Standards-Version: 3.8.2
+Standards-Version: 3.9.4
 Vcs-Browser: http://bugs.debian.org/debbugs-source/mainline
 Vcs-Git: http://bugs.debian.org/debbugs-source/debbugs.git
 Build-Depends: debhelper (>= 5)
@@ -25,7 +25,7 @@ Depends:
  libdebbugs-perl,
 Recommends: debbugs-web
 Suggests: spamassassin (>= 3.0), libcgi-alert-perl
-Description: The bug tracking system based on the active Debian BTS
+Description: bug tracking system based on the active Debian BTS
  Debian has a bug tracking system which files details of bugs reported by
  users and developers. Each bug is given a number, and is kept on file until
  it is marked as having been dealt with. The system is mainly controlled by
@@ -79,7 +79,7 @@ Depends:
  ${misc:Depends},
  libdebbugs-perl, debbugs-web, libconfig-simple-perl,
  libuser-perl, rsync, libhttp-server-simple-perl, libnet-server-perl
-Description: run and maintains a local mirror of the Debian BTS
+Description: Run and maintains a local mirror of the Debian BTS
  Debian has a bug tracking system which files details of bugs reported
  by users and developers. Each bug is given a number, and is kept on
  file until it is marked as having been dealt with. The system is
index c3483791a6757eec503f2920237f60f45e4c0eb3..7bdd341f7ab2e7ce59ca12837a2c5e56aedfa278 100755 (executable)
@@ -10,7 +10,13 @@ DEST_DIR := $(CURDIR)/debian/tmp
 PERL ?= /usr/bin/perl
 
 
-build: build-stamp
+build: build-arch build-indep
+
+build-arch:
+# nothing to do, as there aren't any architecture-dependent packages
+
+build-indep: build-stamp
+
 build-stamp:
 # Call the test suite
        $(PERL) Makefile.PL INSTALLDIRS=vendor
@@ -35,7 +41,7 @@ install-stamp: build
        dh_clean -k
        dh_installdirs
        $(MAKE) install_mostfiles DESTDIR=$(DEST_DIR)
-       $(MAKE) -f Makefile.perl install PREFIX=$(DEST_DIR)/usr
+       $(MAKE) -f Makefile.perl install DESTDIR=$(DEST_DIR)
        touch $@
 
 binary-arch:
@@ -47,7 +53,7 @@ binary-indep: build install
        dh_clean -k
        dh_installdirs
        $(MAKE) install_mostfiles DESTDIR=$(DEST_DIR)
-       $(MAKE) -f Makefile.perl install PREFIX=$(DEST_DIR)/usr
+       $(MAKE) -f Makefile.perl install DESTDIR=$(DEST_DIR)
        dh_install --sourcedir=debian/tmp --fail-missing
        dh_installdocs
        dh_installchangelogs
diff --git a/debian/source/format b/debian/source/format
new file mode 100644 (file)
index 0000000..9f67427
--- /dev/null
@@ -0,0 +1 @@
+3.0 (native)
\ No newline at end of file
index 382b779de61ae51d3ab130eae54745134e463b39..dfcc44a30bbd8999c60cbe44bd2f8a5464853320 100755 (executable)
@@ -39,6 +39,7 @@ my %bugclosers = count_bugs(function => sub {
 
 open BUGCLOSERS, '> /org/bugs.debian.org/www/stats/bugclosers.txt.new'
     or die "can't open bugclosers.txt.new: $!";
+binmode(BUGCLOSERS,':raw:encoding(UTF-8)');
 for my $closer (sort { $bugclosers{$a} <=> $bugclosers{$b} } keys %bugclosers) {
     printf BUGCLOSERS "%4d %s\n", $bugclosers{$closer}, $closer
        or die "can't write to bugclosers.txt.new: $!";
index c251cea97376a7845f37646819bf34361a9d422e..9019b9d8a32d3f21cf1ffdb8970d5bf25bc3e908 100644 (file)
@@ -99,7 +99,7 @@ a.submitter:hover, a.submitter:visited:hover {
 
 pre.message {
     font-family: monospace;
-    padding-top: 0;
+    padding-top: 8px;
     margin-top: 0;
     border-top: 0;
 }
@@ -133,6 +133,15 @@ div.headers {
     overflow: auto;
  }
 
+div.header {
+    font-family: sans-serif;
+    font-size: 95%;
+    color: #3c3c3c;
+    padding: 0px;
+    line-height: 120%;
+    margin: 0px;
+}
+
 div.headers p {
     font-family: sans-serif;
     font-size: 95%;
@@ -146,7 +155,7 @@ div.headers img {
     float: right;
 }
 
-span.header { 
+span.headerfield { 
   font-weight: bold
  };
 
index 8fb590fcd65d1f2b6e8503820a354860cf62530b..2f1d2dfb8371d8736fa759c0573f003f2583c562 100644 (file)
@@ -2,4 +2,6 @@
 use Test::More;
 eval "use Test::Pod 1.00";
 plan skip_all => "Test::Pod 1.00 required for testing POD" if $@;
-all_pod_files_ok(all_pod_files('.'));
+all_pod_files_ok(grep {$_ !~ /[~#]$/} all_pod_files((-e 'blib'?'blib':(qw(Debbugs Mail))),
+                                                     (qw(bin cgi scripts))
+                                                    ));
diff --git a/t/15_rebuild_indexdb.t b/t/15_rebuild_indexdb.t
new file mode 100644 (file)
index 0000000..a3036ec
--- /dev/null
@@ -0,0 +1,128 @@
+# -*- mode: cperl;-*-
+
+use Test::More tests => 9;
+
+use warnings;
+use strict;
+
+use utf8;
+
+# Here, we're going to shoot messages through a set of things that can
+# happen.
+
+# First, we're going to send mesages to receive.
+# To do so, we'll first send a message to submit,
+# then send messages to the newly created bugnumber.
+
+use IO::File;
+use File::Temp qw(tempdir);
+use Cwd qw(getcwd);
+use Debbugs::MIME qw(create_mime_message);
+use File::Basename qw(dirname basename);
+# The test functions are placed here to make things easier
+use lib qw(t/lib);
+use DebbugsTest qw(:all);
+use Data::Dumper;
+use Encode qw(decode encode decode_utf8 encode_utf8);
+
+# HTTP::Server:::Simple defines a SIG{CHLD} handler that breaks system; undef it here.
+$SIG{CHLD} = sub {};
+my %config;
+eval {
+     %config = create_debbugs_configuration(debug => exists $ENV{DEBUG}?$ENV{DEBUG}:0);
+};
+if ($@) {
+     BAIL_OUT($@);
+}
+
+my $sendmail_dir = $config{sendmail_dir};
+my $spool_dir = $config{spool_dir};
+my $config_dir = $config{config_dir};
+
+END{
+     if ($ENV{DEBUG}) {
+         diag("spool_dir:   $spool_dir\n");
+         diag("config_dir:   $config_dir\n");
+         diag("sendmail_dir: $sendmail_dir\n");
+     }
+}
+
+# We're going to use create mime message to create these messages, and
+# then just send them to receive.
+
+send_message(to=>'submit@bugs.something',
+            headers => [To   => 'submit@bugs.something',
+                        From => 'föoff@bugs.something',
+                        Subject => 'Submiting a bug',
+                       ],
+            body => <<EOF,attachments => [{Type=>"text/plain",Charset=>"utf-8",Data=><<EOF2}]) or fail('Unable to send message');
+Package: foo
+Severity: normal
+
+This is a silly bug
+EOF
+This is the silly bug's test ütff8 attachment.
+EOF2
+
+
+
+# now we check to see that we have a bug, and nextnumber has been incremented
+ok(-e "$spool_dir/db-h/01/1.log",'log file created');
+ok(-e "$spool_dir/db-h/01/1.summary",'sumary file created');
+ok(-e "$spool_dir/db-h/01/1.status",'status file created');
+ok(-e "$spool_dir/db-h/01/1.report",'report file created');
+ok(system('sh','-c','[ $(grep "attachment." '.$spool_dir.'/db-h/01/1.log|grep -v "ütff8"|wc -l) -eq 0 ]') == 0,
+   'Everything attachment is escaped properly');
+
+# next, we check to see that (at least) the proper messages have been
+# sent out. 1) ack to submitter 2) mail to maintainer
+
+# This keeps track of the previous size of the sendmail directory
+my $SD_SIZE = 0;
+$SD_SIZE =
+    num_messages_sent($SD_SIZE,2,
+                     $sendmail_dir,
+                     'submit messages appear to have been sent out properly',
+                    );
+
+
+# now send a message to the bug
+
+send_message(to => '1@bugs.something',
+            headers => [To   => '1@bugs.something',
+                        From => 'föoff@bugs.something',
+                        Subject => 'Sending a message to a bug',
+                       ],
+            body => <<EOF) or fail('sending message to 1@bugs.someting failed');
+Package: foo
+Severity: normal
+
+This is a silly bug
+EOF
+
+$SD_SIZE =
+    num_messages_sent($SD_SIZE,2,
+                     $sendmail_dir,
+                     '1@bugs.something messages appear to have been sent out properly');
+
+# just check to see that control doesn't explode
+send_message(to => 'control@bugs.something',
+            headers => [To   => 'control@bugs.something',
+                        From => 'föoff@bugs.something',
+                        Subject => 'Munging a bug',
+                       ],
+            body => <<EOF) or fail 'message to control@bugs.something failed';
+severity 1 wishlist
+retitle 1 ütff8 title encoding test
+thanks
+EOF
+
+$SD_SIZE =
+   num_messages_sent($SD_SIZE,1,
+                    $sendmail_dir,
+                    'control@bugs.something messages appear to have been sent out properly');
+# now we need to check to make sure the control message was processed without errors
+# now we need to check to make sure that the control message actually did anything
+# This is an eval because $ENV{DEBBUGS_CONFIG_FILE} isn't set at BEGIN{} time
+eval "use Debbugs::Status qw(read_bug writebug);";
+ok(system('bin/debbugs-rebuild-index.db')==0,'debbugs-rebuild-index seems to work');
index 253f1d7acbe61f9d5dedae7cd549299f5560dcf0..df280061512421f67fe3045652ab8810cc3c1567 100644 (file)
@@ -111,9 +111,11 @@ END
            "$spool_dir/index.archive");
 
      # create the spool files and sub directories
-     map {system('mkdir','-p',"$spool_dir/$_"); }
-         map {('db-h/'.$_,'archive/'.$_)}
-              map { sprintf "%02d",$_ % 100} 0..99;
+     for my $dir (0..99) {
+         for my $archive (qw(db-h archive)) {
+             system('mkdir','-p',"$spool_dir/$archive/".sprintf('%02d',$dir));
+         }
+     }
      system('mkdir','-p',"$spool_dir/incoming");
      system('mkdir','-p',"$spool_dir/lock");
 
@@ -156,8 +158,9 @@ sub send_message{
      $ENV{LOCAL_PART} = $param{to};
      my ($rfd,$wfd);
      my $output='';
-     local $SIG{PIPE} = 'IGNORE';
-     local $SIG{CHLD} = sub {};
+     my $pipe_handler = $SIG{PIPE};
+     $SIG{PIPE} = 'IGNORE';
+     $SIG{CHLD} = 'DEFAULT';
      my $pid = open3($wfd,$rfd,$rfd,'scripts/receive')
          or die "Unable to start receive: $!";
      print {$wfd} create_mime_message($param{headers},
@@ -165,6 +168,7 @@ sub send_message{
                                      $param{attachments}) or
                                          die "Unable to to print to receive";
      close($wfd) or die "Unable to close receive";
+     $SIG{PIPE} = $pipe_handler;
      my $err = $? >> 8;
      my $childpid = waitpid($pid,0);
      if ($childpid != -1) {
index 070005abdd1e40517e1449e4269ff029054c993b..66a1ca2dd0f132b4b57ff83af1dfe07049e9891e 100644 (file)
@@ -43,7 +43,7 @@ function toggle_infmessages()
 }
 {$log}
 <hr>
-<p class="msgreceived">Send a report that <a href="http://{$config{cgi_domain}}/bugspam.cgi">this bug log contains spam</a>.</p>
+<p class="msgreceived">Send a report that <a href="http://{$config{cgi_domain}}/bugspam.cgi?bug={$bug_num}">this bug log contains spam</a>.</p>
 <hr>
 {include(q(html/html_tail))}
 </body>