Мы работаем! Пишите WhatsApp / Viber / Telegram: +7 951 127-23-57, Skype: creograf

Записи по тегу utf-8

Смена кодировки сайта на perl'e с window-1251 на utf8. Продолжение...

14:09:36 21.02.2011 Комментарии: 1

Описанный ранее автоматический способ перевода сайта на perl'e с виндовской кодировки в юникод разбился об реальность %). Опишу проблемы, с которыми пришлось столкнуться, может быть кому-то пригодится.

1. База данных. В моем случае - это mysql. У каждого скаляра, вынутого из базы данных, должна стоять галочка, что он в utf8. В противном случае не будут работать regexp'ы и проч. Можно помечать их utf8-ом руками: 

  utf8::decode($string_from_db);

Но если применить это к двоичным данным из blob'ов, то что-нибудь может сломаться. Альтернативный вариант - это после соединения с БД сообщить DBI, что данные в utf8.

  $dbh->{'mysql_enable_utf8'} = 1 if($encoding=~/utf/i);

Тогда она должна сама переводить строки в utf8, а blob не трогать. Должна, но на хостинге у nic.ru почему-то то работает, то не работает. Вроде бы в третьей DBI были какие-то косяки с utf8.   
Вот не очень красивый, но эффективный способ это полечить:

my $rusletters = qr{А-Яа-я};
#...
# для всего, что вытаскивается из бд
_fix_utf8($data_from_db); 

#...

# если кодировка utf8, то
# у все, что вытаскивается из БД, нужено пометить, как utf8
sub _fix_utf8 {
	my $arg = shift;
 #   return $arg; #!! off
 	return undef unless ( defined $arg );
	return $arg unless ( $encoding =~ /utf/i );

	unless ( ref $arg ) {
		utf8::decode( $arg ) if (utf8::valid($arg) and !utf8::is_utf8( $arg ) and $arg=~$rusletters);
		return $arg;
	}
	elsif ( ref $arg eq "ARRAY" ) {
		return _fix_utf8_array($arg);
	}
	elsif ( ref $arg eq "HASH" ) {
		die "hash?";
		return _fix_utf8_hash($arg);
	}
	return $arg;
}

sub _fix_utf8_array {
	my $arg = shift;

	return $arg unless ( ref $arg eq "ARRAY" );

	for ( my $i = 0 ; $i < 1 + $#$arg ; $i++ ) {
		$arg->[$i] = _fix_utf8_array( $arg->[$i] )
		  if ( ref $arg->[$i] eq "ARRAY" );
		$arg->[$i] = _fix_utf8( $arg->[$i] ) unless ( ref $arg->[$i] );
	}
	return $arg;
}

Он помечает utf-8 все строки, которые не помечены utf8, и содержат буквы А-Яа-я в юникоде. В общем-то в буквах А-Яа-я вся некрасивость.

2. Во всех модулях, где в качестве значения переменных используется utf-8, надо писать

  use utf8;
  #...
  $param->{ModuleName}="Блог";

Тоже самое, если в модуле выполняются regexp'ы над юникодными строками.

