X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=functions%2Fstrings.php;h=27dfa8a1f96cecbe28cfc061369296c20ab1bf5a;hb=c9d61baf815700ed32427bf46fed3a5cc093216a;hp=e295c4c910581e81d4f37e7384ebfed934bccb33;hpb=3ecad5e6d4b425f935cbb53d460cd627a9db2f17;p=squirrelmail.git diff --git a/functions/strings.php b/functions/strings.php index e295c4c9..27dfa8a1 100644 --- a/functions/strings.php +++ b/functions/strings.php @@ -9,7 +9,7 @@ * This code provides various string manipulation functions that are * used by the rest of the Squirrelmail code. * - * $Id$ + * @version $Id$ * @package squirrelmail */ @@ -33,6 +33,237 @@ $SQM_INTERNAL_VERSION = array(1,5,1); */ require_once(SM_PATH . 'functions/global.php'); +/** + * Appends citation markers to the string. + * Also appends a trailing space. + * + * @author Justus Pendleton + * + * @param string str The string to append to + * @param int citeLevel the number of markers to append + * @return null + */ +function sqMakeCite (&$str, $citeLevel) { + for ($i = 0; $i < $citeLevel; $i++) { + $str .= '>'; + } + if ($citeLevel != 0) { + $str .= ' '; + } +} + +/** + * Create a newline in the string, adding citation + * markers to the newline as necessary. + * + * @author Justus Pendleton + * + * @param string str the string to make a newline in + * @param int citeLevel the citation level the newline is at + * @param int column starting column of the newline + * @return null + */ +function sqMakeNewLine (&$str, $citeLevel, &$column) { + $str .= "\n"; + $column = 0; + if ($citeLevel > 0) { + sqMakeCite ($str, $citeLevel); + $column = $citeLevel + 1; + } else { + $column = 0; + } +} + +/** + * Wraps text at $wrap characters. While sqWordWrap takes + * a single line of text and wraps it, this function works + * on the entire corpus at once, this allows it to be a little + * bit smarter and when and how to wrap. + * + * @author Justus Pendleton + * + * @param string body the entire body of text + * @param int wrap the maximum line length + * @return string the wrapped text + */ +function &sqBodyWrap (&$body, $wrap) { + // the newly wrapped text + $outString = ''; + // current column since the last newline in the outstring + $outStringCol = 0; + $length = strlen($body); + // where we are in the original string + $pos = 0; + // the number of >>> citation markers we are currently at + $citeLevel = 0; + + // the main loop, whenever we start a newline of input text + // we start from here + while ($pos < $length) { + // we're at the beginning of a line, get the new cite level + $newCiteLevel = 0; + + while (($pos < $length) && ($body{$pos} == '>')) { + $newCiteLevel++; + $pos++; + + // skip over any spaces interleaved among the cite markers + while (($pos < $length) && ($body{$pos} == ' ')) { + $pos++; + } + if ($pos >= $length) { + break; + } + } + + // special case: if this is a blank line then maintain it + // (i.e. try to preserve original paragraph breaks) + // unless they occur at the very beginning of the text + if (($body{$pos} == "\n") && (strlen($outString) != 0)) { + $outStringLast = $outString{strlen($outString) - 1}; + if ($outStringLast != "\n") { + $outString .= "\n"; + } + sqMakeCite ($outString, $newCiteLevel); + $outString .= "\n"; + $pos++; + $outStringCol = 0; + continue; + } + + // if the cite level has changed, then start a new line + // with the new cite level. + if (($citeLevel != $newCiteLevel) && ($pos > ($newCiteLevel + 1)) && ($outStringCol != 0)) { + sqMakeNewLine ($outString, 0, $outStringCol); + } + + $citeLevel = $newCiteLevel; + + // prepend the quote level if necessary + if ($outStringCol == 0) { + sqMakeCite ($outString, $citeLevel); + // if we added a citation then move the column + // out by citelevel + 1 (the cite markers + the space) + $outStringCol = $citeLevel + ($citeLevel ? 1 : 0); + } else if ($outStringCol > $citeLevel) { + // not a cite and we're not at the beginning of a line + // in the output. add a space to separate the new text + // from previous text. + $outString .= ' '; + $outStringCol++; + } + + // find the next newline -- we don't want to go further than that + $nextNewline = strpos ($body, "\n", $pos); + if ($nextNewline === FALSE) { + $nextNewline = $length; + } + + // Don't wrap unquoted lines at all. For now the textarea + // will work fine for this. Maybe revisit this later though + // (for completeness more than anything else, I think) + if ($citeLevel == 0) { + $outString .= substr ($body, $pos, ($nextNewline - $pos)); + $outStringCol = $nextNewline - $pos; + if ($nextNewline != $length) { + sqMakeNewLine ($outString, 0, $outStringCol); + } + $pos = $nextNewline + 1; + continue; + } + + // inner loop, (obviously) handles wrapping up to + // the next newline + while ($pos < $nextNewline) { + // skip over initial spaces + while (($pos < $nextNewline) && (ctype_space ($body{$pos}))) { + $pos++; + } + + // if this is a short line then just append it and continue outer loop + if (($outStringCol + $nextNewline - $pos) <= ($wrap - $citeLevel - 1)) { + // if this is the final line in the input string then include + // any trailing newlines + if (($nextNewline + 1 == $length) && ($body{$nextNewline} == "\n")) { + $nextNewline++; + } + + // trim trailing spaces + $lastRealChar = $nextNewline; + while (($lastRealChar > $pos) && (ctype_space ($body{$lastRealChar}))) { + $lastRealChar--; + } + + $outString .= substr ($body, $pos, ($lastRealChar - $pos + 1)); + $outStringCol += ($lastRealChar - $pos); + $pos = $nextNewline + 1; + continue; + } + + $eol = $pos + $wrap - $citeLevel - $outStringCol; + // eol is the tentative end of line. + // look backwards for there for a whitespace to break at. + // if it's already less than our current position then + // our current line is already too long, break immediately + // and restart outer loop + if ($eol <= $pos) { + sqMakeNewLine ($outString, $citeLeve, $outStringCol); + continue; + } + + // start looking backwards for whitespace to break at. + $breakPoint = $eol; + while (($breakPoint > $pos) && (! ctype_space ($body{$breakPoint}))) { + $breakPoint--; + } + + // if we didn't find a breakpoint by looking backward then we + // need to figure out what to do about that + if ($breakPoint == $pos) { + // if we are not at the beginning then end this line + // and start a new loop + if ($outStringCol > ($citeLevel + 1)) { + sqMakeNewLine ($outString, $citeLevel, $outStringCol); + continue; + } else { + // just hard break here. most likely we are breaking + // a really long URL. could also try searching + // forward for a break point, which is what Mozilla + // does. don't bother for now. + $breakPoint = $eol; + } + } + + // special case: maybe we should have wrapped last + // time. if the first breakpoint here makes the + // current line too long and there is already text on + // the current line, break and loop again if at + // beginning of current line, don't force break + $SLOP = 6; + if ((($outStringCol + ($breakPoint - $pos)) > ($wrap + $SLOP)) && ($outStringCol > ($citeLevel + 1))) { + sqMakeNewLine ($outString, $citeLevel, $outStringCol); + continue; + } + + // skip newlines or whitespace at the beginning of the string + $substring = substr ($body, $pos, ($breakPoint - $pos)); + $substring = rtrim ($substring); // do rtrim and ctype_space have the same ideas about whitespace? + $outString .= $substring; + $outStringCol += strlen ($substring); + // advance past the whitespace which caused the wrap + $pos = $breakPoint; + while (($pos < $length) && (ctype_space ($body{$pos}))) { + $pos++; + } + if ($pos < $length) { + sqMakeNewLine ($outString, $citeLevel, $outStringCol); + } + } + } + + return $outString; +} + /** * Wraps text at $wrap characters * @@ -161,6 +392,8 @@ function readShortMailboxName($haystack, $needle) { } /** + * php_self + * * 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. * @@ -187,6 +420,8 @@ function php_self () { /** + * get_location + * * Determines the location to forward to, relative to your server. * This is used in HTTP Location: redirects. * If this doesnt work correctly for you (although it should), you can @@ -261,6 +496,8 @@ function get_location () { /** + * Encrypts password + * * These functions are used to encrypt the password before it is * stored in a cookie. The encryption key is generated by * OneTimePadCreate(); @@ -280,7 +517,9 @@ function OneTimePadEncrypt ($string, $epad) { } /** - * Decrypt a password from the cookie, encrypted by OneTimePadEncrypt. + * 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 @@ -300,9 +539,11 @@ function OneTimePadDecrypt ($string, $epad) { /** - * Randomize 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. + * 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 * @return void @@ -329,6 +570,8 @@ function sq_mt_seed($Val) { /** + * 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. @@ -370,6 +613,8 @@ function sq_mt_randomize() { } /** + * Creates encryption key + * * Creates an encryption key for encrypting the password stored in the cookie. * The encryption key itself is stored in the session. * @@ -425,7 +670,6 @@ function show_readable_size($bytes) { * 4 = add numbers 0-9 to $chars * @return string the random string */ - function GenerateRandomString($size, $chars, $flags = 0) { if ($flags & 0x1) { $chars .= 'abcdefghijklmnopqrstuvwxyz'; @@ -454,14 +698,17 @@ function GenerateRandomString($size, $chars, $flags = 0) { /** * Escapes special characters for use in IMAP commands. + * * @param string the string to escape * @return string the escaped string */ function quoteimap($str) { - return ereg_replace('(["\\])', '\\\\1', $str); + return preg_replace("/([\"\\\\])/", "\\\\$1", $str); } /** + * Trims array + * * Trims every element in the array, ie. remove the first char of each element * @param array array the array to trim */ @@ -482,6 +729,8 @@ function TrimArray(&$array) { } /** + * Create compose link + * * 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 @@ -497,14 +746,14 @@ function makeComposeLink($url, $text = null, $target='') } - // if not using "compose in new window", make + // if not using "compose in new window", make // regular link and be done with it if($compose_new_win != '1') { return makeInternalLink($url, $text, $target); } - // build the compose in new window link... + // build the compose in new window link... // if javascript is on, use onClick event to handle it @@ -520,11 +769,14 @@ function makeComposeLink($url, $text = null, $target='') } /** + * Print variable + * * 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 * values like to be displayed. - * The output is wrapped in
 and 
tags. + * The output is wrapped in <
> and <
> tags. * * @return void */ @@ -545,17 +797,101 @@ function sm_print_r() { * version of fwrite which checks for failure */ function sq_fwrite($fp, $string) { - // write to file - $count = @fwrite($fp,$string); - // the number of bytes written should be the length of the string - if($count != strlen($string)) { - return FALSE; - } - - return $count; + // write to file + $count = @fwrite($fp,$string); + // the number of bytes written should be the length of the string + if($count != strlen($string)) { + return FALSE; + } + + return $count; } +/** + * sq_get_html_translation_table + * + * Returns the translation table used by sq_htmlentities() + * + * @param integer $table html translation table. Possible values (without quotes): + * + * @param integer $quote_style quote encoding style. Possible values (without quotes): + * + * @param string $charset charset used for encoding. default to us-ascii, 'auto' uses $default_charset global value. + * @return array html translation array + */ +function sq_get_html_translation_table($table,$quote_style=ENT_COMPAT,$charset='us-ascii') { + global $default_charset; + + if ($table == HTML_SPECIALCHARS) $charset='us-ascii'; + + // Start array with ampersand + $sq_html_ent_table = array( "&" => '&' ); + + // < and > + $sq_html_ent_table = array_merge($sq_html_ent_table, + array("<" => '<', + ">" => '>') + ); + // double quotes + if ($quote_style == ENT_COMPAT) + $sq_html_ent_table = array_merge($sq_html_ent_table, + array("\"" => '"') + ); + + // double and single quotes + if ($quote_style == ENT_QUOTES) + $sq_html_ent_table = array_merge($sq_html_ent_table, + array("\"" => '"', + "'" => ''') + ); + + if ($charset=='auto') $charset=$default_charset; + + // add entities that depend on charset + switch($charset){ + case 'iso-8859-1': + include_once(SM_PATH . 'functions/htmlentities/iso-8859-1.php'); + break; + case 'utf-8': + include_once(SM_PATH . 'functions/htmlentities/utf-8.php'); + break; + case 'us-ascii': + default: + break; + } + // return table + return $sq_html_ent_table; +} +/** + * sq_htmlentities + * + * Convert all applicable characters to HTML entities. + * Minimal php requirement - v.4.0.5 + * + * @param string $string string that has to be sanitized + * @param integer $quote_style quote encoding style. Possible values (without quotes): + * + * @param string $charset charset used for encoding. defaults to 'us-ascii', 'auto' uses $default_charset global value. + * @return string sanitized string + */ +function sq_htmlentities($string,$quote_style=ENT_COMPAT,$charset='us-ascii') { + // get translation table + $sq_html_ent_table=sq_get_html_translation_table(HTML_ENTITIES,$quote_style,$charset); + // convert characters + return str_replace(array_keys($sq_html_ent_table),array_values($sq_html_ent_table),$string); +} $PHP_SELF = php_self(); -?> +?> \ No newline at end of file