• Publicidad

Unicode (UTF-8) en la salida de CGI

¿Ya sabes lo que es una referencia? Has progresado, el nível básico es cosa del pasado y ahora estás listo para el siguiente nivel.

Unicode (UTF-8) en la salida de CGI

Notapor seafree » 2014-07-17 11:41 @528

En la codificación de los programas desarrollados declaro use utf8, sin embargo al acceder por ejemplo al proceso de Actualizar e ir navegando en el sistema la Codificación en Internet Explorer 11.0.9600.17126 se convierte a Europeo Occidental (ISO) y se pierde el UTF8. Supuse la probabilidad de que fuera el navegador y probé con el Google Chrome pero sucede lo mismo. ¿De qué manera puedo visualizar correctamente todos los caracteres?

Gracias.
seafree
Perlero nuevo
Perlero nuevo
 
Mensajes: 296
Registrado: 2012-08-10 11:26 @518

Publicidad

Re: Unicode (UTF-8)

Notapor explorer » 2014-07-17 15:39 @694

No, no es así.

use utf8; sirve para indicar a Perl que ese programa está escrito en esa codificación (es decir, que dentro del código del programa, hay caracteres codificados en utf-8).

NO quiere decir que la entrada y/o la salida del programa sea en esa codificación. Perl seguirá trabajando en codificación ISO-8859-1 (latin1 o Windows 1252) con las entradas y salidas.

Si quieres que las salidas sean con codificación utf-8 pues hay que indicarlo de forma expresa.

Por favor, repasa el hilo 44 recetas para trabajar con Unicode en Perl, sobre todo las recetas 15 y siguientes. Quizás, con un simple

use open qw(:std :utf8);

podría ser más que suficiente.

Pero aún hay más...

No vale solo con que la salida vaya codificada en UTF-8. Dices que estás usando navegadores web, así que podemos pensar que lo que estás viendo es la salida de un programa Perl en un navegador web (lo que es un CGI, por ejemplo). Bueno, entonces estamos hablando de que la salida es una página codificada en HTML...

Bueno, pues en la cabecera HTML hay que indicar en qué está codificada esa página. Si está en UTF-8, en la cabecera (<head>) del HTML debe aparecer esto:

<meta charset="UTF-8">

en caso de estar generando HTML v5. Para HTML v4 usar esto otro:

<meta http-equiv="Content-Type" content="text/html; charset=utf-8">

Por otra parte, si el servidor web es tuyo o está bajo tu control, puedes configurarlo para que incorpore la codificación UTF-8 en las cabeceras de respuesta HTTP, por lo que los navegadores aplicarán la codificación para todo lo que reciban. Bastaría con añadir

AddDefaultCharset UTF-8

en un archivo .htaccess local o en la definición del dominio (todo esto para el caso de un servidor Apache).

Más información
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14475
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Unicode (UTF-8)

Notapor seafree » 2014-07-18 09:36 @442

Gracias, explorer.
seafree
Perlero nuevo
Perlero nuevo
 
Mensajes: 296
Registrado: 2012-08-10 11:26 @518

Re: Unicode (UTF-8)

Notapor seafree » 2015-02-26 16:06 @712

Hola, explorer, empleo tus sugerencias pero no obtengo el resultado deseado. Pensé que ya había funcionado pero no. Te mando el código que estoy utilizando esperando que me puedas apoyar:

Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #! /usr/bin/perl -w
  2. use CGI qw(:standard :netscape :shortcuts);
  3. use CGI::Carp qw/fatalsToBrowser/;
  4. use DBI;
  5. use strict;
  6. use URI::Escape;
  7. use Switch;
  8. use open qw(:utf8);
  9. ...
  10. ...
  11. ...
  12. print header;
  13. print start_html (-title=>"SOLUCION");
  14. print<<"HTML";
  15. <!DOCtype HTML PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
  16. <html xmlns="http://www.w3.org/1999/xhtml">
  17. <head>
  18. <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8">
  19. <script type="text/JavaScript" src="/prototype.js"></script>
  20. </head>
  21. HTML
  22. ...
  23. ...
  24. ...
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4


¿Cuáles son tus sugerencias? Gracias.
seafree
Perlero nuevo
Perlero nuevo
 
