Source for file strings.php
Documentation is available at strings.php
* This code provides various string manipulation functions that are
* used by the rest of the SquirrelMail code.
* @copyright © 1999-2006 The SquirrelMail Project Team
* @license http://opensource.org/licenses/gpl-license.php GNU Public License
* @version $Id: strings.php,v 1.184.2.58 2006/08/11 11:24:05 kink Exp $
* SquirrelMail version number -- DO NOT CHANGE
$version =
'1.4.9 [CVS]';
* SquirrelMail internal version number -- DO NOT CHANGE
* $sm_internal_version = array (release, major, minor)
global $SQM_INTERNAL_VERSION;
$SQM_INTERNAL_VERSION =
array(1,4,9);
* There can be a circular issue with includes, where the $version string is
* referenced by the include of global.php, etc. before it's defined.
* For that reason, bring in global.php AFTER we define the version strings.
require_once(SM_PATH .
'functions/global.php');
* Wraps text at $wrap characters
* Has a problem with special HTML characters, so call this before
* you do character translation.
* Specifically, ' comes up as 5 characters instead of 1.
* This should not add newlines to the end of lines.
function sqWordWrap(&$line, $wrap, $charset=
null) {
global $languages, $squirrelmail_language;
if (isset
($languages[$squirrelmail_language]['XTRA_CODE']) &&
if (mb_detect_encoding($line) !=
'ASCII') {
$line =
$languages[$squirrelmail_language]['XTRA_CODE']('wordwrap', $line, $wrap);
ereg("^([\t >]*)([^\t >].*)?$", $line, $regs);
$beginning_spaces =
$regs[1];
$line =
$beginning_spaces;
while ($i <
count($words)) {
/* Force one word to be on a line (minimum) */
$line_len =
strlen($beginning_spaces) +
sq_strlen($words[$i],$charset) +
2;
if (isset
($words[$i +
1]))
$line_len +=
sq_strlen($words[$i +
1],$charset);
/* Add more words (as long as they fit) */
while ($line_len <
$wrap &&
$i <
count($words)) {
$line .=
' ' .
$words[$i];
$line_len +=
sq_strlen($words[$i],$charset) +
1;
/* Skip spaces if they are the first thing on a continued line */
while (!isset
($words[$i]) &&
$i <
count($words)) {
/* Go to the next line if we have more to process */
if ($i <
count($words)) {
* Does the opposite of sqWordWrap()
* @param string body the text to un-wordwrap
global $squirrelmail_language;
if ($squirrelmail_language ==
'ja_JP') {
for ($i =
0; $i <
$cnt; $i ++
) {
preg_match("/^([\t >]*)([^\t >].*)?$/", $lines[$i], $regs);
$CurrentSpaces =
$regs[1];
$PreviousSpaces =
$CurrentSpaces;
} else if (($PreviousSpaces ==
$CurrentSpaces) /* Do the beginnings match */
&&
(strlen($lines[$i -
1]) >
65) /* Over 65 characters long */
&&
strlen($CurrentRest)) { /* and there's a line to continue with */
$body .=
' ' .
$CurrentRest;
$body .=
"\n" .
$lines[$i];
$PreviousSpaces =
$CurrentSpaces;
* Truncates a string and take care of html encoded characters
* @param string $s string to truncate
* @param int $iTrimAt Trim at nn characters
* @return string Trimmed string
global $languages, $squirrelmail_language;
if (($iTrimAt <=
0) ||
($ent_strlen <=
$iTrimAt))
if (isset
($languages[$squirrelmail_language]['XTRA_CODE']) &&
return $languages[$squirrelmail_language]['XTRA_CODE']('strimwidth', $s, $iTrimAt);
* see if this is entities-encoded string
* If so, Iterate through the whole string, find out
* the real number of characters, and if more
* than $iTrimAt, substr with an updated trim value.
while ( $ent_loc <
$trim_val &&
(($ent_loc =
strpos($s, '&', $ent_offset)) !==
false) &&
(($ent_loc_end =
strpos($s, ';', $ent_loc+
3)) !==
false) ) {
$trim_val +=
($ent_loc_end-
$ent_loc);
$ent_offset =
$ent_loc_end+
1;
if (($trim_val >
$iTrimAt) &&
($ent_strlen >
$trim_val) &&
(strpos($s,';',$trim_val) <
($trim_val +
6))) {
$i =
strpos($s,';',$trim_val);
$trim_val =
strpos($s,';',$trim_val)+
1;
// only print '...' when we're actually dropping part of the subject
if ($ent_strlen <=
$trim_val)
* If $haystack is a full mailbox name and $needle is the mailbox
* separator character, returns the last part of the mailbox name.
* @param string haystack full mailbox name to search
* @param string needle the mailbox separator character
* @return string the last part of the mailbox name
$parts =
explode($needle, $haystack);
while ($elem ==
'' &&
count($parts)) {
* Creates an URL for the page calling this function, using either the PHP global
* REQUEST_URI, or the PHP global PHP_SELF with QUERY_STRING added.
* @return string the complete url for this page
// need to add query string to end of PHP_SELF to match REQUEST_URI
$php_self .=
'?' .
$query_string;
* Find out where squirrelmail lives and try to be smart about it.
* The only problem would be when squirrelmail lives in directories
* called "src", "functions", or "plugins", but people who do that need
* to be beaten with a steel pipe anyway.
* @return string the base uri of squirrelmail installation.
global $base_uri, $PHP_SELF;
* If it is in the session, just return it.
$dirs =
array('|src/.*|', '|plugins/.*|', '|functions/.*|');
$repl =
array('', '', '');
* Determines the location to forward to, relative to your server.
* This is used in HTTP Location: redirects.
* If set, it uses $config_location_base as the first part of the URL,
* specifically, the protocol, hostname and port parts. The path is
* @return string the base url for this SquirrelMail installation
/* Get the path, handle virtual directories */
// proto+host+port are already set in config:
if ( !empty($config_location_base) ) {
// register it in the session just in case some plugin depends on this
return $config_location_base .
$path ;
// we computed it before, get it from the session:
return $full_url .
$path;
/* Check if this is a HTTPS or regular HTTP request. */
* If you have 'SSLOptions +StdEnvVars' in your apache config
* OR if you have HTTPS=on in your HTTP_SERVER_VARS
* OR if you are on port 443
if ((isset
($getEnvVar) &&
strcasecmp($getEnvVar, 'on') ===
0) ||
/* Get the hostname from the Host header or server config. */
if (($server_port !=
80 &&
$proto ==
'http://') ||
($server_port !=
443 &&
$proto ==
'https://')) {
$port =
sprintf(':%d', $server_port);
/* this is a workaround for the weird macosx caching that
causes Apache to return 16080 as the port number, which causes
if ($imap_server_type ==
'macosx' &&
$port ==
':16080') {
/* Fallback is to omit the server name and use a relative */
/* URI, although this is not RFC 2616 compliant. */
$full_url =
($host ?
$proto .
$host .
$port :
'');
return $full_url .
$path;
* These functions are used to encrypt the password before it is
* stored in a cookie. The encryption key is generated by
* @param string string the (password)string to encrypt
* @param string epad the encryption key
* @return string the base64-encoded encrypted password
// make sure that pad is longer than string
// FIXME: what should we do when $epad is not base64 encoded or empty.
for ($i =
0; $i <
strlen ($string); $i++
) {
$encrypted .=
chr (ord($string[$i]) ^
ord($pad[$i]));
* Decrypts a password from the cookie
* Decrypts a password from the cookie, encrypted by OneTimePadEncrypt.
* This uses the encryption key that is stored in the session.
* @param string string the string to decrypt
* @param string epad the encryption key from the session
* @return string the decrypted password
// make sure that pad is longer than string
// FIXME: what should we do when $epad is not base64 encoded or empty.
for ($i =
0; $i <
strlen ($encrypted); $i++
) {
$decrypted .=
chr (ord($encrypted[$i]) ^
ord($pad[$i]));
* Randomizes the mt_rand() function.
* Toss this in strings or integers and it will seed the generator
* appropriately. With strings, it is better to get them long.
* Use md5() to lengthen smaller strings.
* @param mixed val a value to seed the random number generator
/* if mt_getrandmax() does not return a 2^n - 1 number,
this might not work well. This uses $Max as a bitmask. */
* Init random number generator
* This function initializes the random number generator fairly well.
* It also only initializes it once, so you don't accidentally get
* the same 'random' numbers twice in one session.
/* Avoid warnings with Win32 */
foreach ($dat as $k =>
$v)
* Creates an encryption key for encrypting the password stored in the cookie.
* The encryption key itself is stored in the session.
* @param int length optional, length of the string to generate
* @return string the encryption key
for ($i =
0; $i <
$length; $i++
) {
* Returns a string showing the size of the message/attachment.
* @param int bytes the filesize in bytes
* @return string the filesize in human readable format
return $bytes .
'<small> ' .
$type .
'</small>';
* Generates a random string from the caracter set you pass in
* @param int size the size of the string to generate
* @param string chars a string containing the characters to use
* @param int flags a flag to add a specific set to the characters to use:
* 1 = add lowercase a-z to $chars
* 2 = add uppercase A-Z to $chars
* 4 = add numbers 0-9 to $chars
* @return string the random string
$chars .=
'abcdefghijklmnopqrstuvwxyz';
$chars .=
'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if (($size <
1) ||
(strlen($chars) <
1)) {
while (strlen($String) <
$size) {
* Escapes special characters for use in IMAP commands.
* @param string the string to escape
* @return string the escaped string
* Trims every element in the array, ie. remove the first char of each element
* Obsolete: will probably removed soon
* @param array array the array to trim
foreach ($array as $k =>
$v) {
foreach ($
$k as $k2 =>
$v2) {
/* Re-assign back to array. */
* Removes slashes from every element in the array
foreach ($array as $k =>
$v) {
foreach ($
$k as $k2 =>
$v2) {
/* Re-assign back to the array. */
* Returns a link to the compose-page, taking in consideration
* the compose_in_new and javascript settings.
* @param string url the URL to the compose page
* @param string text the link text, default "Compose"
* @return string a link to the compose page
global $compose_new_win,$javascript_on;
// if not using "compose in new window", make
// regular link and be done with it
if($compose_new_win !=
'1') {
// build the compose in new window link...
// if javascript is on, use onClick event to handle it
return '<a href="javascript:void(0)" onclick="comp_in_new(\''.
$base_uri.
$url.
'\')">'.
$text.
'</a>';
// otherwise, just open new window using regular HTML
* sm_print_r($some_variable, [$some_other_variable [, ...]]);
* Debugging function - does the same as print_r, but makes sure special
* characters are converted to htmlentities first. This will allow
* The output is wrapped in <<pre>> and <</pre>> tags.
ob_end_clean(); // Silently discard the output & stop buffering
* version of fwrite which checks for failure
$count =
@fwrite($fp,$string);
// the number of bytes written should be the length of the string
if($count !=
strlen($string)) {
* Tests if string contains 8bit symbols.
* If charset is not set, function defaults to default_charset.
* $default_charset global must be set correctly if $charset is
* @param string $string tested string
* @param string $charset charset used in a string
* @return bool true if 8bit symbols are detected
if ($charset==
'') $charset=
$default_charset;
* Don't use \240 in ranges. Sometimes RH 7.2 doesn't like it.
* Don't use \200-\237 for iso-8859-x charsets. This ranges
* stores control symbols in those charsets.
* Use preg_match instead of ereg in order to avoid problems
* with mbstring overloading
$needle=
'/\240|[\241-\377]/';
$needle=
'/[\200-\237]|\240|[\241-\377]/';
* Function returns number of characters in string.
* Returned number might be different from number of bytes in string,
* if $charset is multibyte charset. Detection depends on mbstring
* functions. If mbstring does not support tested multibyte charset,
* vanilla string length function is used.
* @param string $str string
* @param string $charset charset
* @return integer number of characters in string
// lowercase charset name
// use automatic charset detection, if function call asks for it
$charset=
$default_charset;
// Use mbstring only with listed charsets
$aList_of_mb_charsets=
array('utf-8','big5','gb2312','gb18030','euc-jp','euc-cn','euc-tw','euc-kr');
// calculate string length according to charset
$real_length =
mb_strlen($str,$charset);
// own strlen detection code is removed because missing strpos,
// strtoupper and substr implementations break string wrapping.
* Replacement of mb_list_encodings function
* This function provides replacement for function that is available only
* in php 5.x. Function does not test all mbstring encodings. Only the ones
* that might be used in SM translations.
* Supported strings are stored in session in order to reduce number of
* mb_internal_encoding function calls.
* If mb_list_encodings() function is present, code uses it. Main difference
* from original function behaviour - array values are lowercased in order to
* simplify use of returned array in in_array() checks.
* If you want to test all mbstring encodings - fill $list_of_encodings
* @return array list of encodings supported by php mbstring extension
// check if mbstring extension is present
$ret =
mb_list_encodings();
// don't try to test encodings, if they are already stored in session
return $mb_supported_encodings;
// save original encoding
$orig_encoding=
mb_internal_encoding();
$supported_encodings=
array();
foreach ($list_of_encoding as $encoding) {
// try setting encodings. suppress warning messages
if (@mb_internal_encoding($encoding))
$supported_encodings[]=
$encoding;
// restore original encoding
mb_internal_encoding($orig_encoding);
// register list in session
return $supported_encodings;
* Callback function used to lowercase array values.
* @param string $val array value
* @param mixed $key array key
* Callback function to trim whitespace from a value, to be used in array_walk
* @param string $value value to trim
Documentation generated on Sat, 07 Oct 2006 16:33:53 +0300 by phpDocumentor 1.3.0RC6