I've tracked down a bug that was causing some users to
get inconsistent login errors on a machine that has
recently had the mbstring extension installed.
It seems that the default options for mbstring (there
are no relevant flag settings in httpd.conf or php.ini)
are to use an mbstring.internal_encoding of "UTF-8" and
mbstring.func_overload of, well that's a little odd.
mb_get_info() returns func_overload as the string
"pass". ini_get() reports it as "0", but it certainly
behaves as if it's set quite high.
The problem is that in processing the password,
Squirrelmail works internally with encrypted binary
strings, which are often likely to contain byte values
which signal the start of a multi-byte character.
OneTimePad(Decrypt/Encrypt) use strlen to determine the
number of bytes to process, but if mbstring function
overloading is active it will return instead the number
of characters, not the number of bytes, which will
often be smaller. This causes truncation of the
password and an inability to log in at all. (This is
definitely the point of failure - inserting lots of
echo statements shows clearly the mismatch between
string length and the value of strlen.)
func_overload can't be changed in a .htaccess file,
only in httpd.conf and php.ini. I also haven't had any
success trying to set the internal_encoding to a
single-byte encoding through .htaccess either, though
that ought to work.
I find I can get it working by issuing
mb_internal_encoding("ISO-8859-1"); at global level at
the start of functions/strings.php. Another option
would be to implement a str_bytelen function which
explicitly forces a single-byte encoding whenever it is
used with the mbstring extension enabled
(mb_strlen($str, "ISO-8859-1") should work), and use
this instead of plain strlen whenever processing
binary, non-text, strings. The pages themselves seem to
be delivered as ISO-8859-1 in any case, though that may
be an Apache default rather than deliberate action on
the part of Squirrelmail.
It would probably be a very good idea for Squirrelmail
to check for this case and report an error, since
func_overload clearly violates the expectations that
went into the code. As detailed above, mb_get_info and
ini_get don't seem reliable, or to match with reality.
However, by calling strlen on a specific string
containing several multibyte sequences one can
determine if overloading is active. For example
strlen("\xc3\xa0") should return 2 for a non-mbstring
aware strlen, but will return 1 if it's interpreting it
as a UTF-8 string. (A couple more sequences from other
multi-byte encodings would probably be a good idea, or
the internal_encoding could be temporarily switched to
UTF-8 for the duration of the test.)