Source for file strings.php

Documentation is available at strings.php

  1. <?php
  2.  
  3. /**
  4.  * strings.php
  5.  *
  6.  * This code provides various string manipulation functions that are
  7.  * used by the rest of the SquirrelMail code.
  8.  *
  9.  * @copyright &copy; 1999-2006 The SquirrelMail Project Team
  10.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  11.  * @version $Id: strings.php,v 1.184.2.58 2006/08/11 11:24:05 kink Exp $
  12.  * @package squirrelmail
  13.  */
  14.  
  15. /**
  16.  * SquirrelMail version number -- DO NOT CHANGE
  17.  */
  18. global $version;
  19. $version = '1.4.9 [CVS]';
  20.  
  21. /**
  22.  * SquirrelMail internal version number -- DO NOT CHANGE
  23.  * $sm_internal_version = array (release, major, minor)
  24.  */
  25. global $SQM_INTERNAL_VERSION;
  26. $SQM_INTERNAL_VERSION = array(1,4,9);
  27.  
  28. /**
  29.  * There can be a circular issue with includes, where the $version string is
  30.  * referenced by the include of global.php, etc. before it's defined.
  31.  * For that reason, bring in global.php AFTER we define the version strings.
  32.  */
  33. require_once(SM_PATH . 'functions/global.php');
  34.  
  35. /**
  36.  * Wraps text at $wrap characters
  37.  *
  38.  * Has a problem with special HTML characters, so call this before
  39.  * you do character translation.
  40.  *
  41.  * Specifically, &#039 comes up as 5 characters instead of 1.
  42.  * This should not add newlines to the end of lines.
  43.  */
  44. function sqWordWrap(&$line, $wrap, $charset=null) {
  45.     global $languages, $squirrelmail_language;
  46.  
  47.     if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
  48.         function_exists($languages[$squirrelmail_language]['XTRA_CODE'])) {
  49.         if (mb_detect_encoding($line) != 'ASCII') {
  50.             $line = $languages[$squirrelmail_language]['XTRA_CODE']('wordwrap', $line, $wrap);
  51.             return;
  52.         }
  53.     }
  54.  
  55.     ereg("^([\t >]*)([^\t >].*)?$", $line, $regs);
  56.     $beginning_spaces = $regs[1];
  57.     if (isset($regs[2])) {
  58.         $words = explode(' ', $regs[2]);
  59.     } else {
  60.         $words = '';
  61.     }
  62.  
  63.     $i = 0;
  64.     $line = $beginning_spaces;
  65.  
  66.     while ($i < count($words)) {
  67.         /* Force one word to be on a line (minimum) */
  68.         $line .= $words[$i];
  69.         $line_len = strlen($beginning_spaces) + sq_strlen($words[$i],$charset) + 2;
  70.         if (isset($words[$i + 1]))
  71.             $line_len += sq_strlen($words[$i + 1],$charset);
  72.         $i ++;
  73.  
  74.         /* Add more words (as long as they fit) */
  75.         while ($line_len < $wrap && $i < count($words)) {
  76.             $line .= ' ' . $words[$i];
  77.             $i++;
  78.             if (isset($words[$i]))
  79.                 $line_len += sq_strlen($words[$i],$charset) + 1;
  80.             else
  81.                 $line_len += 1;
  82.         }
  83.  
  84.         /* Skip spaces if they are the first thing on a continued line */
  85.         while (!isset($words[$i]) && $i < count($words)) {
  86.             $i ++;
  87.         }
  88.  
  89.         /* Go to the next line if we have more to process */
  90.         if ($i < count($words)) {
  91.             $line .= "\n";
  92.         }
  93.     }
  94. }
  95.  
  96. /**
  97.  * Does the opposite of sqWordWrap()
  98.  * @param string body the text to un-wordwrap
  99.  * @return void 
  100.  */
  101. function sqUnWordWrap(&$body) {
  102.     global $squirrelmail_language;
  103.  
  104.     if ($squirrelmail_language == 'ja_JP') {
  105.         return;
  106.     }
  107.  
  108.     $lines = explode("\n", $body);
  109.     $body = '';
  110.     $PreviousSpaces = '';
  111.     $cnt = count($lines);
  112.     for ($i = 0; $i < $cnt; $i ++) {
  113.         preg_match("/^([\t >]*)([^\t >].*)?$/", $lines[$i], $regs);
  114.         $CurrentSpaces = $regs[1];
  115.         if (isset($regs[2])) {
  116.             $CurrentRest = $regs[2];
  117.         } else {
  118.             $CurrentRest = '';
  119.         }
  120.  
  121.         if ($i == 0) {
  122.             $PreviousSpaces = $CurrentSpaces;
  123.             $body = $lines[$i];
  124.         } else if (($PreviousSpaces == $CurrentSpaces) /* Do the beginnings match */
  125.                    && (strlen($lines[$i - 1]) > 65)    /* Over 65 characters long */
  126.                    && strlen($CurrentRest)) {          /* and there's a line to continue with */
  127.             $body .= ' ' . $CurrentRest;
  128.         } else {
  129.             $body .= "\n" . $lines[$i];
  130.             $PreviousSpaces = $CurrentSpaces;
  131.         }
  132.     }
  133.     $body .= "\n";
  134. }
  135.  
  136. /**
  137.  * Truncates a string and take care of html encoded characters
  138.  *
  139.  * @param string  $s string to truncate
  140.  * @param int $iTrimAt Trim at nn characters
  141.  * @return string  Trimmed string
  142.  */
  143. function truncateWithEntities($s, $iTrimAt) {
  144.     global $languages, $squirrelmail_language;
  145.  
  146.     $ent_strlen = strlen($s);
  147.     if (($iTrimAt <= 0) || ($ent_strlen <= $iTrimAt))
  148.         return $s;
  149.  
  150.  
  151.     if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
  152.         function_exists($languages[$squirrelmail_language]['XTRA_CODE'])) {
  153.             return $languages[$squirrelmail_language]['XTRA_CODE']('strimwidth', $s, $iTrimAt);
  154.     } else {
  155.         /*
  156.          * see if this is entities-encoded string
  157.          * If so, Iterate through the whole string, find out
  158.          * the real number of characters, and if more
  159.          * than $iTrimAt, substr with an updated trim value.
  160.          */
  161.         $trim_val = $iTrimAt;
  162.         $ent_offset = 0;
  163.         $ent_loc = 0;
  164.         while ( $ent_loc < $trim_val && (($ent_loc = strpos($s, '&', $ent_offset)) !== false) &&
  165.                 (($ent_loc_end = strpos($s, ';', $ent_loc+3)) !== false) ) {
  166.             $trim_val += ($ent_loc_end-$ent_loc);
  167.             $ent_offset  = $ent_loc_end+1;
  168.         }
  169.  
  170.         if (($trim_val > $iTrimAt) && ($ent_strlen > $trim_val) && (strpos($s,';',$trim_val) < ($trim_val + 6))) {
  171.             $i = strpos($s,';',$trim_val);
  172.             if ($i !== false) {
  173.                 $trim_val = strpos($s,';',$trim_val)+1;
  174.             }
  175.         }
  176.         // only print '...' when we're actually dropping part of the subject
  177.         if ($ent_strlen <= $trim_val)
  178.             return $s;
  179.     }
  180.  
  181.     return substr_replace($s, '...', $trim_val);
  182. }
  183.  
  184. /**
  185.  * If $haystack is a full mailbox name and $needle is the mailbox
  186.  * separator character, returns the last part of the mailbox name.
  187.  *
  188.  * @param string haystack full mailbox name to search
  189.  * @param string needle the mailbox separator character
  190.  * @return string the last part of the mailbox name
  191.  */
  192. function readShortMailboxName($haystack, $needle) {
  193.  
  194.     if ($needle == '') {
  195.         $elem = $haystack;
  196.     } else {
  197.         $parts = explode($needle, $haystack);
  198.         $elem = array_pop($parts);
  199.         while ($elem == '' && count($parts)) {
  200.             $elem = array_pop($parts);
  201.         }
  202.     }
  203.     return( $elem );
  204. }
  205.  
  206. /**
  207.  * php_self
  208.  *
  209.  * Creates an URL for the page calling this function, using either the PHP global
  210.  * REQUEST_URI, or the PHP global PHP_SELF with QUERY_STRING added.
  211.  *
  212.  * @return string the complete url for this page
  213.  */
  214. function php_self () {
  215.     if ( sqgetGlobalVar('REQUEST_URI', $req_uri, SQ_SERVER) && !empty($req_uri) ) {
  216.       return $req_uri;
  217.     }
  218.  
  219.     if ( sqgetGlobalVar('PHP_SELF', $php_self, SQ_SERVER) && !empty($php_self) ) {
  220.  
  221.       // need to add query string to end of PHP_SELF to match REQUEST_URI
  222.       //
  223.       if ( sqgetGlobalVar('QUERY_STRING', $query_string, SQ_SERVER) && !empty($query_string) ) {
  224.          $php_self .= '?' . $query_string;
  225.       }
  226.  
  227.       return $php_self;
  228.     }
  229.  
  230.     return '';
  231. }
  232.  
  233.  
  234. /**
  235.  * Find out where squirrelmail lives and try to be smart about it.
  236.  * The only problem would be when squirrelmail lives in directories
  237.  * called "src", "functions", or "plugins", but people who do that need
  238.  * to be beaten with a steel pipe anyway.
  239.  *
  240.  * @return string the base uri of squirrelmail installation.
  241.  */
  242. function sqm_baseuri(){
  243.     global $base_uri, $PHP_SELF;
  244.     /**
  245.      * If it is in the session, just return it.
  246.      */
  247.     if (sqgetGlobalVar('base_uri',$base_uri,SQ_SESSION)){
  248.         return $base_uri;
  249.     }
  250.     $dirs = array('|src/.*|', '|plugins/.*|', '|functions/.*|');
  251.     $repl = array('', '', '');
  252.     $base_uri = preg_replace($dirs, $repl, $PHP_SELF);
  253.     return $base_uri;
  254. }
  255.  
  256. /**
  257.  * get_location
  258.  *
  259.  * Determines the location to forward to, relative to your server.
  260.  * This is used in HTTP Location: redirects.
  261.  * If set, it uses $config_location_base as the first part of the URL,
  262.  * specifically, the protocol, hostname and port parts. The path is
  263.  * always autodetected.
  264.  *
  265.  * @return string the base url for this SquirrelMail installation
  266.  */
  267. function get_location () {
  268.  
  269.  
  270.     /* Get the path, handle virtual directories */
  271.     if(strpos(php_self(), '?')) {
  272.         $path = substr(php_self(), 0, strpos(php_self(), '?'));
  273.     } else {
  274.         $path = php_self();
  275.     }
  276.     $path = substr($path, 0, strrpos($path, '/'));
  277.  
  278.     // proto+host+port are already set in config:
  279.     if ( !empty($config_location_base) ) {
  280.         // register it in the session just in case some plugin depends on this
  281.         sqsession_register($config_location_base . $path, 'sq_base_url');
  282.         return $config_location_base . $path ;
  283.     }
  284.     // we computed it before, get it from the session:
  285.     if ( sqgetGlobalVar('sq_base_url', $full_url, SQ_SESSION) ) {
  286.         return $full_url . $path;
  287.     }
  288.     // else: autodetect
  289.  
  290.     /* Check if this is a HTTPS or regular HTTP request. */
  291.     $proto = 'http://';
  292.  
  293.     /*
  294.      * If you have 'SSLOptions +StdEnvVars' in your apache config
  295.      *     OR if you have HTTPS=on in your HTTP_SERVER_VARS
  296.      *     OR if you are on port 443
  297.      */
  298.     $getEnvVar = getenv('HTTPS');
  299.     if ((isset($getEnvVar) && strcasecmp($getEnvVar, 'on') === 0) ||
  300.         (sqgetGlobalVar('HTTPS', $https_on, SQ_SERVER) && strcasecmp($https_on, 'on') === 0) ||
  301.         (sqgetGlobalVar('SERVER_PORT', $server_port, SQ_SERVER) &&  $server_port == 443)) {
  302.         $proto = 'https://';
  303.     }
  304.  
  305.     /* Get the hostname from the Host header or server config. */
  306.     if ( !sqgetGlobalVar('HTTP_X_FORWARDED_HOST', $host, SQ_SERVER) || empty($host) ) {
  307.         if ( !sqgetGlobalVar('HTTP_HOST', $host, SQ_SERVER) || empty($host) ) {
  308.             if ( !sqgetGlobalVar('SERVER_NAME', $host, SQ_SERVER) || empty($host) ) {
  309.                 $host = '';
  310.             }
  311.         }
  312.     }
  313.  
  314.     $port = '';
  315.     if (! strstr($host, ':')) {
  316.         if (sqgetGlobalVar('SERVER_PORT', $server_port, SQ_SERVER)) {
  317.             if (($server_port != 80 && $proto == 'http://') ||
  318.                 ($server_port != 443 && $proto == 'https://')) {
  319.                 $port = sprintf(':%d', $server_port);
  320.             }
  321.         }
  322.     }
  323.  
  324.    /* this is a workaround for the weird macosx caching that
  325.       causes Apache to return 16080 as the port number, which causes
  326.       SM to bail */
  327.  
  328.    if ($imap_server_type == 'macosx' && $port == ':16080') {
  329.         $port = '';
  330.    }
  331.  
  332.    /* Fallback is to omit the server name and use a relative */
  333.    /* URI, although this is not RFC 2616 compliant.          */
  334.    $full_url = ($host ? $proto . $host . $port : '');
  335.    sqsession_register($full_url, 'sq_base_url');
  336.    return $full_url . $path;
  337. }
  338.  
  339.  
  340. /**
  341.  * Encrypts password
  342.  *
  343.  * These functions are used to encrypt the password before it is
  344.  * stored in a cookie. The encryption key is generated by
  345.  * OneTimePadCreate();
  346.  *
  347.  * @param string string the (password)string to encrypt
  348.  * @param string epad the encryption key
  349.  * @return string the base64-encoded encrypted password
  350.  */
  351. function OneTimePadEncrypt ($string, $epad) {
  352.     $pad = base64_decode($epad);
  353.  
  354.     if (strlen($pad)>0) {
  355.         // make sure that pad is longer than string
  356.         while (strlen($string)>strlen($pad)) {
  357.             $pad.=$pad;
  358.         }
  359.     } else {
  360.         // FIXME: what should we do when $epad is not base64 encoded or empty.
  361.     }
  362.  
  363.     $encrypted = '';
  364.     for ($i = 0; $i < strlen ($string); $i++) {
  365.         $encrypted .= chr (ord($string[$i]) ^ ord($pad[$i]));
  366.     }
  367.  
  368.     return base64_encode($encrypted);
  369. }
  370.  
  371. /**
  372.  * Decrypts a password from the cookie
  373.  *
  374.  * Decrypts a password from the cookie, encrypted by OneTimePadEncrypt.
  375.  * This uses the encryption key that is stored in the session.
  376.  *
  377.  * @param string string the string to decrypt
  378.  * @param string epad the encryption key from the session
  379.  * @return string the decrypted password
  380.  */
  381. function OneTimePadDecrypt ($string, $epad) {
  382.     $pad = base64_decode($epad);
  383.  
  384.     if (strlen($pad)>0) {
  385.         // make sure that pad is longer than string
  386.         while (strlen($string)>strlen($pad)) {
  387.             $pad.=$pad;
  388.         }
  389.     } else {
  390.         // FIXME: what should we do when $epad is not base64 encoded or empty.
  391.     }
  392.  
  393.     $encrypted = base64_decode ($string);
  394.     $decrypted = '';
  395.     for ($i = 0; $i < strlen ($encrypted); $i++) {
  396.         $decrypted .= chr (ord($encrypted[$i]) ^ ord($pad[$i]));
  397.     }
  398.  
  399.     return $decrypted;
  400. }
  401.  
  402.  
  403. /**
  404.  * Randomizes the mt_rand() function.
  405.  *
  406.  * Toss this in strings or integers and it will seed the generator
  407.  * appropriately. With strings, it is better to get them long.
  408.  * Use md5() to lengthen smaller strings.
  409.  *
  410.  * @param mixed val a value to seed the random number generator
  411.  * @return void 
  412.  */
  413. function sq_mt_seed($Val) {
  414.     /* if mt_getrandmax() does not return a 2^n - 1 number,
  415.        this might not work well.  This uses $Max as a bitmask. */
  416.     $Max = mt_getrandmax();
  417.  
  418.     if (! is_int($Val)) {
  419.             $Val = crc32($Val);
  420.     }
  421.  
  422.     if ($Val < 0) {
  423.         $Val *= -1;
  424.     }
  425.  
  426.     if ($Val == 0) {
  427.         return;
  428.     }
  429.  
  430.     mt_srand(($Val ^ mt_rand(0, $Max)) & $Max);
  431. }
  432.  
  433.  
  434. /**
  435.  * Init random number generator
  436.  *
  437.  * This function initializes the random number generator fairly well.
  438.  * It also only initializes it once, so you don't accidentally get
  439.  * the same 'random' numbers twice in one session.
  440.  *
  441.  * @return void 
  442.  */
  443. function sq_mt_randomize() {
  444.     static $randomized;
  445.  
  446.     if ($randomized) {
  447.         return;
  448.     }
  449.  
  450.     /* Global. */
  451.     sqgetGlobalVar('REMOTE_PORT', $remote_port, SQ_SERVER);
  452.     sqgetGlobalVar('REMOTE_ADDR', $remote_addr, SQ_SERVER);
  453.     sq_mt_seed((int)((double) microtime() * 1000000));
  454.     sq_mt_seed(md5($remote_port . $remote_addr . getmypid()));
  455.  
  456.     /* getrusage */
  457.     if (function_exists('getrusage')) {
  458.         /* Avoid warnings with Win32 */
  459.         $dat = @getrusage();
  460.         if (isset($dat) && is_array($dat)) {
  461.             $Str = '';
  462.             foreach ($dat as $k => $v)
  463.                 {
  464.                     $Str .= $k . $v;
  465.                 }
  466.             sq_mt_seed(md5($Str));
  467.         }
  468.     }
  469.  
  470.     if(sqgetGlobalVar('UNIQUE_ID', $unique_id, SQ_SERVER)) {
  471.         sq_mt_seed(md5($unique_id));
  472.     }
  473.  
  474.     $randomized = 1;
  475. }
  476.  
  477. /**
  478.  * Creates encryption key
  479.  *
  480.  * Creates an encryption key for encrypting the password stored in the cookie.
  481.  * The encryption key itself is stored in the session.
  482.  *
  483.  * @param int length optional, length of the string to generate
  484.  * @return string the encryption key
  485.  */
  486. function OneTimePadCreate ($length=100) {
  487.     sq_mt_randomize();
  488.  
  489.     $pad = '';
  490.     for ($i = 0; $i < $length; $i++) {
  491.         $pad .= chr(mt_rand(0,255));
  492.     }
  493.  
  494.     return base64_encode($pad);
  495. }
  496.  
  497. /**
  498.  * Returns a string showing the size of the message/attachment.
  499.  *
  500.  * @param int bytes the filesize in bytes
  501.  * @return string the filesize in human readable format
  502.  */
  503. function show_readable_size($bytes) {
  504.     $bytes /= 1024;
  505.     $type = 'k';
  506.  
  507.     if ($bytes / 1024 > 1) {
  508.         $bytes /= 1024;
  509.         $type = 'M';
  510.     }
  511.  
  512.     if ($bytes < 10) {
  513.         $bytes *= 10;
  514.         settype($bytes, 'integer');
  515.         $bytes /= 10;
  516.     } else {
  517.         settype($bytes, 'integer');
  518.     }
  519.  
  520.     return $bytes . '<small>&nbsp;' . $type . '</small>';
  521. }
  522.  
  523. /**
  524.  * Generates a random string from the caracter set you pass in
  525.  *
  526.  * @param int size the size of the string to generate
  527.  * @param string chars a string containing the characters to use
  528.  * @param int flags a flag to add a specific set to the characters to use:
  529.  *      Flags:
  530.  *        1 = add lowercase a-z to $chars
  531.  *        2 = add uppercase A-Z to $chars
  532.  *        4 = add numbers 0-9 to $chars
  533.  * @return string the random string
  534.  */
  535. function GenerateRandomString($size, $chars, $flags = 0) {
  536.     if ($flags & 0x1) {
  537.         $chars .= 'abcdefghijklmnopqrstuvwxyz';
  538.     }
  539.     if ($flags & 0x2) {
  540.         $chars .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
  541.     }
  542.     if ($flags & 0x4) {
  543.         $chars .= '0123456789';
  544.     }
  545.  
  546.     if (($size < 1) || (strlen($chars) < 1)) {
  547.         return '';
  548.     }
  549.  
  550.     sq_mt_randomize(); /* Initialize the random number generator */
  551.  
  552.     $String = '';
  553.     $j = strlen( $chars ) - 1;
  554.     while (strlen($String) < $size) {
  555.         $String .= $chars{mt_rand(0, $j)};
  556.     }
  557.  
  558.     return $String;
  559. }
  560.  
  561. /**
  562.  * Escapes special characters for use in IMAP commands.
  563.  *
  564.  * @param string the string to escape
  565.  * @return string the escaped string
  566.  */
  567. function quoteimap($str) {
  568.     return preg_replace("/([\"\\\\])/", "\\\\$1", $str);
  569. }
  570.  
  571. /**
  572.  * Trims array
  573.  *
  574.  * Trims every element in the array, ie. remove the first char of each element
  575.  * Obsolete: will probably removed soon
  576.  * @param array array the array to trim
  577.  * @obsolete
  578.  */
  579. function TrimArray(&$array) {
  580.     foreach ($array as $k => $v) {
  581.         global $$k;
  582.         if (is_array($$k)) {
  583.             foreach ($$k as $k2 => $v2) {
  584.                 $$k[$k2] = substr($v2, 1);
  585.             }
  586.         } else {
  587.             $$k = substr($v, 1);
  588.         }
  589.  
  590.         /* Re-assign back to array. */
  591.         $array[$k] = $$k;
  592.     }
  593. }
  594.  
  595. /**
  596.  * Removes slashes from every element in the array
  597.  */
  598. function RemoveSlashes(&$array) {
  599.     foreach ($array as $k => $v) {
  600.         global $$k;
  601.         if (is_array($$k)) {
  602.             foreach ($$k as $k2 => $v2) {
  603.                 $newArray[stripslashes($k2)] = stripslashes($v2);
  604.             }
  605.             $$k = $newArray;
  606.         } else {
  607.             $$k = stripslashes($v);
  608.         }
  609.  
  610.         /* Re-assign back to the array. */
  611.         $array[$k] = $$k;
  612.     }
  613. }
  614.  
  615. /**
  616.  * Create compose link
  617.  *
  618.  * Returns a link to the compose-page, taking in consideration
  619.  * the compose_in_new and javascript settings.
  620.  * @param string url the URL to the compose page
  621.  * @param string text the link text, default "Compose"
  622.  * @return string a link to the compose page
  623.  */
  624. function makeComposeLink($url, $text = null, $target='')
  625. {
  626.     global $compose_new_win,$javascript_on;
  627.  
  628.     if(!$text) {
  629.         $text = _("Compose");
  630.     }
  631.  
  632.  
  633.     // if not using "compose in new window", make
  634.     // regular link and be done with it
  635.     if($compose_new_win != '1') {
  636.         return makeInternalLink($url, $text, $target);
  637.     }
  638.  
  639.  
  640.     // build the compose in new window link...
  641.  
  642.  
  643.     // if javascript is on, use onClick event to handle it
  644.     if($javascript_on) {
  645.         sqgetGlobalVar('base_uri', $base_uri, SQ_SESSION);
  646.         return '<a href="javascript:void(0)" onclick="comp_in_new(\''.$base_uri.$url.'\')">'. $text.'</a>';
  647.     }
  648.  
  649.  
  650.     // otherwise, just open new window using regular HTML
  651.     return makeInternalLink($url, $text, '_blank');
  652.  
  653. }
  654.  
  655. /**
  656.  * Print variable
  657.  *
  658.  * sm_print_r($some_variable, [$some_other_variable [, ...]]);
  659.  *
  660.  * Debugging function - does the same as print_r, but makes sure special
  661.  * characters are converted to htmlentities first.  This will allow
  662.  * values like <[email protected]> to be displayed.
  663.  * The output is wrapped in <<pre>> and <</pre>> tags.
  664.  *
  665.  * @return void 
  666.  */
  667. function sm_print_r() {
  668.     ob_start();  // Buffer output
  669.     foreach(func_get_args() as $var) {
  670.         print_r($var);
  671.         echo "\n";
  672.     }
  673.     $buffer = ob_get_contents(); // Grab the print_r output
  674.     ob_end_clean();  // Silently discard the output & stop buffering
  675.     print '<pre>';
  676.     print htmlentities($buffer);
  677.     print '</pre>';
  678. }
  679.  
  680. /**
  681.  * version of fwrite which checks for failure
  682.  */
  683. function sq_fwrite($fp, $string) {
  684.         // write to file
  685.         $count = @fwrite($fp,$string);
  686.         // the number of bytes written should be the length of the string
  687.         if($count != strlen($string)) {
  688.                 return FALSE;
  689.         }
  690.  
  691.         return $count;
  692. }
  693. /**
  694.  * Tests if string contains 8bit symbols.
  695.  *
  696.  * If charset is not set, function defaults to default_charset.
  697.  * $default_charset global must be set correctly if $charset is
  698.  * not used.
  699.  * @param string $string tested string
  700.  * @param string $charset charset used in a string
  701.  * @return bool true if 8bit symbols are detected
  702.  * @since 1.5.1 and 1.4.4
  703.  */
  704. function sq_is8bit($string,$charset='') {
  705.     global $default_charset;
  706.  
  707.     if ($charset=='') $charset=$default_charset;
  708.  
  709.     /**
  710.      * Don't use \240 in ranges. Sometimes RH 7.2 doesn't like it.
  711.      * Don't use \200-\237 for iso-8859-x charsets. This ranges
  712.      * stores control symbols in those charsets.
  713.      * Use preg_match instead of ereg in order to avoid problems
  714.      * with mbstring overloading
  715.      */
  716.     if (preg_match("/^iso-8859/i",$charset)) {
  717.         $needle='/\240|[\241-\377]/';
  718.     } else {
  719.         $needle='/[\200-\237]|\240|[\241-\377]/';
  720.     }
  721.     return preg_match("$needle",$string);
  722. }
  723.  
  724. /**
  725.  * Function returns number of characters in string.
  726.  *
  727.  * Returned number might be different from number of bytes in string,
  728.  * if $charset is multibyte charset. Detection depends on mbstring
  729.  * functions. If mbstring does not support tested multibyte charset,
  730.  * vanilla string length function is used.
  731.  * @param string $str string
  732.  * @param string $charset charset
  733.  * @since 1.5.1 and 1.4.6
  734.  * @return integer number of characters in string
  735.  */
  736. function sq_strlen($str, $charset=null){
  737.     // default option
  738.     if (is_null($charset)) return strlen($str);
  739.  
  740.     // lowercase charset name
  741.     $charset=strtolower($charset);
  742.  
  743.     // use automatic charset detection, if function call asks for it
  744.     if ($charset=='auto') {
  745.         global $default_charset;
  746.         set_my_charset();
  747.         $charset=$default_charset;
  748.     }
  749.  
  750.     // Use mbstring only with listed charsets
  751.     $aList_of_mb_charsets=array('utf-8','big5','gb2312','gb18030','euc-jp','euc-cn','euc-tw','euc-kr');
  752.  
  753.     // calculate string length according to charset
  754.     if (in_array($charset,$aList_of_mb_charsets) && in_array($charset,sq_mb_list_encodings())) {
  755.         $real_length = mb_strlen($str,$charset);
  756.     } else {
  757.         // own strlen detection code is removed because missing strpos,
  758.         // strtoupper and substr implementations break string wrapping.
  759.         $real_length=strlen($str);
  760.     }
  761.     return $real_length;
  762. }
  763.  
  764. /**
  765.  * Replacement of mb_list_encodings function
  766.  *
  767.  * This function provides replacement for function that is available only
  768.  * in php 5.x. Function does not test all mbstring encodings. Only the ones
  769.  * that might be used in SM translations.
  770.  *
  771.  * Supported strings are stored in session in order to reduce number of
  772.  * mb_internal_encoding function calls.
  773.  *
  774.  * If mb_list_encodings() function is present, code uses it. Main difference
  775.  * from original function behaviour - array values are lowercased in order to
  776.  * simplify use of returned array in in_array() checks.
  777.  *
  778.  * If you want to test all mbstring encodings - fill $list_of_encodings
  779.  * array.
  780.  * @return array list of encodings supported by php mbstring extension
  781.  * @since 1.5.1 and 1.4.6
  782.  */
  783. function sq_mb_list_encodings() {
  784.     // check if mbstring extension is present
  785.     if (! function_exists('mb_internal_encoding'))
  786.         return array();
  787.  
  788.     // php 5+ function
  789.     if (function_exists('mb_list_encodings')) {
  790.         $ret = mb_list_encodings();
  791.         array_walk($ret,'sq_lowercase_array_vals');
  792.         return $ret;
  793.     }
  794.  
  795.     // don't try to test encodings, if they are already stored in session
  796.     if (sqgetGlobalVar('mb_supported_encodings',$mb_supported_encodings,SQ_SESSION))
  797.         return $mb_supported_encodings;
  798.  
  799.     // save original encoding
  800.     $orig_encoding=mb_internal_encoding();
  801.  
  802.     $list_of_encoding=array(
  803.         'pass',
  804.         'auto',
  805.         'ascii',
  806.         'jis',
  807.         'utf-8',
  808.         'sjis',
  809.         'euc-jp',
  810.         'iso-8859-1',
  811.         'iso-8859-2',
  812.         'iso-8859-7',
  813.         'iso-8859-9',
  814.         'iso-8859-15',
  815.         'koi8-r',
  816.         'koi8-u',
  817.         'big5',
  818.         'gb2312',
  819.         'gb18030',
  820.         'windows-1251',
  821.         'windows-1255',
  822.         'windows-1256',
  823.         'tis-620',
  824.         'iso-2022-jp',
  825.         'euc-cn',
  826.         'euc-kr',
  827.         'euc-tw',
  828.         'uhc',
  829.         'utf7-imap');
  830.  
  831.     $supported_encodings=array();
  832.  
  833.     foreach ($list_of_encoding as $encoding) {
  834.         // try setting encodings. suppress warning messages
  835.         if (@mb_internal_encoding($encoding))
  836.             $supported_encodings[]=$encoding;
  837.     }
  838.  
  839.     // restore original encoding
  840.     mb_internal_encoding($orig_encoding);
  841.  
  842.     // register list in session
  843.     sqsession_register($supported_encodings,'mb_supported_encodings');
  844.  
  845.     return $supported_encodings;
  846. }
  847.  
  848. /**
  849.  * Callback function used to lowercase array values.
  850.  * @param string $val array value
  851.  * @param mixed $key array key
  852.  * @since 1.5.1 and 1.4.6
  853.  */
  854. function sq_lowercase_array_vals(&$val,$key) {
  855.     $val = strtolower($val);
  856. }
  857.  
  858. /**
  859.  * Callback function to trim whitespace from a value, to be used in array_walk
  860.  * @param string $value value to trim
  861.  * @since 1.5.2 and 1.4.7
  862.  */
  863. function sq_trim_value ( &$value ) {
  864.     $value = trim($value);
  865. }
  866.  
  867.  
  868. $PHP_SELF = php_self();
  869. ?>

Documentation generated on Sat, 07 Oct 2006 16:33:53 +0300 by phpDocumentor 1.3.0RC6