Mensajes: 296
Registrado: 2012-08-10 11:26 @518

Re: Unicode (UTF-8)

Notapor explorer » 2015-02-26 18:03 @794

Primero, unos comentarios sobre el código...

:netscape no te hace falta, pues solo sirve para importar marcas HTML que están ya obsoletas

:shortcuts no es una opción válida para CGI

El módulo Switch se recomienda no usarlo bajo ninguna circunstancia.

use open qw(:utf8); no está bien escrito. Aclarado en el ejemplo de abajo.

El uso de <<HTML demuestra que no acabas de entender la utilidad de use CGI ':standard': No es necesario poner código HTML explícitamente, ya que se puede abreviar con la ayuda de funciones que CGI nos da.

Este es un ejemplo de un CGI que saca su salida en formato utf8:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use CGI       qw(:standard :utf8);
  3. use CGI::Carp qw(fatalsToBrowser);
  4.  
  5. use strict;
  6. use warnings;
  7. use utf8;
  8.  
  9. use open OUT => ':utf8';        # Salida en utf8
  10. use open ':std';                # incluida la salida estándar
  11.  
  12. my $parametro = query_string(); # 'keywords=A1'
  13. #print "$parametro\n";
  14. #$parametro = (split ";", $parametro)[0];
  15. ($parametro) = split "=", $parametro;
  16. #print "$parametro\n";
  17.  
  18. if    ( $parametro eq 'A1' ) { AlmacenaCaracteresSinAjax() }
  19. elsif ( $parametro eq 'A2' ) { AlmacenaCaracteresConAjax() }
  20.  
  21.  
  22. sub AlmacenaCaracteresSinAjax {
  23.     my $cadena = param('cadena');
  24. #    my $cadena = decode('utf8', param('cadena'));
  25. #    my $cadena = decode_utf8(param('cadena'));
  26.  
  27.     print
  28.         header(
  29.             -charset => 'utf-8',
  30.             -type    => 'text/html',
  31.         ),
  32.         start_html,
  33.         p("Sin Ajax: $cadena."),
  34.         end_html,
  35.         ;
  36. }
  37.  
  38. sub AlmacenaCaracteresConAjax {
  39.     my $cadena = param('cadena');
  40.  
  41.     print
  42.         header(
  43.             -charset => 'utf-8',
  44.             -type    => 'text/plain',
  45.         ),
  46.         "Con Ajax: $cadena",
  47.         ;
  48. }
  49.  
  50. __END__
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
Este programa es un cgi, pero se puede ejecutar desde la línea de comandos, para hacer una prueba:

perl pruebautf8.pl A1=1 cadena=Camión

La salida es:
Sintáxis: [ Descargar ] [ Ocultar ]
Using text Syntax Highlighting
Content-Type: text/html; charset=utf-8

<!DOCTYPE html
        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head>
<body>
<p>Sin Ajax: Camión.</p>
</body>
</html>
Coloreado en 0.000 segundos, usando GeSHi 1.0.8.4

La clave está en:
  • hay dos 'use open' que indican que la salida estándar debe ir en utf8
  • las líneas 24 y 25, que están comentadas, sirven para decodificar los parámetros pasados al programa, si estuvieran en utf8. Recordar que hay que decodificar lo que recibimos, y codificar lo que entregamos
  • a la hora de la salida, en el método header(), indicamos que el 'charset' es utf-8
