b2evolution

Multilingual multiuser multiblog engine

b2evolution Technical Documentation (0.9.x) [ class tree: evocore ] [ index: evocore ] [ all elements ]

Source for file _functions.php

Documentation is available at _functions.php

  1. <?php
  2. /**
  3.  * General purpose functions
  4.  *
  5.  * b2evolution - {@link http://b2evolution.net/}
  6.  * Released under GNU GPL License - {@link http://b2evolution.net/about/license.html}
  7.  * @copyright (c)2003-2005 by Francois PLANQUE - {@link http://fplanque.net/}
  8.  *
  9.  * @package evocore
  10.  * @author This file built upon code from original b2 - http://cafelog.com/
  11.  * @author vegarg
  12.  */
  13. if!defined('DB_USER') ) die'Please, do not access this page directly.' );
  14.  
  15. /**
  16.  * Includes:
  17.  */
  18. require_oncedirname(__FILE__)'/_functions_cats.php' );
  19. require_oncedirname(__FILE__)'/_functions_blogs.php' );
  20. require_oncedirname(__FILE__)'/_functions_bposts.php' );
  21. require_oncedirname(__FILE__)'/_functions_users.php' );
  22. require_oncedirname(__FILE__)'/_functions_trackback.php' );
  23. require_oncedirname(__FILE__)'/_functions_pingback.php' );
  24. require_oncedirname(__FILE__)'/_functions_pings.php' );
  25. require_oncedirname(__FILE__)'/_functions_skins.php' );
  26. require_oncedirname(__FILE__)'/_functions_errors.php' );
  27. require_oncedirname(__FILE__)'/_functions_antispam.php' );
  28. if!isset$use_html_checker ) ) $use_html_checker 1;
  29. if$use_html_checker require_oncedirname(__FILE__)'/_class_htmlchecker.php' );
  30.  
  31.  
  32. /* functions... */
  33.  
  34.  
  35.  
  36. /**
  37.  * Report MySQL errors in detail.
  38.  *
  39.  * {@internal mysql_oops(-) }}
  40.  *
  41.  * @deprecated use class DB instead
  42.  *
  43.  * @param string The query which led to the error
  44.  * @return boolean success?
  45.  */
  46. function mysql_oops$sql_query )
  47. {
  48.     $error  '<p class="error">'T_('Oops, MySQL error!')'</p>'
  49.         . '<p>Your query:<br /><code>'$sql_query'</code></p>'
  50.         . '<p>MySQL said:<br /><code>'mysql_error()' (error 'mysql_errno()')</code></p>';
  51.     die$error );
  52. }
  53.  
  54.  
  55. /***** Formatting functions *****/
  56.  
  57.  
  58. /**
  59.  * Format a string/content for being output
  60.  *
  61.  * {@internal format_to_output(-) }}
  62.  *
  63.  * @author fplanque
  64.  * @param string raw text
  65.  * @param string format, can be one of the following
  66.  *  - raw: do nothing
  67.  *  - htmlbody: display in HTML page body: allow full HTML
  68.  *  - entityencoded: Special mode for RSS 0.92: allow full HTML but escape it
  69.  *  - htmlhead: strips out HTML (mainly for use in Title)
  70.  *  - htmlattr: use as an attribute: strips tags and escapes quotes
  71.  *  - formvalue: use as a form value: escapes quotes and < > but leaves code alone
  72.  *  - xml: use in an XML file: strip HTML tags
  73.  *  - xmlattr: use as an attribute: strips tags and escapes quotes
  74.  * @return string formatted text
  75.  */
  76. function format_to_output$content$format 'htmlbody' )
  77. {
  78.     global $Renderer;
  79.  
  80.     switch$format )
  81.     {
  82.         case 'raw':
  83.             // do nothing!
  84.             break;
  85.  
  86.         case 'htmlbody':
  87.             // display in HTML page body: allow full HTML
  88.             $content convert_chars($content'html');
  89.             break;
  90.  
  91.         case 'entityencoded':
  92.             // Special mode for RSS 0.92: apply renders and allow full HTML but escape it
  93.             $content convert_chars($content'html');
  94.             $content htmlspecialchars$content );
  95.             break;
  96.  
  97.         case 'htmlhead':
  98.             // strips out HTML (mainly for use in Title)
  99.             $content strip_tags($content);
  100.             $content convert_chars($content'html');
  101.             break;
  102.  
  103.         case 'htmlattr':
  104.             // use as an attribute: strips tags and escapes quotes
  105.             $content strip_tags($content);
  106.             $content convert_chars($content'html');
  107.             $content str_replace('"''&quot;'$content );
  108.             $content str_replace("'"'&#039;'$content );
  109.             break;
  110.  
  111.         case 'formvalue':
  112.             // use as a form value: escapes quotes and < > but leaves code alone
  113.             $content htmlspecialchars$content );
  114.             $content str_replace('"''&quot;'$content );
  115.             $content str_replace("'"'&#039;'$content );
  116.             $content str_replace('<''&lt;'$content );
  117.             $content str_replace(">"'&gt;'$content );
  118.             break;
  119.  
  120.         case 'xml':
  121.             // use in an XML file: strip HTML tags
  122.             $content strip_tags($content);
  123.             $content convert_chars($content'xml');
  124.             break;
  125.  
  126.         case 'xmlattr':
  127.             // use as an attribute: strips tags and escapes quotes
  128.             $content strip_tags($content);
  129.             $content convert_chars($content'xml');
  130.             $content str_replace('"''&quot;'$content );
  131.             $content str_replace("'"'&#039;'$content );
  132.             break;
  133.  
  134.         default:
  135.             die'Output format ['.$format.'] not supported.' );
  136.     }
  137.  
  138.     return $content;
  139. }
  140.  
  141.  
  142. /*
  143.  * format_to_edit(-)
  144.  */
  145. function format_to_edit$content$autobr false )
  146. {
  147.     if$autobr )
  148.     {
  149.         // echo 'unBR:',htmlspecialchars(str_replace( ' ', '*', $content) );
  150.         $content unautobrize($content);
  151.     }
  152.  
  153.     $content htmlspecialchars($content);
  154.     return($content);
  155. }
  156.  
  157.  
  158. /*
  159.  * format_to_post(-)
  160.  */
  161. function format_to_post$content$autobr 0$is_comment 0$encoding '' )
  162. {
  163.     global $use_balanceTags$use_html_checker$use_security_checker;
  164.     global $allowed_tags$allowed_attribues$uri_attrs$allowed_uri_scheme;
  165.     global $comments_allowed_tags$comments_allowed_attribues$comments_allowed_uri_scheme;
  166.  
  167.     // Replace any & that is not a character or entity reference with &amp;
  168.     $contentpreg_replace'/&(?!#[0-9]+;|#x[0-9a-fA-F]+;|[a-zA-Z_:][a-zA-Z0-9._:-]*;)/''&amp;'$content );
  169.  
  170.     if$autobr )
  171.     // Auto <br />:
  172.         // may put brs in the middle of multiline tags...
  173.         $content autobrize($content);
  174.     }
  175.  
  176.     if$use_balanceTags )
  177.     {    // Auto close open tags:
  178.         $content balanceTags($content$is_comment);
  179.     }
  180.  
  181.     if$use_html_checker )
  182.     {    // Check the code:
  183.         if$is_comment )
  184.         {
  185.             $checker new SafeHtmlChecker$allowed_tags$allowed_attribues,
  186.                                                                             $uri_attrs$allowed_uri_scheme$encoding );
  187.         }
  188.         else
  189.         {
  190.             $checker new SafeHtmlChecker$comments_allowed_tags$comments_allowed_attribues,
  191.                                                                             $uri_attrs$comments_allowed_uri_scheme$encoding );
  192.         }
  193.  
  194.         $checker->check$content );
  195.     }
  196.  
  197.     if!isset$use_security_checker ) ) $use_security_checker 1;
  198.     if$use_security_checker )
  199.     {
  200.         // Security checking:
  201.         $check $content;
  202.         // Open comments or '<![CDATA[' are dangerous
  203.         $check str_replace('<!''<'$check);
  204.         // # # are delimiters
  205.         // i modifier at the end means caseless
  206.         $matches array();
  207.         // onclick= etc...
  208.         ifpreg_match ('#\s(on[a-z]+)\s*=#i'$check$matches)
  209.             // action=, background=, cite=, classid=, codebase=, data=, href=, longdesc=, profile=, src=
  210.             // usemap=
  211.             || preg_match ('#=["\'\s]*(javascript|vbscript|about):#i'$check$matches)
  212.             || preg_match ('#\<\/?\s*(frame|iframe|applet|object)#i'$check$matches) )
  213.         {
  214.             errors_add'Illegal markup found: '.htmlspecialchars($matches[1]) );
  215.         }
  216.         // Styling restictions:
  217.         $matches array();
  218.         if$is_comment && preg_match ('#\s(style|class|id)\s*=#i'$check$matches) )
  219.         {
  220.             errors_add'Unallowed CSS markup found: '.htmlspecialchars($matches[1]) );
  221.         }
  222.     }
  223.     return($content);
  224. }
  225.  
  226.  
  227. /*
  228.  * autobrize(-)
  229.  */
  230. function autobrize($content{
  231.     $content preg_replace("/<br>\n/""\n"$content);
  232.     $content preg_replace("/<br \/>\n/""\n"$content);
  233.     $content preg_replace("/(\015\012)|(\015)|(\012)/""<br />\n"$content);
  234.     return($content);
  235.     }
  236.  
  237. /*
  238.  * unautobrize(-)
  239.  */
  240. function unautobrize($content)
  241. {
  242.     $content preg_replace("/<br>\n/""\n"$content);   //for PHP versions before 4.0.5
  243.     $content preg_replace("/<br \/>\n/""\n"$content);
  244.     return($content);
  245. }
  246.  
  247. /*
  248.  * zeroise(-)
  249.  */
  250. function zeroise($number$threshold)
  251. // function to add leading zeros when necessary
  252.     $l strlen($number);
  253.     if ($l $threshold)
  254.         for ($i 0$i ($threshold $l)$i $i 1$number='0'.$number;    }
  255.     return($number);
  256. }
  257.  
  258.  
  259.  
  260. /*
  261.  * Convert all non ASCII chars (except if UTF-8) to &#nnnn; unicode references.
  262.  * Also convert entities to &#nnnn; unicode references if output is not HTML (eg XML)
  263.  *
  264.  * Preserves < > and quotes.
  265.  *
  266.  * {@internal convert_chars(-)}}
  267.  *
  268.  * fplanque: simplified
  269.  * sakichan: pregs instead of loop
  270.  */
  271. function convert_chars$content$flag='html' )
  272. {
  273.     global $b2_htmltrans$b2_htmltranswinuni;
  274.  
  275.     // Convert highbyte non ASCII/UTF-8 chars to urefs:
  276.     if( (locale_charset(false!= 'utf-8'&& (locale_charset(false!= 'gb2312') )
  277.     {    // This is a single byte charset
  278.         $content preg_replace_callback(
  279.             '/[\x80-\xff]/',
  280.             create_function'$j''return "&#".ord($j[0]).";";' ),
  281.             $content);
  282.     }
  283.  
  284.     // Convert Windows CP1252 => Unicode (valid HTML)
  285.     // TODO: should this go to input conversions instead (?)
  286.     $content strtr$content$b2_htmltranswinuni );
  287.  
  288.     if$flag == 'html' )
  289.     // we can use entities
  290.         // Convert & chars that are not used in an entity
  291.         $content preg_replace('/&(?![#A-Za-z0-9]{2,20};)/''&amp;'$content);
  292.     }
  293.     else
  294.     {    // unicode, xml...
  295.         // Convert & chars that are not used in an entity
  296.         $content preg_replace('/&(?![#A-Za-z0-9]{2,20};)/''&#38;'$content);
  297.  
  298.         // Convert HTML entities to urefs:
  299.         $content strtr($content$b2_htmltrans);
  300.     }
  301.  
  302.     return$content );
  303. }
  304.  
  305.  
  306. /**
  307.  * Make links clickable in a given text.
  308.  *
  309.  * {@internal NOTE: its tested in the misc.funcs.simpletest.php test case }}
  310.  *
  311.  * @todo IMHO it would be better to use "\b" (word boundary) to match the beginning of links..
  312.  *
  313.  *  original function: phpBB, extended here for AIM & ICQ
  314.  *  fplanque restricted :// to http:// and mailto://
  315.  */
  316. function make_clickable$text$moredelim '&amp;' )
  317. {
  318.     $text preg_replace(
  319.         array'#(^|[\s>])(https?|mailto)://([^<>{}\s]+[^.,<>{}\s])#i',
  320.             '#(^|[\s>])aim:([^,<\s]+)#i',
  321.             '#(^|[\s>])icq:(\d+)#i',
  322.             '#(^|[\s>])www\.([a-z0-9\-]+)\.([a-z0-9\-.\~]+)((?:/[^<\s]*)?[^.,\s])#i',
  323.             '#(^|[\s>])([a-z0-9\-_.]+?)@([^,<\s]+)#i'),
  324.         array'$1<a href="$2://$3">$2://$3</a>',
  325.             '$1<a href="aim:goim?screenname=$2$3'.$moredelim.'message='.rawurlencode(T_('Hello')).'">$2$3</a>',
  326.             '$1<a href="http://wwp.icq.com/scripts/search.dll?to=$2">$2</a>',
  327.             '$1<a href="http://www.$2.$3$4">www.$2.$3$4</a>',
  328.             '$1<a href="mailto:$2@$3">$2@$3</a>'),
  329.         $text );
  330.  
  331.     return $text;
  332. }
  333.  
  334.  
  335. /***** // Formatting functions *****/
  336.  
  337. /*
  338.  * mysql2date(-)
  339.  *
  340.  * with enhanced format string
  341.  */
  342. function mysql2date$dateformatstring$mysqlstring$useGM false )
  343. {
  344.     $m $mysqlstring;
  345.     ifempty($m) )    return false;
  346.  
  347.     // Get a timestamp:
  348.     $unixtimestamp mktime(substr($m,11,2),substr($m,14,2),substr($m,17,2),substr($m,5,2),substr($m,8,2),substr($m,0,4));
  349.  
  350.     return date_i18n$dateformatstring$unixtimestamp$useGM );
  351. }
  352.  
  353.  
  354. /*
  355.  * date_i18n(-)
  356.  *
  357.  * date internationalization: same as date() formatting but with i18n support
  358.  */
  359. function date_i18n$dateformatstring$unixtimestamp$useGM false )
  360. {
  361.     global $month$month_abbrev$weekday$weekday_abbrev$weekday_letter;
  362.     global $Settings;
  363.  
  364.     $datemonth date('m'$unixtimestamp);
  365.     $dateweekday date('w'$unixtimestamp);
  366.  
  367.     if$dateformatstring == 'isoZ' )
  368.     // full ISO 8601 format
  369.         $dateformatstring 'Y-m-d\TH:i:s\Z';
  370.     }
  371.  
  372.     if$useGM )
  373.     // We want a Greenwich Meridian time:
  374.         $j gmdate($dateformatstring$unixtimestamp ($Settings->get('time_difference'3600));
  375.     }
  376.     else
  377.     {    // We want default timezone time:
  378.         $dateformatstring ' '.$dateformatstring// will be removed later
  379.  
  380.         // echo $dateformatstring, '<br />';
  381.  
  382.         // weekday:
  383.         $dateformatstring preg_replace("/([^\\\])l/"'\\1@@@\\l@@@'$dateformatstring);
  384.         // weekday abbrev:
  385.         $dateformatstring preg_replace("/([^\\\])D/"'\\1@@@\\D@@@'$dateformatstring);
  386.         // weekday letter:
  387.         $dateformatstring preg_replace("/([^\\\])e/"'\\1@@@e@@@'$dateformatstring);
  388.         // month:
  389.         $dateformatstring preg_replace("/([^\\\])F/"'\\1@@@\\F@@@'$dateformatstring);
  390.         // month abbrev:
  391.         $dateformatstring preg_replace("/([^\\\])M/"'\\1@@@\\M@@@'$dateformatstring);
  392.  
  393.         $dateformatstring substr($dateformatstring1strlen($dateformatstring)-1);
  394.  
  395.         // echo $dateformatstring, '<br />';
  396.  
  397.         $j date($dateformatstring$unixtimestamp);
  398.  
  399.         // weekday:
  400.         $j str_replace'@@@l@@@'T_($weekday[$dateweekday])$j);
  401.         // weekday abbrev:
  402.         $j str_replace'@@@D@@@'T_($weekday_abbrev[$dateweekday])$j);
  403.         // weekday letter:
  404.         $j str_replace'@@@e@@@'T_($weekday_letter[$dateweekday])$j);
  405.         // month:
  406.         $j str_replace'@@@F@@@'T_($month[$datemonth])$j);
  407.         // month abbrev:
  408.         $j str_replace'@@@M@@@'T_($month_abbrev[$datemonth])$j);
  409.     }
  410.  
  411.     return $j;
  412. }
  413.  
  414. /**
  415.  * Get start and end day of a week, based on week number and start-of-week
  416.  *
  417.  * Used by Calendar
  418.  *
  419.  * {@internal get_weekstartend(-)}}
  420.  */
  421. function get_weekstartend($mysqlstring$start_of_week)
  422. {
  423.     $my substr($mysqlstring04);
  424.     $mm substr($mysqlstring52);
  425.     $md substr($mysqlstring82);
  426.     $day mktime(000$mm$md$my);
  427.     $weekday date('w'$day);
  428.     $i 86400;
  429.     while$weekday $start_of_week )
  430.     {
  431.         $weekday date('w'$day);
  432.         $day $day 86400;
  433.         $i 0;
  434.     }
  435.     $week['start'$day 86400 $i;
  436.     $week['end']   $day 691199;
  437.     return$week );
  438. }
  439.  
  440.  
  441. function antispambot($emailaddy$mailto 0{
  442.     $emailNOSPAMaddy '';
  443.     srand ((float) microtime(1000000);
  444.     for ($i 0$i strlen($emailaddy)$i $i 1{
  445.         $j floor(rand(0$mailto));
  446.         if ($j == 0{
  447.             $emailNOSPAMaddy .= '&#' ordsubstr$emailaddy$i) )';';
  448.         elseif ($j == 1{
  449.             $emailNOSPAMaddy .= substr($emailaddy$i1);
  450.         elseif ($j == 2{
  451.             $emailNOSPAMaddy .= '%' zeroisedechexordsubstr$emailaddy$i) ) ));
  452.         }
  453.     }
  454.     $emailNOSPAMaddy str_replace('@''&#64;'$emailNOSPAMaddy);
  455.     return $emailNOSPAMaddy;
  456. }
  457.  
  458.  
  459. /*
  460.  * is_email(-)
  461.  *
  462.  * Check that email address looks valid
  463.  */
  464. function is_email($user_email{
  465.     #$chars = "/^([a-z0-9_]|\\-|\\.)+@(([a-z0-9_]|\\-)+\\.)+[a-z]{2,4}\$/i";
  466.     $chars '/^.+@[^\.].*\.[a-z]{2,}$/i';
  467.     if(strstr($user_email'@'&& strstr($user_email'.')) {
  468.         return (bool)(preg_match($chars$user_email));
  469.     else {
  470.         return false;
  471.     }
  472. }
  473.  
  474.  
  475. function alert_error$msg )
  476. // displays a warning box with an error message (original by KYank)
  477.     ?>
  478.     <html xml:lang="<?php locale_lang(?>" lang="<?php locale_lang(?>">
  479.     <head>
  480.     <script language="JavaScript">
  481.     <!--
  482.     alert('<?php echo str_replace"'""\'"$msg ?>');
  483.     history.back();
  484.     //-->
  485.     </script>
  486.     </head>
  487.     <body>
  488.     <!-- this is for non-JS browsers (actually we should never reach that code, but hey, just in case...) -->
  489.     <?php echo $msg?><br />
  490.     <a href="<?php echo $_SERVER["HTTP_REFERER"]?>"><?php echo T_('go back'?></a>
  491.     </body>
  492.     </html>
  493.     <?php
  494.     exit;
  495. }
  496.  
  497.  
  498. function alert_confirm($msg)
  499. // asks a question - if the user clicks Cancel then it brings them back one page
  500.     ?>
  501.     <script language="JavaScript">
  502.     <!--
  503.     if (!confirm("<?php echo $msg ?>")) {
  504.     history.back();
  505.     }
  506.     //-->
  507.     </script>
  508.     <?php
  509. }
  510.  
  511.  
  512. function redirect_js($url,$title="..."{
  513.     ?>
  514.     <script language="JavaScript">
  515.     <!--
  516.     function redirect() {
  517.     window.location = "<?php echo $url?>";
  518.     }
  519.     setTimeout("redirect();", 100);
  520.     //-->
  521.     </script>
  522.     <p><?php echo T_('Redirecting you to:'?> <strong><?php echo $title?></strong><br />
  523.     <br />
  524.     <?php printfT_('If nothing happens, click <a %s>here</a>.')' href="'.$url.'"' )?></p>
  525.     <?php
  526.     exit();
  527. }
  528.  
  529.  
  530. // functions to count the page generation time (from phpBB2)
  531. // ( or just any time between timer_start() and timer_stop() )
  532.  
  533. function timer_start({
  534.         global $timestart;
  535.         $mtime microtime();
  536.         $mtime explode(" ",$mtime);
  537.         $mtime $mtime[1$mtime[0];
  538.         $timestart $mtime;
  539.         return true;
  540.     }
  541.  
  542. function timer_stop($display=0,$precision=3//if called like timer_stop(1), will echo $timetotal
  543.         global $timestart,$timeend;
  544.         $mtime microtime();
  545.         $mtime explode(" ",$mtime);
  546.         $mtime $mtime[1$mtime[0];
  547.         $timeend $mtime;
  548.         $timetotal $timeend-$timestart;
  549.         if ($display)
  550.             echo number_format($timetotal,$precision);
  551.         return($timetotal);
  552.     }
  553.  
  554.  
  555. function xmlrpc_getposttitle($content)
  556. {
  557.     global $post_default_title;
  558.     if (preg_match('/<title>(.+?)<\/title>/is'$content$matchtitle))
  559.     {
  560.         $post_title $matchtitle[1];
  561.     }
  562.     else
  563.     {
  564.         $post_title $post_default_title;
  565.     }
  566.     return($post_title);
  567. }
  568.  
  569. /**
  570.  * Also used by post by mail
  571.  */
  572. function xmlrpc_getpostcategory($content)
  573. {
  574.     if (preg_match('/<category>([0-9]+?)<\/category>/is'$content$matchcat))
  575.     {
  576.         return $matchcat[1];
  577.     }
  578.  
  579.     return false;
  580. }
  581.  
  582. /*
  583.  * xmlrpc_removepostdata(-)
  584.  */
  585. function xmlrpc_removepostdata($content)
  586. {
  587.     $content preg_replace('/<title>(.*?)<\/title>/si'''$content);
  588.     $content preg_replace('/<category>(.*?)<\/category>/si'''$content);
  589.     $content trim($content);
  590.     return($content);
  591. }
  592.  
  593.  
  594. /*
  595.  * xmlrpc_displayresult(-)
  596.  *
  597.  * fplanque: created
  598.  */
  599. function xmlrpc_displayresult$result$log ''$display true )
  600. {
  601.     if$result )
  602.     {
  603.         if$display echo T_('No response!'),"<br />\n";
  604.         return false;
  605.     }
  606.     elseif$result->faultCode() )
  607.     {    // We got a remote error:
  608.         if$display echo T_('Remote error')': '$result->faultString()' ('$result->faultCode()")<br />\n";
  609.         debug_fwrite($log$result->faultCode().' -- '.$result->faultString());
  610.         return false;
  611.     }
  612.  
  613.     // We'll display the response:
  614.     $val $result->value();
  615.     $value xmlrpc_decode_recurse($result->value());
  616.     if (is_array($value))
  617.     {
  618.         $value_arr '';
  619.         foreach($value as $blah)
  620.         {
  621.             $value_arr .= ' ['.$blah.'] ';
  622.         }
  623.         if$display echo T_('Response')': '$value_arr"<br />\n";
  624.         debug_fwrite($log$value_arr);
  625.     }
  626.     else
  627.     {
  628.         if$display echo T_('Response')': '$value ,"<br />\n";
  629.         debug_fwrite($log$value);
  630.     }
  631.  
  632.     return true;
  633. }
  634.  
  635.  
  636. function debug_fopen($filename$mode{
  637.     global $debug;
  638.     if ($debug == && !empty($filename) ) )
  639.     {
  640.         $fp fopen($filename$mode);
  641.         return $fp;
  642.     else {
  643.         return false;
  644.     }
  645. }
  646.  
  647. function debug_fwrite($fp$string)
  648. {
  649.     global $debug;
  650.     if$debug && $fp )
  651.     {
  652.         fwrite($fp$string);
  653.     }
  654. }
  655.  
  656. function debug_fclose($fp)
  657. {
  658.     global $debug;
  659.     if$debug && $fp )
  660.     {
  661.         fclose($fp);
  662.     }
  663. }
  664.  
  665.  
  666.  
  667. /*
  668.  balanceTags
  669.  
  670.  Balances Tags of string using a modified stack.
  671.  
  672.  @param text      Text to be balanced
  673.  @return          Returns balanced text
  674.  @author          Leonard Lin (leonard@acm.org)
  675.  @version         v1.1
  676.  @date            November 4, 2001
  677.  @license         GPL v2.0
  678.  @notes
  679.  @changelog
  680.              1.2  ***TODO*** Make better - change loop condition to $text
  681.              1.1  Fixed handling of append/stack pop order of end text
  682.                   Added Cleaning Hooks
  683.              1.0  First Version
  684. */
  685. function balanceTags($text)
  686. {
  687.     $tagstack array();
  688.     $stacksize 0;
  689.     $tagqueue '';
  690.     $newtext '';
  691.  
  692.     # b2 bug fix for comments - in case you REALLY meant to type '< !--'
  693.     $text str_replace('< !--''<    !--'$text);
  694.  
  695.     # b2 bug fix for LOVE <3 (and other situations with '<' before a number)
  696.     $text preg_replace('#<([0-9]{1})#''&lt;$1'$text);
  697.  
  698.     whilepreg_match("/<(\/?\w*)\s*([^>]*)>/"$text$regex) )
  699.     {
  700.         $newtext $newtext $tagqueue;
  701.  
  702.         $i strpos($text,$regex[0]);
  703.         $l strlen($tagqueuestrlen($regex[0]);
  704.  
  705.         // clear the shifter
  706.         $tagqueue '';
  707.  
  708.         // Pop or Push
  709.         ifsubstr($regex[1],0,1== '/' )
  710.         // End Tag
  711.             $tag strtolower(substr($regex[1],1));
  712.  
  713.             // if too many closing tags
  714.             if($stacksize <= 0{
  715.                 $tag '';
  716.                 //or close to be safe $tag = '/' . $tag;
  717.             }
  718.             // if stacktop value = tag close value then pop
  719.             else if ($tagstack[$stacksize 1== $tag// found closing tag
  720.                 $tag '</' $tag '>'// Close Tag
  721.                 // Pop
  722.                 array_pop ($tagstack);
  723.                 $stacksize--;
  724.             else // closing tag not at top, search for it
  725.                 for ($j=$stacksize-1;$j>=0;$j--{
  726.                     if ($tagstack[$j== $tag{
  727.                     // add tag to tagqueue
  728.                         for ($k=$stacksize-1;$k>=$j;$k--){
  729.                             $tagqueue .= '</' array_pop ($tagstack'>';
  730.                             $stacksize--;
  731.                         }
  732.                         break;
  733.                     }
  734.                 }
  735.                 $tag '';
  736.             }
  737.         }
  738.         else
  739.         // Begin Tag
  740.             $tag strtolower($regex[1]);
  741.  
  742.             // Tag Cleaning
  743.  
  744.             // Push if not img or br or hr
  745.             if($tag != 'br' && $tag != 'img' && $tag != 'hr'{
  746.                 $stacksize array_push ($tagstack$tag);
  747.             }
  748.  
  749.             // Attributes
  750.             // $attributes = $regex[2];
  751.             $attributes $regex[2];
  752.             if($attributes{
  753.                 $attributes ' '.$attributes;
  754.             }
  755.  
  756.             $tag '<'.$tag.$attributes.'>';
  757.         }
  758.  
  759.         $newtext .= substr($text,0,$i$tag;
  760.         $text substr($text,$i+$l);
  761.     }
  762.  
  763.     // Clear Tag Queue
  764.     $newtext $newtext $tagqueue;
  765.  
  766.     // Add Remaining text
  767.     $newtext .= $text;
  768.  
  769.     // Empty Stack
  770.     while($x array_pop($tagstack)) {
  771.         $newtext $newtext '</' $x '>'// Add remaining tags to close
  772.     }
  773.  
  774.     # b2 fix for the bug with HTML comments
  775.     $newtext str_replace'< !--''<'.'!--'$newtext )// the concatenation is needed to work around some strange parse error in PHP 4.3.1
  776.     $newtext str_replace'<    !--''< !--'$newtext );
  777.  
  778.     return $newtext;
  779. }
  780.  
  781.  
  782. /**
  783.  * Clean up the mess PHP has created with its funky quoting everything!
  784.  *
  785.  * {@internal remove_magic_quotes(-)}}
  786.  *
  787.  * @param mixed string or array (function is recursive)
  788.  */
  789. function remove_magic_quotes$mixed )
  790. {
  791.     ifget_magic_quotes_gpc() )
  792.     {    // That stupid PHP behaviour consisting of adding slashes everywhere is unfortunately on
  793.         ifis_array$mixed ) )
  794.         {
  795.             foreach($mixed as $k => $v)
  796.             {
  797.                 $mixed[$kremove_magic_quotes$v );
  798.             }
  799.         }
  800.         else
  801.         {
  802.             // echo 'Removing slashes ';
  803.             $mixed stripslashes$mixed );
  804.         }
  805.     }
  806.     return $mixed;
  807. }
  808.  
  809.  
  810. /**
  811.  * Sets a parameter with values from the request or to provided default,
  812.  * except if param is already set!
  813.  *
  814.  * Also removes magic quotes if they are set automatically by PHP.
  815.  * Also forces type.
  816.  * Priority order: POST, GET, COOKIE, DEFAULT.
  817.  *
  818.  * {@internal param(-) }}
  819.  *
  820.  * @author fplanque
  821.  * @param string Variable to set
  822.  * @param string Force value type to one of:
  823.  *  - boolean
  824.  *  - integer
  825.  *  - float
  826.  *  - string
  827.  *  - array
  828.  *  - object
  829.  *  - null
  830.  *  - html (does nothing)
  831.  * @param mixed Default value or TRUE if user input required
  832.  * @param boolean Do we need to memorize this to regenerate the URL for this page?
  833.  * @param boolean Override if variable already set
  834.  * @param boolean Force setting of variable to default?
  835.  * @return mixed Final value of Variable, or false if we don't force setting and and did not set
  836.  *
  837.  * @todo add option to override what's already set. DONE.
  838.  */
  839. function param(    $var$type '',    $default ''$memorize false$override false$forceset true )
  840. {
  841.     global $$var;
  842.     global $global_param_list;
  843.  
  844.     // Check if already set
  845.     // WARNING: when PHP register globals is ON, COOKIES get priority over GET and POST with this!!!
  846.     if!isset$$var || $override )
  847.     {
  848.         ifisset($_POST[$var]) )
  849.         {
  850.             $$var remove_magic_quotes$_POST[$var);
  851.             // echo "$var=".$$var." set by POST!<br/>";
  852.         }
  853.         elseifisset($_GET["$var"]) )
  854.         {
  855.             $$var remove_magic_quotes($_GET[$var]);
  856.             // echo "$var=".$$var." set by GET!<br/>";
  857.         }
  858.         elseifisset($_COOKIE[$var]))
  859.         {
  860.             $$var remove_magic_quotes($_COOKIE[$var]);
  861.             // echo "$var=".$$var." set by COOKIE!<br/>";
  862.         }
  863.         elseif$default === true )
  864.         {
  865.             die'<p class="error">'.sprintfT_('Parameter %s is required!')$var ).'</p>' );
  866.         }
  867.         elseif$forceset )
  868.         {
  869.             $$var $default;
  870.             // echo "$var=".$$var." set to default<br/>";
  871.         }
  872.         else
  873.         // param not found! don't set the variable.
  874.             // Won't be memorized nor type-forced!
  875.             return false;
  876.         }
  877.     }
  878.     else
  879.     {    // Variable was already set but we need to remove the auto quotes
  880.         $$var remove_magic_quotes($$var);
  881.  
  882.         // echo $var, ' already set';
  883.         /*    if($var == 'post_extracats' )
  884.             { echo "$var=".$$var." was already set! count = ", count($$var),"<br/>";
  885.                 foreach( $$var as $tes )
  886.                 {
  887.                     echo '<br>value=', $tes;
  888.  
  889.                 }
  890.             } */
  891.     }
  892.  
  893.     // type will be forced even if it was set before and not overriden
  894.     if!empty($type) )
  895.     {    // Force the type
  896.         // echo "forcing type!";
  897.         switch$type )
  898.         {
  899.             case 'html':
  900.                 // do nothing
  901.                 break;
  902.  
  903.             case 'string':
  904.                 // echo $var, '=', $$var, '<br>';
  905.                 $$var trimstrip_tags($$var) );
  906.                 break;
  907.  
  908.             default:
  909.                 settype$$var$type );
  910.         }
  911.     }
  912.  
  913.     if$memorize )
  914.     {    // Memorize this parameter
  915.         if!isset($global_param_list) )
  916.         // Init list if necessary:
  917.             $global_param_list array();
  918.         }
  919.         // echo "Memorize(".count($global_param_list).") 'var' => $var, 'type' => $type, 'default' => $default <br>";
  920.         $global_param_list[$vararray'type' => $type'default' => $default );
  921.     }
  922.  
  923.     // echo $var, '(', gettype($$var), ')=', $$var, '<br />';
  924.     return $$var;
  925. }
  926.  
  927.  
  928. /*
  929.  * regenerate_url(-)
  930.  *
  931.  * Regenerate current URL from parameters
  932.  * This may clean it up
  933.  * But it is also useful when generating static pages: you cannot rely on $_REQUEST[]
  934.  *
  935.  * fplanque: created
  936.  */
  937. function regenerate_url$ignore ''$set ''$pagefileurl '' )
  938. {
  939.     global $global_param_list$ReqPath;
  940.  
  941.     if$ignore == '' )
  942.         $ignore array);
  943.     elseif!is_array($ignore) )
  944.         $ignore array$ignore );
  945.  
  946.     if$set == '' )
  947.         $set array);
  948.     elseif!is_array($set) )
  949.         $set array$set );
  950.  
  951.     $params array();
  952.     ifisset($global_param_list) ) foreach$global_param_list as $var => $thisparam )
  953.     {
  954.         $type $thisparam['type'];
  955.         $defval $thisparam['default'];
  956.  
  957.         ifin_array$var$ignore ) )
  958.         {    // we don't want to include that one
  959.             continue;
  960.         }
  961.  
  962.         // Special cases:
  963.         switch$var )
  964.         {
  965.             case 'catsel':
  966.             {
  967.                 global $catsel;
  968.                 if( (empty($catsel)) && (strpos$cat'-' === false) )
  969.                 {    // It's worthwhile retransmitting the catsels
  970.                     foreach$catsel as $value )
  971.                     {
  972.                         $params['catsel%5B%5D='.rawurlencode($value);
  973.                     }
  974.                 }
  975.                 break;
  976.             }
  977.  
  978.             case 'show_status':
  979.             {
  980.                 global $show_status;
  981.                 ifempty($show_status) )
  982.                 {
  983.                     foreach$show_status as $value )
  984.                     {
  985.                         $params['show_status%5B%5D='.rawurlencode($value);
  986.                     }
  987.                 }
  988.                 break;
  989.             }
  990.  
  991.             default:
  992.             {
  993.                 global $$var;
  994.                 $value = $$var;
  995.                 // echo "var=$var, type=$type, defval=[$defval], val=[$value] \n";
  996.                 if( (!empty($value)) && ($value != $defval) )
  997.                 // Value exists and is not set to default value:
  998.                     // echo "adding $var \n";
  999.                     $params[$var.'='.rawurlencode($value);
  1000.                 }
  1001.                 // else echo "ignoring $var \n";
  1002.             }
  1003.         }
  1004.     }
  1005.  
  1006.     ifempty$set ) )
  1007.     {
  1008.         $params array_merge$params$set );
  1009.     }
  1010.  
  1011.     $url empty($pagefileurl$ReqPath $pagefileurl;
  1012.  
  1013.     if!empty$params ) )
  1014.     {
  1015.         $url url_add_param$urlimplode'&amp;'$params ) );
  1016.     }
  1017.  
  1018.     return $url;
  1019. }
  1020.  
  1021.  
  1022. /**
  1023.  * get_path(-)
  1024.  */
  1025. function get_path$which='' )
  1026. {
  1027.     global $core_subdir$skins_subdir$basepath;
  1028.  
  1029.     switch$which )
  1030.     {
  1031.         case 'skins':
  1032.             return $basepath.'/'.$skins_subdir;
  1033.  
  1034.     }
  1035.  
  1036.     return $basepath;
  1037. }
  1038.  
  1039. /*
  1040.  * autoquote(-)
  1041.  */
  1042. function autoquote$string )
  1043. {
  1044.     ifstrpos$string"'" !== )
  1045.     {    // no quote at position 0
  1046.         $string "'".$string."'";
  1047.     }
  1048. }
  1049.  
  1050.  
  1051. /**
  1052.  * Check the validity of a given URL
  1053.  *
  1054.  * Checks allowed URI schemes and URL ban list
  1055.  * URL can be empty
  1056.  *
  1057.  * @param string Url to validate
  1058.  * @param array Allowed URI schemes (see /conf/_formatting.php)
  1059.  * @return mixed false or error message
  1060.  */
  1061. function validate_url$url$allowed_uri_scheme )
  1062. {
  1063.     global $debug;
  1064.  
  1065.     ifempty($url) )
  1066.     {    // Empty URL, no problem
  1067.         return false;
  1068.     }
  1069.  
  1070.     ifpreg_match('¤^                                                        # start
  1071.                                         ([a-z][a-z0-9+.\-]*):[0-9]*        # scheme
  1072.                                         //                                                        # authority absolute URLs only
  1073.                                         [a-z][a-z0-9~+.\-_,:;/\\\\]*     # Don t allow anything too funky like entities
  1074.                                         ([?#][a-z0-9~+.\-_,:;/\\\\%&=#]*)?
  1075.                                         $¤ix'$url$matches) )
  1076.     {    // Cannot vaidate URL structure
  1077.         return T_('Invalid URL');
  1078.     }
  1079.  
  1080.     $scheme strtolower($matches[1]);
  1081.     if(!in_array$scheme$allowed_uri_scheme ))
  1082.     {    // Scheme not allowed
  1083.         return T_('URI scheme not allowed');
  1084.     }
  1085.  
  1086.     // Search for blocked URLs:
  1087.     if$block antispam_check($url) )
  1088.     {
  1089.         if$debug return 'Url refused. Debug info: blacklisted word: ['.$block.']';
  1090.         return T_('URL not allowed');
  1091.     }
  1092.  
  1093.     return false;        // OK
  1094. }
  1095.  
  1096.  
  1097. /**
  1098.  * wrap pre around var_dump(), better debuggin'
  1099.  *
  1100.  * {@internal pre_dump(-) }}
  1101.  *
  1102.  * @author blueyed
  1103.  *
  1104.  * @param mixed variable to dump
  1105.  * @param string title to display
  1106.  */
  1107. function pre_dump($dump$title '')
  1108. {
  1109.     echo "\n".'<pre>';
  1110.     if$title !== '' )
  1111.     {
  1112.         echo $title': <br />';
  1113.     }
  1114.     var_dump($dump);
  1115.     echo '</pre>'."\n";
  1116. }
  1117.  
  1118.  
  1119. $debug_messages array();
  1120. /**
  1121.  * Log a debug string to be displayed later. (Typically at the end of the page)
  1122.  *
  1123.  * {@internal debug_log(-) }}
  1124.  *
  1125.  * @param boolean true to force output
  1126.  */
  1127. function debug_log$message )
  1128. {
  1129.     global $debug_messages;
  1130.  
  1131.     $debug_messages[$message;
  1132. }
  1133.  
  1134. /**
  1135.  * Outputs debug info. (Typically at the end of the page)
  1136.  *
  1137.  * {@internal debug_info(-) }}
  1138.  *
  1139.  * @param boolean true to force output
  1140.  */
  1141. function debug_info$force false )
  1142. {
  1143.     global $debug;
  1144.     global $querycount;
  1145.     global $debug_messages;
  1146.     global $DB;
  1147.     global $obhandler_debug;
  1148.     global $Timer;
  1149.  
  1150.     if$debug || $force )
  1151.     {
  1152.         echo '<div class="debug"><h2>Debug info</h2>';
  1153.  
  1154.         if!$obhandler_debug )
  1155.         // don't display changing time when we want to test obhandler
  1156.             $time_page $Timer->get_duration'main' );
  1157.             $time_queries $Timer->get_duration'sql_queries' );
  1158.             $percent_queries $time_page number_format100/$time_page $time_queries0;
  1159.             echo 'Page processing time: '.$time_page.' seconds.<br/>';
  1160.             echo 'SQL processing time: '.$time_queries.' seconds, '.$percent_queries.'%.<br/>';
  1161.         }
  1162.  
  1163.         ifcount$debug_messages ) )
  1164.         {
  1165.             echo '<h3>Debug messages</h3><ul>';
  1166.             foreach$debug_messages as $message )
  1167.             {
  1168.                 echo '<li>'format_to_output$message'htmlbody' )'</li>';
  1169.             }
  1170.             echo '</ul>';
  1171.         }
  1172.  
  1173.         echo '<h3>DB</h3>';
  1174.  
  1175.         echo 'Old style queries: '$querycount'<br />';
  1176.         echo 'DB queries: '$DB->num_queries'<br />';
  1177.  
  1178.         $DB->dump_queries();
  1179.  
  1180.         echo '</div>';
  1181.     }
  1182. }
  1183.  
  1184. /**
  1185.  * Output Buffer handler.
  1186.  *
  1187.  * It will be set in /blogs/evocore/_main.php and handle the output.
  1188.  * It strips every line and generates a md5-ETag, which is checked against the one eventually
  1189.  * being sent by the browser.
  1190.  *
  1191.  * @author blueyed
  1192.  *  {@internal obhandler(-) }}
  1193.  *
  1194.  * @param string output given by PHP
  1195. */
  1196. function obhandler$output )
  1197. {
  1198.     global $lastmodified$use_gzipcompression$use_etags;
  1199.  
  1200.     // we're sending out by default
  1201.     $sendout true;
  1202.  
  1203.     if!isset$lastmodified ) )
  1204.     // default of lastmodified is now
  1205.         $lastmodified time();
  1206.     }
  1207.  
  1208.  
  1209.     // strip each line
  1210.     $output explode("\n"$output);
  1211.     $out '';
  1212.     foreach ($output as $v)
  1213.         $out .= trim($v"\n";
  1214.  
  1215.     if$use_etags )
  1216.     {    // Generating ETAG
  1217.  
  1218.         // prefix with PUB or AUT.
  1219.         ifis_logged_in() )
  1220.             $ETag '"AUT';    // A private page
  1221.         else $ETag '"PUB'// and public one
  1222.  
  1223.         $ETag .= md5$out ).'"';
  1224.         header'ETag: '.$ETag );
  1225.  
  1226.         // decide to send out or not
  1227.         ifisset($_SERVER['HTTP_IF_NONE_MATCH'])
  1228.                 && stripslashes($_SERVER['HTTP_IF_NONE_MATCH']=== $ETag )
  1229.         // check ETag
  1230.             $sendout false;
  1231.         }
  1232.     }
  1233.  
  1234.     if!$sendout )
  1235.     {  // send 304 and die
  1236.         header'Content-Length: 0' );
  1237.         header$_SERVER['SERVER_PROTOCOL'' 304 Not Modified' );
  1238.         #log_hit();  // log this somehow?
  1239.         die;
  1240.     };
  1241.  
  1242.  
  1243.     // Send Last-Modified -----------------
  1244.     // We should perhaps make this the central point for this.
  1245.     // Also handle Cache-Control and Pragma here (with global vars).
  1246.  
  1247.     // header( 'Last-Modified: ' . gmdate('D, d M Y H:i:s \G\M\T', $lastmodified) );
  1248.  
  1249.  
  1250.     // GZIP encoding
  1251.     if$use_gzipcompression
  1252.             && isset($_SERVER['HTTP_ACCEPT_ENCODING'])
  1253.             && strstr($_SERVER['HTTP_ACCEPT_ENCODING']'gzip') )
  1254.     {
  1255.         $out gzencode($out);
  1256.         header'Content-Encoding: gzip' );
  1257.     }
  1258.  
  1259.  
  1260.     header'Content-Length: 'strlen($out) );
  1261.     return $out;
  1262. }
  1263.  
  1264.  
  1265. /**
  1266.  * Add param(s) at the end of an URL, using either ? or &amp; depending on exiting url
  1267.  *
  1268.  * url_add_param(-)
  1269.  *
  1270.  * @param string existing url
  1271.  * @param string params to add
  1272.  * @param string delimiter to use for more params
  1273.  */
  1274. function url_add_param$url$param$moredelim '&amp;' )
  1275. {
  1276.     ifempty($param) )
  1277.     {
  1278.         return $url;
  1279.     }
  1280.  
  1281.     ifstrpos$url'?' !== false )
  1282.     {    // There are already params in the URL
  1283.         return $url.$moredelim.$param;
  1284.     }
  1285.  
  1286.     // These are the first params
  1287.     return $url.'?'.$param;
  1288. }
  1289.  
  1290.  
  1291. /**
  1292.  * Add a tail (starting with /) at the end of an URL before any params (starting with ?)
  1293.  *
  1294.  * url_add_tail(-)
  1295.  *
  1296.  * @param string existing url
  1297.  * @param string tail to add
  1298.  */
  1299. function url_add_tail$url$tail )
  1300. {
  1301.     $parts explode'?'$url );
  1302.     ifisset($parts[1]) )
  1303.     {
  1304.         return $parts[0].$tail.'?'.$parts[1];
  1305.     }
  1306.  
  1307.     return $parts[0].$tail;
  1308. }
  1309.  
  1310.  
  1311. /**
  1312.  * sends a mail, wraps PHP's mail() function.
  1313.  *
  1314.  * $current_locale will be used to set the charset
  1315.  *
  1316.  * send_mail(-)
  1317.  *
  1318.  * @param string recipient
  1319.  * @param string subject of the mail
  1320.  * @param string the message
  1321.  * @param string From address, being added to headers
  1322.  * @param array additional headers
  1323.  */
  1324. function send_mail$to$subject$message$from ''$headers array() )
  1325. {
  1326.     global $b2_version$current_locale$locales;
  1327.  
  1328.     if!is_array$headers ) )
  1329.     // make sure $headers is an array
  1330.         $headers array$headers );
  1331.     }
  1332.  
  1333.     // Specify charset and content-type of email
  1334.     $headers['Content-Type: text/plain; charset='.$locales$current_locale ]['charset'];
  1335.     $headers['X-Mailer: b2evolution '.$b2_version.' - PHP/'.phpversion();
  1336.  
  1337.     // -- build headers ----
  1338.     if!empty($from) )
  1339.     // from has to go into headers
  1340.         $headerstring "From: $from\n";
  1341.     }
  1342.     else
  1343.     {
  1344.         $headerstring '';
  1345.     }
  1346.  
  1347.     ifcount($headers) )
  1348.     // add supplied headers
  1349.         $headerstring .= implode"\n"$headers );
  1350.     }
  1351.  
  1352.     debug_log"Sending mail from $from to $to - subject $subject.);
  1353.  
  1354.     return @mail$to$subject$message$headerstring );
  1355. }
  1356. ?>

Documentation generated on Tue, 20 May 2008 01:54:29 +0200 by phpDocumentor 1.4.2