3. Всех параметры http-запросов, кроме файлов, надо декодить в utf8, например так:

  foreach ( $self->{httprequest}->param ) {
    utf8::decode($k);
    if ( $v && !( ref $v && fileno($v) ) ) {
      $k =~ s/\.x//go;
      next if ( $k =~ /\.y/ );
      utf8::decode($v);
    }
    $self->{entry}->{$k} = $v;

4. Отправку писем в utf8 тоже пришлось переписать. Подробности в предыдущем посте

5. Пришлось поправить модуль DBIx::FullIndexSearch. Кому надо, пишите, выложу.

6. При открытии файлов надо указывать, что они в utf8:

  open my $fh, '<:utf8', $tname or die $!;
Теги: perl,utf-8

Отправка письма на Perl через SMTP с аутентификацией и аттачем в utf-8

06:48:44 21.02.2011 Комментарии: 1

Вот модуль, который отправляет письма через SMTP сервер с аутентификацией. Можно прикреплять файлы и передавать текст в юникоде.

Это продолжение поста Отправка письма на Perl через SMTP с аутентификацией и аттачем.

package Mail;
use Exporter;

@ISA = ('Exporter');

#@EXPORT=qw(&SendMail &GetLastSendMailError);
@EXPORT = qw();
use vars qw($Error_Message);

use strict;
use warnings;
use Net::SMTP;
use MIME::Base64;

sub GetLastSendMailError {
	$Error_Message;
}

sub SendMail {
	my $fuc   = shift;
	my $param = shift;
	$param->{smtp_server} ||= "mail.nic.ru";
	$param->{login}       ||= "";
	$param->{password}    ||= "";

	$fuc->Error( "Send mail from " . $param->{to} . " to " . $param->{from} )
	  unless ( $param->{to} && $param->{from} );

    #my $encoding = $fuc->GetParam('Encoding');
    my $encoding = $fuc->GetParam( 'General', 'Encoding' );

	my @files;
	@files = @{ $param->{files} } if ( ref $param->{files} eq "ARRAY" );

	my $msg = "MIME-Version: 1.0\r\n";

	my $mime_id = 'fuc-' . time;
	if ( !$files[0] ) {
		$msg .= "Content-Type: text/plain; charset=$encoding\r\n";
		$msg .=
		    "From: "
		  . $param->{from} . "\r\n"
		  . "Subject: "
		  . $param->{subject}
		  . "\r\n\r\n";
		$msg .= $param->{body} . "\r\n" if ( $param->{body} and !$files[0] );

	}
	else {
		$msg .= "Content-Type: multipart/mixed; boundary=" . $mime_id . "\r\n";
		$msg .=
		    "From: "
		  . $param->{from} . "\r\n"
		  . "Subject: "
		  . $param->{subject}
		  . "\r\n\r\n";

		if ( $param->{body} ) {
			$msg .=
			    "--$mime_id\r\n"
			  . "Content-Type: text/plain; charset=$encoding\r\n"
			  . "Content-Transfer-Encoding: quoted-printable\r\n\r\n"
			  . $param->{body}
			  . "\r\n\r\n";
		}

		for ( my $i = 0 ; $i < ( 1 + $#files ) ; $i++ ) {
			next unless ( $files[$i] );

			my $attach_file = $files[0];

			#   $attach_file =~ /[\\\/:]([^\\\/:]+)$/g;
			$attach_file =~ /.*(\.[^.]*)/;
			my $filename = "attach" . $1;

			$msg .=
			    "--$mime_id\r\n"
			  . "Content-Type: application/octet-stream; name=$filename\r\n"
			  . "Content-Transfer-Encoding: base64\r\n"
			  . "Content-Disposition: attachment; filename=$filename\r\n";

			local $/;
			seek $attach_file, 0, 0;
			my $cont = <$attach_file>;

			my $base64_encoded_data = encode_base64($cont);
			if ( !$base64_encoded_data ) { return (11) }

			$msg .= "\r\n" . $base64_encoded_data . "--$mime_id--\r\n\r\n";

		}
	}

    utf8::encode($msg) if($encoding =~/utf/i);
	my $smtp = Net::SMTP->new( $param->{smtpserver}, Timeout => 120) #, Debug => 1 
	  or die "Cannot connect to smtp server";

	$smtp->auth( $param->{login}, $param->{password} )
	  if ( $param->{login} && $param->{password} );
	$smtp->mail( $param->{from} );
	$smtp->to( $param->{to} );
	$smtp->data();
	#$smtp->datasend($msg);
	#$smtp->dataend();
	#utf8
    while ( $msg =~ m/([^\r\n]*)(\r\n|\n\r|\r|\n)?/g ) {
        my $line = ( defined($1) ? $1 : "" ) . "\r\n";
        $smtp->datasend( $line );
    }
    $smtp->dataend();
	$smtp->quit;

}

1;
=pod

=head1 NAME 

Mail.pm

=head1 DESCRIPTION

Отправляет почту через smtp-сервер, поддерживает аутентификацию через md5 хэш. Отправляет файлы. Текст письма отправляется в windows-1251.

	Mail::SendMail(
		{
			smtpserver => "smtp.testmail.com",
			login => "login",
			password => "password",
			subject => "creograf.ru",
			from => "email@from.ru",
			to   => "email@to.ru",
			body => "test mail",
			files => [$testfilehandle],
		}

}

 
=head1 COPYRIGHT

Деева А.С., Студия "Креограф" L, L

=cut
Теги: perl,utf-8

Смена кодировки сайта на perl'e с window-1251 на utf8

06:46:35 17.02.2011 Комментарии: 0

Максимально автоматизированный способ перевода сайта с windows-1251 на utf-8.

читать дальше

Теги: mysql,perl,utf-8
© 2002-2022 Креограф. Все права защищены законом РФ
 Русский /  English