Aquí hay otro ejemplo, en la que se usan textos literales, para demostrar que salen bien:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. # Joaquín Ferrero. 2013.
  3. # Prueba de Ajax con caracteres utf8
  4. #
  5. use Encode;                                  # de/codificación
  6. use CGI       qw(:standard      );           # procesamiento de los parámetros
  7. use CGI::Carp qw(fatalsToBrowser);           # en caso de error grave, verlos en la ventana del navegador web
  8.  
  9. use strict;                                  # activar modo estricto
  10. use warnings;                                # activar las advertencias
  11. use utf8;                                    # lo pongo porque más abajo hay algunos caracteres tildados
  12. #use open IO => ':utf8';                     # indico que las salidas de archivos serán en utf8,
  13. use open qw':utf8 :std';                             # especialmente STDIN, STDOUT y STDERR
  14.  
  15. my $parametro = param('t');                  # no decodificamos el parámetro "t" porque sabemos
  16.                                              # que solo va a valer dos valores: A1 y A2,
  17.                                              # y esos valores no tienen tildes
  18.  
  19. if    ( $parametro eq 'A1' ) { AlmacenaCaracteres('Sin') }   # caso sin Ajax
  20. elsif ( $parametro eq 'A2' ) { AlmacenaCaracteres('Con') }   # caso con Ajax
  21. else  {                                                      # algo pasó: pintar página de error
  22.     print
  23.         header(-charset => 'utf-8'),                         # vamos a sacar una cabecera HTTP. Indicamos además que lo mandaremos en utf8
  24.         start_html('Error'),                                 # empezamos a enviar el código HTML de la página de error. El título será 'Error'
  25.         h1('Error'),                                         # dentro de la página, un gigantesco 'Error'
  26.         hr,                                                  # una regla horizontal, para hacer bonito
  27.         p('Caracteres especiales: [áéíóúüñçÁÉÍÓÚÜÑÇ]'),      # una demostración de que la salida de caracteres tildados funciona bien
  28.         hr,
  29.         ;
  30.  
  31.     my @parametros = param();                                # volcado de todos los parámetros recibidos, en caso de haber alguno
  32.     foreach my $par ( @parametros ) {                        # recorremos todos los parámetros
  33.         print p($par);                                       # primero ponemos en un párrafo, el nombre del párrafo
  34.         print blockquote(param( $par ));                     # seguido por el valor del parámetro
  35.     }
  36.  
  37.     print
  38.         end_html,                                            # terminamos la página de error
  39.         ;
  40. }
  41.  
  42. # fin de programa
  43.  
  44. # subrutinas
  45. sub AlmacenaCaracteres {
  46.     my $sin_con = shift;                                     # con gas o sin gas
  47.     my $cadena = decode_utf8(param('cadena'));               # decodificación del parámetro 'cadena'
  48. #    my $cadena = param('cadena');                            # extracción del parámetro 'cadena'
  49.  
  50.     print                                                    # esta es la respuesta que mandamos fuera
  51.         header(                                              # creamos una cabecera HTTP
  52.             -charset => 'utf-8',                             # lo que vamos a enviar va a estar en utf8
  53.             -type    => 'text/plain',                        # vamos a enviar puro texto
  54.         ),
  55.         "$sin_con Ajax: $cadena",                            # y este es el texto que enviamos
  56.         ;
  57. }
  58.  
  59. __END__
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

En este caso, el 'use open' indica que está en utf8 las entradas y salidas estándar.

Y hay una línea con un decode_utf8(), pues sabemos que vamos a recibir texto codificado en utf8.
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14475
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Unicode (UTF-8)

Notapor seafree » 2015-02-27 13:05 @586

Gracias Explorer, lo del uso del HTML es una pésima práctica que debo evitar.

Probé el ejemplo que me compartiste:

# perl pruebautf8.pl A1=1 cadena=Camión
Content-Type: text/html; charset=utf-8
PROGRAMA:

!/usr/bin/perl
use CGI qw(:standard :utf8);
use CGI::Carp qw(fatalsToBrowser);
use strict;
use warnings;
use utf8;
use open OUT => ':utf8'; # Salida en utf8
use open ':std'; # incluida la salida estándar
my $parametro = query_string(); # 'keywords=A1'
#$parametro = (split ";", $parametro)[0];
($parametro) = split "=", $parametro;
#print "$parametro\n";
if ( $parametro eq 'A1' ) { AlmacenaCaracteresSinAjax() }
elsif ( $parametro eq 'A2' ) { AlmacenaCaracteresConAjax() }
sub AlmacenaCaracteresSinAjax {
my $cadena = param('cadena');
# my $cadena = decode('utf8', param('cadena'));
# my $cadena = decode_utf8(param('cadena'));
print
header(
-charset => 'utf-8',
-type => 'text/html',
),
start_html,
p("Sin Ajax: $cadena."),
end_html,
;
}

sub AlmacenaCaracteresConAjax {
my $cadena = param('cadena');
print
header(
-charset => 'utf-8',
-type => 'text/plain',
),
"Con Ajax: $cadena",
;
}

RESULTADO:

