Handling encoding issues
LemonLDAP::NG has to integrate with many external systems: HTTP servers and clients, databases, libraries (such as Lasso). At each integration point, it is crucial to ensure that text data is provided in the right form: text string, binary string, etc.
Passing an ISO-8859-1 string to a library that expects an UTF-8 string, or the other way around, will lead to text encoding issues: text will contain odd, unexpected or sometimes missing characters.
Text string and binary strings
Perl was invented before unicode was popular, therefore, even in modern systems, Perl assumes that the default character set is ISO-8859-1. Perl is also weak-typed, which means there is no clear difference between a binary string and a text string. Therefore, when manipulating variables that contain text, the developer must be aware of what format the text is supposed to be encoded as in the current context.
There is no way to distinguish whether a string contains text of binary data in Perl.
Because of this, we needs to have rules to decide if a given variable should contain text data or binary data.
The Perl documentation recommends to immediately decode binary data to text strings and manipulate text strings as much as we can.
However, external systems have no notion of text strings (or numbers, or objects, or cats), computers only understand binary data. Therefore, everytime you need to communicate with an external system, your text strings must be encoded to, or decoded from, binary data.
Some libraries expect text strings, and some others expect binary data, sadly the documentation is not always very clear about that. Some libraries let you decide with an option.
For example, in Net::LDAP, the raw option can be used to indicate which
attributes contain binary data. The other attributs will return or expect text
strings. As another example, the pg_enable_utf8 option makes DBI accept and
return text strings and not binary strings (except if the column type is a
binary type).
How to decode/encode data
In order to convert a text string to a binary string
use Encode;
# Session variables are stored as text strings
my $title = $req->sessionInfo->{title};
# Check that your original text string is correct
$self->p->_dump_string($title);
# Do not alter the original variable! Copy it and convert it to binary
# before handing it to the library
my $binary_title = encode("UTF-8", $title);
function_of_my_lib($binary_title);
In order to convert a binary string to a text sting
use Encode;
my $result = function_of_my_lib();
my $decoded_var = decode("UTF-8", $result);
# Check that your decoded text string is correct
$self->p->_dump_string($decoded_var);
$req->sessionInfo->{title} = $decoded_var;
Checking how Perl understands a string
LemonLDAP::NG provides a _dump_string method that will help you figure out
what a variable contains. It requires the logLevel to be set to debug.
$self->p->_dump_string($var);
[debug] $str = "Le\ Grand\ M\N{LATIN SMALL LETTER E WITH ACUTE}chant\ Loup"
You can use this method to verify if Perl has correctly understood the content of your text strings.
Note that is you try this method on a binary string, you will get erroneous results. This is confusing, but expected.