DSPAM WebUI. Исправляем кодировку на странице истории.
У DSPAM’а есть одна неприятная особенность. На странице “история” вместо темы письма в некоторых случаях отображаются кракозябры. Происходит это потому, что письма приходят в разных кодировках и информация из них заносится в логи как есть, без перекодировок. dspam.cgi же в свою очередь просто берет информацию из лога и выводит тоже как есть. Сегодня меня эта особенность достала окончательно и я решил научить dspam.cgi определять кодировку и перекодировать строки. Результат выкладываю. Оранжевым для наглядности выделены добавленные или измененные строки.
Нам потребуется perl’овый модуль Lingua::DetectCyrillic. Инсталлируем:
# cpan Lingua::DetectCyrillic
Теперь редактируем dspam.cgi.
Находим:
use strict;
use Time::Local;
use vars qw { %CONFIG %DATA %FORM $MAILBOX $CURRENT_USER $USER $TMPFILE};
use vars qw { $CURRENT_STORE };
require "ctime.pl";
Заменяем на:
use strict;
use Time::Local;
use Lingua::DetectCyrillic qw ( &TranslateCyr &toLowerCyr &toUpperCyr );
use vars qw { %CONFIG %DATA %FORM $MAILBOX $CURRENT_USER $USER $TMPFILE};
use vars qw { $CURRENT_STORE };
require "ctime.pl";
Находим:
my($path) = "$USER.frag/$signature.frag";
if (-e $path) {
my(%pairs);
$pairs{'template'} = "fragment";
$pairs{'signatureID'} = $signature;
my($sub) = $subject;
$sub =~ s/#//g;
$sub =~ s/(['])/\$1/g;
$pairs{'subject'} = $sub;
$pairs{'from'} = $from;
$pairs{'info'} = $info;
$pairs{'time'} = $ctime;
$pairs{'user'} = $FORM{'user'};
my($url) = &SafeVars(%pairs);
$from = qq!<a href="javascript:openwin(580,400,1,'$CONFIG{'ME'}?$url')">$from</a>!;
}
my($entry) = <<_END;
<tr>
<td class="$cl $rowclass" nowrap="true"><small>$cllabel</td>
<td class="$rowclass" nowrap="true"><small>
<input name="msgid$retrain_checked_msg_no" type="checkbox" value="$rclass:$signature">
$retrain</td>
<td class="$rowclass" nowrap="true"><small>$ctime</td>
<td class="$rowclass" nowrap="true"><small>$from</td>
<td class="$rowclass" nowrap="true"><small>$subject</td>
<td class="$rowclass" nowrap="true"><small>$info</td>
</tr>
Заменяем на:
my($path) = "$USER.frag/$signature.frag";
if (-e $path) {
my(%pairs);
$pairs{'template'} = "fragment";
$pairs{'signatureID'} = $signature;
my($sub) = $subject;
$sub =~ s/#//g;
$sub =~ s/(['])/\$1/g;
$pairs{'subject'} = $sub;
$pairs{'from'} = $from;
$pairs{'info'} = $info;
$pairs{'time'} = $ctime;
$pairs{'user'} = $FORM{'user'};
my($url) = &SafeVars(%pairs);
$from = qq!<a href="javascript:openwin(580,400,1,'$CONFIG{'ME'}?$url')">$from</a>!;
}
# Add еncoding detection and convertion
my %PREFS;
my $to_charset;
my $subj_decoded;
my $from_decoded;
%PREFS = GetPrefs();
$to_charset = $PREFS{'webCharset'};
my $CyrDetector = Lingua::DetectCyrillic ->new();
my ($Coding,$Language,$CharsProcessed,$Algorithm)= $CyrDetector -> Detect( $subject );
my $subj_decoded=TranslateCyr($Coding,$to_charset,$subject);
my ($Coding,$Language,$CharsProcessed,$Algorithm)= $CyrDetector -> Detect( $from );
my $from_decoded=TranslateCyr($Coding,$to_charset,$from);
my($entry) = <<_END;
<tr>
<td class="$cl $rowclass" nowrap="true"><small>$cllabel</td>
<td class="$rowclass" nowrap="true"><small>
<input name="msgid$retrain_checked_msg_no" type="checkbox" value="$rclass:$signature">
$retrain</td>
<td class="$rowclass" nowrap="true"><small>$ctime</td>
<td class="$rowclass" nowrap="true"><small>$from_decoded</td>
<td class="$rowclass" nowrap="true"><small>$subj_decoded</td>
<td class="$rowclass" nowrap="true"><small>$info</td>
</tr>
Теперь в файл default.prefs добавляем параметр webCharset и указываем в какой кодировке мы хотим получать текст на странице (например webCharset=win). Допустимые значения: win, koi, koi8u, mac, iso, dos, utf.
diff’ы:
dspam.cgi:
# diff dspam.cgi.bak dspam.cgi
22a23
> use Lingua::DetectCyrillic qw ( &TranslateCyr &toLowerCyr &toUpperCyr );
408a410,421
> # Added by woland. Encoding detection patch
> my %PREFS;
> my $to_charset;
> my $subj_decoded;
> my $from_decoded;
> %PREFS = GetPrefs();
> $to_charset = $PREFS{‘webCharset’};
> my $CyrDetector = Lingua::DetectCyrillic ->new();
> my ($Coding,$Language,$CharsProcessed,$Algorithm)= $CyrDetector -> Detect( $subject );
> my $subj_decoded=TranslateCyr($Coding,$to_charset,$subject);
> my ($Coding,$Language,$CharsProcessed,$Algorithm)= $CyrDetector -> Detect( $from );
> my $from_decoded=TranslateCyr($Coding,$to_charset,$from);
417,418c430,431
< <td class=”$rowclass” nowrap=”true”><small>$from</td>
< <td class=”$rowclass” nowrap=”true”><small>$subject</td>
—
> <td class=”$rowclass” nowrap=”true”><small>$from_decoded</td>
> <td class=”$rowclass” nowrap=”true”><small>$subj_decoded</td>
default.prefs:
# diff default.prefs.bak default.prefs
8a9
> webCharset=koi
Дополнительные записи:

4 комментариев
Возможно это работает, у меня почему-то не хочет…
После установки Lingua::DetectCyrillic что-то делать нужно?
Всё сделал как написано всё то-же самое… Причем никаких ошибок в логах апача нет…
Где ещё что посмотреть? Что сделать?…
Аааа… понял… он перекодирует History… А чего его перекодировать?… оно и так более-менее нормально отображается….
Больше интересна тема как там же перекодировать “Карантин”…
=?koi8-r?B?+uH96fTp8/gg7/Qg7ens6ePl6vPr7+fvICDy4eT…
Как вот с этим бороться?…
Аааа… Всё, понял… “Переводится” только лишь “История”…
А как в “карантине” перевести строки типа =?koi8-r?B?+uH96fTp8/gg7/Qg7ens6ePl6vPr7+fvICDy4eT…
? Что с ними можно сделать? А-то прочитать сие чудо нереально вообще…
Я карантин не использую, соответственно не задавался такой целью.
P.S. Скоро буду делать инсталляцию с карантином, тогда может быть и придумаю чего :)