<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>Untitled Document</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<p>Sin Ajax: Camión.</p>
</body>
</html>

¿Qué estoy omitiendo?
seafree
Perlero nuevo
Perlero nuevo
 
Mensajes: 296
Registrado: 2012-08-10 11:26 @518

Re: Unicode (UTF-8)

Notapor explorer » 2015-02-27 13:19 @596

A ver... esto es gordo...

Le especificas que quieres un charset utf8, y resulta que te pone en la cabecera un charset iso-8859-1. ¿Y eso?

¿Qué versión de CGI estás usando?

Ejecuta

perl -MCGI -le 'print $CGI::VERSION'
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14475
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Unicode (UTF-8)

Notapor explorer » 2015-02-27 14:01 @625

También es posible... que tu terminal NO esté en utf-8...

La opción :utf8 que está en el 'use CGI' está indicando que la entrada de los parámetros al CGI van a estar codificados en utf8, así que está suponiendo que la línea que estás escribiendo en la terminal está codificada así (la 'ó' de Camión).

(P.D.: la opción :utf8 no es recomendable usarla en cgi que suben archivos -upload-)

Si luego sale mal, quizás es que la terminal no está en utf-8. En mi shell, sale:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. $ echo $LANG
  2. es_ES.UTF-8
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14475
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Re: Unicode (UTF-8)

Notapor seafree » 2015-02-27 14:13 @634

El archivo httpd.conf está configurado con UTF-8, como se muestra:

AddDefaultCharset UTF-8

En mi shell sale:
Sintáxis: [ Descargar ] [ Ocultar ]
Using bash Syntax Highlighting
  1. # echo $LANG
  2. en_US.UTF-8
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
seafree
Perlero nuevo
Perlero nuevo
 
Mensajes: 296
Registrado: 2012-08-10 11:26 @518

Re: Unicode (UTF-8)

Notapor explorer » 2015-02-27 15:30 @687

¿US? ¿Estados Unidos?

¿Y qué versión de CGI tienes? (repasa los mensajes anteriores).

Este es un ejemplo mínimo:
Sintáxis: [ Descargar ] [ Ocultar ]
Using perl Syntax Highlighting
  1. #!/usr/bin/perl
  2. use strict;
  3. use warnings;
  4.  
  5. use CGI       qw(:standard -utf8);      # importar las funciones estándares y los parámetros llegan en utf8
  6. use CGI::Carp qw(fatalsToBrowser);      # poner errores en el HTML de salida
  7.  
  8. use utf8;                               # hay caracteres utf8 en el código Perl
  9. use open qw<:utf8 :std>;                # utf8 en las entradas y salidas estándar
  10.  
  11. my $cadena = param('cadena');
  12.  
  13. print
  14.     header(
  15.         -charset => 'utf-8',
  16.         -type    => 'text/html',
  17.     ),
  18.     start_html,
  19.         p('[áéíóúüÁñÑ]'), "\n",
  20.         p($cadena),
  21.     end_html,
  22.     ;
  23.  
  24. __END__
Coloreado en 0.001 segundos, usando GeSHi 1.0.8.4
Con
perl utf8cgi.pl cadena=Camión

La salida debería ser:
Sintáxis: [ Descargar ] [ Ocultar ]
Using html4strict Syntax Highlighting
  1. Content-Type: text/html; charset=utf-8
  2.  
  3. <!DOCTYPE html
  4.        PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  5.         "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  6. <html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
  7. <head>
  8. <title>Untitled Document</title>
  9. <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  10. </head>
  11. <body>
  12. <p>[áéíóúüÁñÑ]</p>
  13. <p>Camión</p>
  14. </body>
  15. </html>
Coloreado en 0.002 segundos, usando GeSHi 1.0.8.4

Mira: http://joaquinferrero.com/cgi/utf8cgi.p ... ami%C3%B3n
JF^D Perl programming & Raku programming. Grupo en Telegram: https://t.me/Perl_ES
Avatar de Usuario
explorer
Administrador
Administrador
 
Mensajes: 14475
Registrado: 2005-07-24 18:12 @800
Ubicación: Valladolid, España

Siguiente

Volver a Intermedio

¿Quién está conectado?

Usuarios navegando por este Foro: No hay usuarios registrados visitando el Foro y 0 invitados

cron