includes/functions.php
changeset 76 608dee512bf0
parent 74 68469a95658d
child 78 4df25dfdde63
equal deleted inserted replaced
75:1f85c1c609fd 76:608dee512bf0
    38  * @return null
    38  * @return null
    39  */
    39  */
    40 
    40 
    41 function setConfig($n, $v)
    41 function setConfig($n, $v)
    42 {
    42 {
    43   
    43 
    44   global $enano_config, $db;
    44   global $enano_config, $db;
    45   $enano_config[$n] = $v;
    45   $enano_config[$n] = $v;
    46   $v = $db->escape($v);
    46   $v = $db->escape($v);
    47   
    47 
    48   $e = $db->sql_query('DELETE FROM '.table_prefix.'config WHERE config_name=\''.$n.'\';');
    48   $e = $db->sql_query('DELETE FROM '.table_prefix.'config WHERE config_name=\''.$n.'\';');
    49   if ( !$e )
    49   if ( !$e )
    50   {
    50   {
    51     $db->_die('Error during generic setConfig() call row deletion.');
    51     $db->_die('Error during generic setConfig() call row deletion.');
    52   }
    52   }
    53   
    53 
    54   $e = $db->sql_query('INSERT INTO '.table_prefix.'config(config_name, config_value) VALUES(\''.$n.'\', \''.$v.'\')');
    54   $e = $db->sql_query('INSERT INTO '.table_prefix.'config(config_name, config_value) VALUES(\''.$n.'\', \''.$v.'\')');
    55   if ( !$e )
    55   if ( !$e )
    56   {
    56   {
    57     $db->_die('Error during generic setConfig() call row insertion.');
    57     $db->_die('Error during generic setConfig() call row insertion.');
    58   }
    58   }
    80   {
    80   {
    81     $flags .= $sep . 'theme='.$session->theme;
    81     $flags .= $sep . 'theme='.$session->theme;
    82     $sep = '&';
    82     $sep = '&';
    83   }
    83   }
    84   if ( isset($_GET['style'] ) ) {
    84   if ( isset($_GET['style'] ) ) {
    85     $flags .= $sep . 'style='.$session->style; 
    85     $flags .= $sep . 'style='.$session->style;
    86     $sep = '&';
    86     $sep = '&';
    87   }
    87   }
    88   
    88 
    89   $url = $session->append_sid(contentPath.$t.$flags);
    89   $url = $session->append_sid(contentPath.$t.$flags);
    90   if($query)
    90   if($query)
    91   {
    91   {
    92     $sep = strstr($url, '?') ? '&' : '?';
    92     $sep = strstr($url, '?') ? '&' : '?';
    93     $url = $url . $sep . $query;
    93     $url = $url . $sep . $query;
    94   }
    94   }
    95   
    95 
    96   return ($escape) ? htmlspecialchars($url) : $url;
    96   return ($escape) ? htmlspecialchars($url) : $url;
    97 }
    97 }
    98 
    98 
    99 /**
    99 /**
   100  * Create a URI for an internal link, and be namespace-friendly. Watch out for this one because it's different from most other Enano functions, in that the namespace is the first parameter.
   100  * Create a URI for an internal link, and be namespace-friendly. Watch out for this one because it's different from most other Enano functions, in that the namespace is the first parameter.
   107 
   107 
   108 function makeUrlNS($n, $t, $query = false, $escape = false)
   108 function makeUrlNS($n, $t, $query = false, $escape = false)
   109 {
   109 {
   110   global $db, $session, $paths, $template, $plugins; // Common objects
   110   global $db, $session, $paths, $template, $plugins; // Common objects
   111   $flags = '';
   111   $flags = '';
   112   
   112 
   113   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   113   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   114   {
   114   {
   115     $sep = urlSeparator;
   115     $sep = urlSeparator;
   116   }
   116   }
   117   else
   117   else
   120   }
   120   }
   121   if ( isset( $_GET['printable'] ) ) {
   121   if ( isset( $_GET['printable'] ) ) {
   122     $flags .= $sep . 'printable';
   122     $flags .= $sep . 'printable';
   123     $sep = '&';
   123     $sep = '&';
   124   }
   124   }
   125   if ( isset( $_GET['theme'] ) ) 
   125   if ( isset( $_GET['theme'] ) )
   126   {
   126   {
   127     $flags .= $sep . 'theme='.$session->theme;
   127     $flags .= $sep . 'theme='.$session->theme;
   128     $sep = '&';
   128     $sep = '&';
   129   }
   129   }
   130   if ( isset( $_GET['style'] ) )
   130   if ( isset( $_GET['style'] ) )
   131   {
   131   {
   132     $flags .= $sep . 'style='.$session->style;
   132     $flags .= $sep . 'style='.$session->style;
   133     $sep = '&';
   133     $sep = '&';
   134   }
   134   }
   135   
   135 
   136   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   136   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   137   {
   137   {
   138     $url = contentPath . $paths->nslist[$n] . $t . $flags;
   138     $url = contentPath . $paths->nslist[$n] . $t . $flags;
   139   }
   139   }
   140   else
   140   else
   141   {
   141   {
   142     // If the path manager hasn't been initted yet, take an educated guess at what the URI should be
   142     // If the path manager hasn't been initted yet, take an educated guess at what the URI should be
   143     $url = contentPath . $n . ':' . $t . $flags;
   143     $url = contentPath . $n . ':' . $t . $flags;
   144   }
   144   }
   145   
   145 
   146   if($query)
   146   if($query)
   147   {
   147   {
   148     if(strstr($url, '?')) 
   148     if(strstr($url, '?'))
   149     {
   149     {
   150       $sep =  '&';
   150       $sep =  '&';
   151     }
   151     }
   152     else
   152     else
   153     {
   153     {
   154       $sep = '?';
   154       $sep = '?';
   155     }
   155     }
   156     $url = $url . $sep . $query . $flags;
   156     $url = $url . $sep . $query . $flags;
   157   }
   157   }
   158   
   158 
   159   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   159   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   160   {
   160   {
   161     $url = $session->append_sid($url);
   161     $url = $session->append_sid($url);
   162   }
   162   }
   163   
   163 
   164   return ($escape) ? htmlspecialchars($url) : $url;
   164   return ($escape) ? htmlspecialchars($url) : $url;
   165 }
   165 }
   166 
   166 
   167 /**
   167 /**
   168  * Create a URI for an internal link, be namespace-friendly, and add http://hostname/scriptpath to the beginning if possible. Watch out for this one because it's different from most other Enano functions, in that the namespace is the first parameter.
   168  * Create a URI for an internal link, be namespace-friendly, and add http://hostname/scriptpath to the beginning if possible. Watch out for this one because it's different from most other Enano functions, in that the namespace is the first parameter.
   175 
   175 
   176 function makeUrlComplete($n, $t, $query = false, $escape = false)
   176 function makeUrlComplete($n, $t, $query = false, $escape = false)
   177 {
   177 {
   178   global $db, $session, $paths, $template, $plugins; // Common objects
   178   global $db, $session, $paths, $template, $plugins; // Common objects
   179   $flags = '';
   179   $flags = '';
   180   
   180 
   181   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   181   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   182   {
   182   {
   183     $sep = urlSeparator;
   183     $sep = urlSeparator;
   184   }
   184   }
   185   else
   185   else
   188   }
   188   }
   189   if ( isset( $_GET['printable'] ) ) {
   189   if ( isset( $_GET['printable'] ) ) {
   190     $flags .= $sep . 'printable';
   190     $flags .= $sep . 'printable';
   191     $sep = '&';
   191     $sep = '&';
   192   }
   192   }
   193   if ( isset( $_GET['theme'] ) ) 
   193   if ( isset( $_GET['theme'] ) )
   194   {
   194   {
   195     $flags .= $sep . 'theme='.$session->theme;
   195     $flags .= $sep . 'theme='.$session->theme;
   196     $sep = '&';
   196     $sep = '&';
   197   }
   197   }
   198   if ( isset( $_GET['style'] ) )
   198   if ( isset( $_GET['style'] ) )
   199   {
   199   {
   200     $flags .= $sep . 'style='.$session->style;
   200     $flags .= $sep . 'style='.$session->style;
   201     $sep = '&';
   201     $sep = '&';
   202   }
   202   }
   203   
   203 
   204   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   204   if(defined('ENANO_BASE_CLASSES_INITIALIZED'))
   205   {
   205   {
   206     $url = $session->append_sid(contentPath . $paths->nslist[$n] . $t . $flags);
   206     $url = $session->append_sid(contentPath . $paths->nslist[$n] . $t . $flags);
   207   }
   207   }
   208   else
   208   else
   214   {
   214   {
   215     if(strstr($url, '?')) $sep =  '&';
   215     if(strstr($url, '?')) $sep =  '&';
   216     else $sep = '?';
   216     else $sep = '?';
   217     $url = $url . $sep . $query . $flags;
   217     $url = $url . $sep . $query . $flags;
   218   }
   218   }
   219   
   219 
   220   $baseprot = 'http' . ( isset($_SERVER['HTTPS']) ? 's' : '' ) . '://' . $_SERVER['HTTP_HOST'];
   220   $baseprot = 'http' . ( isset($_SERVER['HTTPS']) ? 's' : '' ) . '://' . $_SERVER['HTTP_HOST'];
   221   $url = $baseprot . $url;
   221   $url = $baseprot . $url;
   222   
   222 
   223   return ($escape) ? htmlspecialchars($url) : $url;
   223   return ($escape) ? htmlspecialchars($url) : $url;
   224 }
   224 }
   225 
   225 
   226 /**
   226 /**
   227  * Tells you the title for the given page ID string
   227  * Tells you the title for the given page ID string
   230  */
   230  */
   231 
   231 
   232 function get_page_title($page_id)
   232 function get_page_title($page_id)
   233 {
   233 {
   234   global $db, $session, $paths, $template, $plugins; // Common objects
   234   global $db, $session, $paths, $template, $plugins; // Common objects
   235   
   235 
   236   $idata = RenderMan::strToPageID($page_id);
   236   $idata = RenderMan::strToPageID($page_id);
   237   $page_id_key = $paths->nslist[ $idata[1] ] . $idata[0];
   237   $page_id_key = $paths->nslist[ $idata[1] ] . $idata[0];
   238   $page_data = $paths->pages[$page_id_key];
   238   $page_data = $paths->pages[$page_id_key];
   239   $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$idata[1]] . str_replace('_', ' ', dirtify_page_id( $idata[0] ) );
   239   $title = ( isset($page_data['name']) ) ? ( $page_data['namespace'] == 'Article' ? '' : $paths->nslist[ $idata[1] ] ) . $page_data['name'] : $paths->nslist[$idata[1]] . str_replace('_', ' ', dirtify_page_id( $idata[0] ) );
   240   return $title;
   240   return $title;
   241 }
   241 }
   242 
   242 
   243 /**
   243 /**
   244  * Tells you the title for the given page ID and namespace
   244  * Tells you the title for the given page ID and namespace
   248  */
   248  */
   249 
   249 
   250 function get_page_title_ns($page_id, $namespace)
   250 function get_page_title_ns($page_id, $namespace)
   251 {
   251 {
   252   global $db, $session, $paths, $template, $plugins; // Common objects
   252   global $db, $session, $paths, $template, $plugins; // Common objects
   253   
   253 
   254   $page_id_key = $paths->nslist[ $namespace ] . $page_id;
   254   $page_id_key = $paths->nslist[ $namespace ] . $page_id;
   255   $page_data = $paths->pages[$page_id_key];
   255   $page_data = $paths->pages[$page_id_key];
   256   $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$namespace] . str_replace('_', ' ', dirtify_page_id( $page_id ) );
   256   $title = ( isset($page_data['name']) ) ? $page_data['name'] : $paths->nslist[$namespace] . str_replace('_', ' ', dirtify_page_id( $page_id ) );
   257   return $title;
   257   return $title;
   258 }
   258 }
   262  * @param string $url The URL, either relative or absolute.
   262  * @param string $url The URL, either relative or absolute.
   263  * @param string $title The title of the message
   263  * @param string $title The title of the message
   264  * @param string $message A short message to show to the user
   264  * @param string $message A short message to show to the user
   265  * @param string $timeout Timeout, in seconds, to delay the redirect. Defaults to 3.
   265  * @param string $timeout Timeout, in seconds, to delay the redirect. Defaults to 3.
   266  */
   266  */
   267  
   267 
   268 function redirect($url, $title = 'Redirecting...', $message = 'Please wait while you are redirected.', $timeout = 3)
   268 function redirect($url, $title = 'Redirecting...', $message = 'Please wait while you are redirected.', $timeout = 3)
   269 {
   269 {
   270   global $db, $session, $paths, $template, $plugins; // Common objects
   270   global $db, $session, $paths, $template, $plugins; // Common objects
   271   
   271 
   272   if ( $timeout == 0 )
   272   if ( $timeout == 0 )
   273   {
   273   {
   274     header('Location: ' . $url);
   274     header('Location: ' . $url);
   275     header('HTTP/1.1 307 Temporary Redirect');
   275     header('HTTP/1.1 307 Temporary Redirect');
   276   }
   276   }
   277   
   277 
   278   $template->add_header('<meta http-equiv="refresh" content="' . $timeout . '; url=' . str_replace('"', '\\"', $url) . '" />');
   278   $template->add_header('<meta http-equiv="refresh" content="' . $timeout . '; url=' . str_replace('"', '\\"', $url) . '" />');
   279   $template->add_header('<script type="text/javascript">
   279   $template->add_header('<script type="text/javascript">
   280       function __r() {
   280       function __r() {
   281         // FUNCTION AUTOMATICALLY GENERATED
   281         // FUNCTION AUTOMATICALLY GENERATED
   282         window.location="' . str_replace('"', '\\"', $url) . '";
   282         window.location="' . str_replace('"', '\\"', $url) . '";
   283       }
   283       }
   284       setTimeout(\'__r();\', ' . $timeout . '000);
   284       setTimeout(\'__r();\', ' . $timeout . '000);
   285     </script>
   285     </script>
   286     ');
   286     ');
   287   
   287 
   288   $template->tpl_strings['PAGE_NAME'] = $title;
   288   $template->tpl_strings['PAGE_NAME'] = $title;
   289   $template->header(true);
   289   $template->header(true);
   290   echo '<p>' . $message . '</p><p>If you are not redirected within ' . ( $timeout + 1 ) . ' seconds, <a href="' . str_replace('"', '\\"', $url) . '">please click here</a>.</p>';
   290   echo '<p>' . $message . '</p><p>If you are not redirected within ' . ( $timeout + 1 ) . ' seconds, <a href="' . str_replace('"', '\\"', $url) . '">please click here</a>.</p>';
   291   $template->footer(true);
   291   $template->footer(true);
   292   
   292 
   293   $db->close();
   293   $db->close();
   294   exit(0);
   294   exit(0);
   295   
   295 
   296 }
   296 }
   297 
   297 
   298 // Removed wikiFormat() from here, replaced with RenderMan::render
   298 // Removed wikiFormat() from here, replaced with RenderMan::render
   299 
   299 
   300 /**
   300 /**
   303  * @return bool True if the page exists, false otherwise
   303  * @return bool True if the page exists, false otherwise
   304  */
   304  */
   305 
   305 
   306 function isPage($p) {
   306 function isPage($p) {
   307   global $db, $session, $paths, $template, $plugins; // Common objects
   307   global $db, $session, $paths, $template, $plugins; // Common objects
   308   
   308 
   309   // Try the easy way first ;-)
   309   // Try the easy way first ;-)
   310   if ( isset( $paths->pages[ $p ] ) )
   310   if ( isset( $paths->pages[ $p ] ) )
   311   {
   311   {
   312     return true;
   312     return true;
   313   }
   313   }
   314   
   314 
   315   // Special case for Special, Template, and Admin pages that can't have slashes in their URIs
   315   // Special case for Special, Template, and Admin pages that can't have slashes in their URIs
   316   $ns_test = RenderMan::strToPageID( $p );
   316   $ns_test = RenderMan::strToPageID( $p );
   317   
   317 
   318   if($ns_test[1] != 'Special' && $ns_test[1] != 'Template' && $ns_test[1] != 'Admin')
   318   if($ns_test[1] != 'Special' && $ns_test[1] != 'Template' && $ns_test[1] != 'Admin')
   319   {
   319   {
   320     return false;
   320     return false;
   321   }
   321   }
   322   
   322 
   323   $particles = explode('/', $p);
   323   $particles = explode('/', $p);
   324   if ( isset ( $paths->pages[ $particles[ 0 ] ] ) )
   324   if ( isset ( $paths->pages[ $particles[ 0 ] ] ) )
   325   {
   325   {
   326     return true;
   326     return true;
   327   }
   327   }
   328   else
   328   else
   329   {
   329   {
   330     return false;
   330     return false;
   331   }
   331   }
   332 }
   332 }
       
   333 
       
   334 /**
       
   335  * These are some old functions that were used with the Midget codebase. They are deprecated and should not be used any more.
       
   336  */
   333 
   337 
   334 function arrayItemUp($arr, $keyname) {
   338 function arrayItemUp($arr, $keyname) {
   335   $keylist = array_keys($arr);
   339   $keylist = array_keys($arr);
   336   $keyflop = array_flip($keylist);
   340   $keyflop = array_flip($keylist);
   337   $idx = $keyflop[$keyname];
   341   $idx = $keyflop[$keyname];
   434   return implode('.', $newoct);
   438   return implode('.', $newoct);
   435 }
   439 }
   436 
   440 
   437 // Function strip_php moved to RenderMan class
   441 // Function strip_php moved to RenderMan class
   438 
   442 
       
   443 /**
       
   444  * Immediately brings the site to a halt with an error message. Unlike grinding_halt() this can only be called after the config has been
       
   445  * fetched (plugin developers don't even need to worry since plugins are always loaded after the config) and shows the site name and
       
   446  * description.
       
   447  * @param string The title of the error message
       
   448  * @param string The body of the message, this can be HTML, and should be separated into paragraphs using the <p> tag
       
   449  */
       
   450 
   439 function die_semicritical($t, $p)
   451 function die_semicritical($t, $p)
   440 {
   452 {
   441   global $db, $session, $paths, $template, $plugins; // Common objects
   453   global $db, $session, $paths, $template, $plugins; // Common objects
   442   $db->close();
   454   $db->close();
   443   
   455 
   444   if ( ob_get_status() )
   456   if ( ob_get_status() )
   445     ob_end_clean();
   457     ob_end_clean();
   446   
   458 
   447   dc_here('functions: <span style="color: red">calling die_semicritical</span>');
   459   dc_here('functions: <span style="color: red">calling die_semicritical</span>');
   448   
   460 
   449   $tpl = new template_nodb();
   461   $tpl = new template_nodb();
   450   $tpl->load_theme('oxygen', 'bleu');
   462   $tpl->load_theme('oxygen', 'bleu');
   451   $tpl->tpl_strings['SITE_NAME'] = getConfig('site_name');
   463   $tpl->tpl_strings['SITE_NAME'] = getConfig('site_name');
   452   $tpl->tpl_strings['SITE_DESC'] = getConfig('site_desc');
   464   $tpl->tpl_strings['SITE_DESC'] = getConfig('site_desc');
   453   $tpl->tpl_strings['COPYRIGHT'] = getConfig('copyright_notice');
   465   $tpl->tpl_strings['COPYRIGHT'] = getConfig('copyright_notice');
   454   $tpl->tpl_strings['PAGE_NAME'] = $t;
   466   $tpl->tpl_strings['PAGE_NAME'] = $t;
   455   $tpl->header();
   467   $tpl->header();
   456   echo $p;
   468   echo $p;
   457   $tpl->footer();
   469   $tpl->footer();
   458   
   470 
   459   exit;
   471   exit;
   460 }
   472 }
   461 
   473 
       
   474 /**
       
   475  * Halts Enano execution with a message. This doesn't have to be an error message, it's sometimes used to indicate success at an operation.
       
   476  * @param string The title of the message
       
   477  * @param string The body of the message, this can be HTML, and should be separated into paragraphs using the <p> tag
       
   478  */
       
   479 
   462 function die_friendly($t, $p)
   480 function die_friendly($t, $p)
   463 {
   481 {
   464   global $db, $session, $paths, $template, $plugins; // Common objects
   482   global $db, $session, $paths, $template, $plugins; // Common objects
   465   
   483 
   466   if ( ob_get_status() )
   484   if ( ob_get_status() )
   467     ob_end_clean();
   485     ob_end_clean();
   468   
   486 
   469   dc_here('functions: <span style="color: red">calling die_friendly</span>');
   487   dc_here('functions: <span style="color: red">calling die_friendly</span>');
   470   $paths->cpage['name'] = $t;
   488   $paths->cpage['name'] = $t;
   471   $template->tpl_strings['PAGE_NAME'] = $t;
   489   $template->tpl_strings['PAGE_NAME'] = $t;
   472   $template->header();
   490   $template->header();
   473   echo $p;
   491   echo $p;
   474   $template->footer();
   492   $template->footer();
   475   $db->close();
   493   $db->close();
   476   
   494 
   477   exit;
   495   exit;
   478 }
   496 }
   479 
   497 
       
   498 /**
       
   499  * Immediately brings the site to a halt with an error message, and focuses on immediately closing the database connection and shutting down Enano in the event that an attack may happen. This should only be used very early on to indicate very severe errors, or if the site may be under attack (like if the DBAL detects a malicious query). In the vast majority of cases, die_semicritical() is more appropriate.
       
   500  * @param string The title of the error message
       
   501  * @param string The body of the message, this can be HTML, and should be separated into paragraphs using the <p> tag
       
   502  */
       
   503 
   480 function grinding_halt($t, $p)
   504 function grinding_halt($t, $p)
   481 {
   505 {
   482   global $db, $session, $paths, $template, $plugins; // Common objects
   506   global $db, $session, $paths, $template, $plugins; // Common objects
   483   
   507 
   484   $db->close();
   508   $db->close();
   485   
   509 
   486   if ( ob_get_status() )
   510   if ( ob_get_status() )
   487     ob_end_clean();
   511     ob_end_clean();
   488   
   512 
   489   dc_here('functions: <span style="color: red">calling grinding_halt</span>');
   513   dc_here('functions: <span style="color: red">calling grinding_halt</span>');
   490   $tpl = new template_nodb();
   514   $tpl = new template_nodb();
   491   $tpl->load_theme('oxygen', 'bleu');
   515   $tpl->load_theme('oxygen', 'bleu');
   492   $tpl->tpl_strings['SITE_NAME'] = 'Critical error';
   516   $tpl->tpl_strings['SITE_NAME'] = 'Critical error';
   493   $tpl->tpl_strings['SITE_DESC'] = 'This website is experiencing a serious error and cannot load.';
   517   $tpl->tpl_strings['SITE_DESC'] = 'This website is experiencing a serious error and cannot load.';
   497   echo $p;
   521   echo $p;
   498   $tpl->footer();
   522   $tpl->footer();
   499   exit;
   523   exit;
   500 }
   524 }
   501 
   525 
   502 function show_category_info() {
   526 /**
       
   527  * Prints out the categorization box found on most regular pages. Doesn't take or return anything, but assumes that the page information is already set in $paths.
       
   528  */
       
   529 
       
   530  /*
       
   531 function show_category_info()
       
   532 {
   503   global $db, $session, $paths, $template, $plugins; // Common objects
   533   global $db, $session, $paths, $template, $plugins; // Common objects
   504   dc_here('functions: showing category info');
   534   dc_here('functions: showing category info');
   505   if($template->no_headers && !strpos($_SERVER['REQUEST_URI'], 'ajax.php')) return '';
   535   // if($template->no_headers && !strpos($_SERVER['REQUEST_URI'], 'ajax.php')) return '';
   506   if($paths->namespace=='Category')
   536   if ( $paths->namespace == 'Category' )
   507   {
   537   {
   508     $q = $db->sql_query('SELECT page_id,namespace FROM '.table_prefix.'categories WHERE category_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace=\'Category\' ORDER BY page_id;');
   538     $q = $db->sql_query('SELECT page_id,namespace FROM '.table_prefix.'categories WHERE category_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace=\'Category\' ORDER BY page_id;');
   509     if(!$q) $db->_die('The category information could not be selected.');
   539     if(!$q) $db->_die('The category information could not be selected.');
   510     $ticker = -1;
   540     $ticker = -1;
   511     echo '<h3>Subcategories</h3>';
   541     echo '<h3>Subcategories</h3>';
   512     if($db->numrows() < 1) echo '<p>There are no subcategories in this category.</p>';
   542     if($db->numrows() < 1) echo '<p>There are no subcategories in this category.</p>';
   513     echo '<table border="0" cellspacing="1" cellpadding="4">';
   543     echo '<table border="0" cellspacing="1" cellpadding="4">';
   514     while($row = $db->fetchrow())
   544     while($row = $db->fetchrow())
   515     {
   545     {
   516       $ticker++;if($ticker==3) $ticker=0;
   546       $ticker++;
   517       if($ticker==0) echo '<tr>';
   547       if ( $ticker == 3 )
   518       echo '<td style="width: 200px;"><a href="'.makeUrlNS($row['namespace'], $row['page_id']).'">'.$paths->pages[$paths->nslist[$row['namespace']].$row['page_id']]['name'].'</a></td>';
   548       {
   519       if($ticker==2) echo '</tr>';
   549         $ticker = 0;
       
   550       }
       
   551       if ( $ticker == 0 )
       
   552       {
       
   553         echo '<tr>';
       
   554       }
       
   555       echo '<td style="width: 200px;"><a href="' . makeUrlNS($row['namespace'], $row['page_id']) . '">' . htmlspecialchars($paths->pages[$paths->nslist[$row['namespace']].$row['page_id']]['name']) . '</a></td>';
       
   556       if ( $ticker == 2 )
       
   557       {
       
   558         echo '</tr>';
       
   559       }
   520     }
   560     }
   521     $db->free_result();
   561     $db->free_result();
   522     if($ticker) echo '</tr>';
   562     if($ticker) echo '</tr>';
   523     echo '</table>';
   563     echo '</table>';
   524     
   564 
   525     $q = $db->sql_query('SELECT page_id,namespace FROM '.table_prefix.'categories WHERE category_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace!=\'Category\' ORDER BY page_id;');
   565     $q = $db->sql_query('SELECT page_id,namespace FROM '.table_prefix.'categories WHERE category_id=\''.$paths->cpage['urlname_nons'].'\' AND namespace!=\'Category\' ORDER BY page_id;');
   526     if(!$q) $db->_die('The category information could not be selected.');
   566     if ( !$q )
       
   567     {
       
   568       $db->_die('The category information could not be selected.');
       
   569     }
   527     $ticker = -1;
   570     $ticker = -1;
   528     echo '<h3>Pages</h3>';
   571     echo '<h3>Pages</h3>';
   529     if($db->numrows() < 1) echo '<p>There are no pages in this category.</p>';
   572     if ( $db->numrows() < 1 )
       
   573     {
       
   574       echo '<p>There are no pages in this category.</p>';
       
   575     }
   530     echo '<table border="0" cellspacing="1" cellpadding="4">';
   576     echo '<table border="0" cellspacing="1" cellpadding="4">';
   531     while($row = $db->fetchrow())
   577     while($row = $db->fetchrow())
   532     {
   578     {
   533       $ticker++;if($ticker==3) $ticker=0;
   579       $ticker += ( $ticker == 3 ) ? -3 : 1;
   534       if($ticker==0) echo '<tr>';
   580       if ( $ticker == 0 )
   535       echo '<td style="width: 200px;"><a href="'.makeUrlNS($row['namespace'], $row['page_id']).'">'.$paths->pages[$paths->nslist[$row['namespace']].$row['page_id']]['name'].'</a></td>';
   581       {
   536       if($ticker==2) echo '</tr>';
   582         echo '<tr>';
       
   583       }
       
   584       echo '<td style="width: 200px;"><a href="'.makeUrlNS($row['namespace'], $row['page_id']).'">'.htmlspecialchars($paths->pages[$paths->nslist[$row['namespace']].$row['page_id']]['name']).'</a></td>';
       
   585       if ( $ticker == 2 )
       
   586       {
       
   587         echo '</tr>';
       
   588       }
   537     }
   589     }
   538     $db->free_result();
   590     $db->free_result();
   539     if($ticker) echo '</tr>';
   591     if($ticker) echo '</tr>';
   540     echo '</table><br /><br />';
   592     echo '</table><br /><br />';
   541   }
   593   }
   549       if($i>0) echo ', ';
   601       if($i>0) echo ', ';
   550       $i++;
   602       $i++;
   551       echo '<a href="'.makeUrlNS('Category', $r['category_id']).'">'.$paths->pages[$paths->nslist['Category'].$r['category_id']]['name'].'</a>';
   603       echo '<a href="'.makeUrlNS('Category', $r['category_id']).'">'.$paths->pages[$paths->nslist['Category'].$r['category_id']]['name'].'</a>';
   552     }
   604     }
   553     if( ( $paths->wiki_mode && !$paths->page_protected ) || ( $session->get_permissions('edit_cat') && $session->get_permissions('even_when_protected') ) ) echo ' [ <a href="'.makeUrl($paths->page, 'do=catedit', true).'" onclick="ajaxCatEdit(); return false;">edit categorization</a> ]</div>';
   605     if( ( $paths->wiki_mode && !$paths->page_protected ) || ( $session->get_permissions('edit_cat') && $session->get_permissions('even_when_protected') ) ) echo ' [ <a href="'.makeUrl($paths->page, 'do=catedit', true).'" onclick="ajaxCatEdit(); return false;">edit categorization</a> ]</div>';
   554   } else {
   606   } 
       
   607   else
       
   608   {
   555     echo '<div class="mdg-comment" style="margin-left: 0;">Categories: ';
   609     echo '<div class="mdg-comment" style="margin-left: 0;">Categories: ';
   556     echo '(Uncategorized)';
   610     echo '(Uncategorized)';
   557     if( ( $paths->wiki_mode && !$paths->page_protected ) || ( $session->get_permissions('edit_cat') && $session->get_permissions('even_when_protected') ) ) echo ' [ <a href="'.makeUrl($paths->page, 'do=catedit', true).'" onclick="ajaxCatEdit(); return false;">edit categorization</a> ]</div>';
   611     if( ( $paths->wiki_mode && !$paths->page_protected ) || ( $session->get_permissions('edit_cat') && $session->get_permissions('even_when_protected') ) ) echo ' [ <a href="'.makeUrl($paths->page, 'do=catedit', true).'" onclick="ajaxCatEdit(); return false;">edit categorization</a> ]</div>';
   558     else echo '</div>';
   612     else echo '</div>';
   559   }
   613   }
   560   $db->free_result();
   614   $db->free_result();
   561 }
   615 }
       
   616 */
       
   617 
       
   618 function show_category_info()
       
   619 {
       
   620   global $db, $session, $paths, $template, $plugins; // Common objects
       
   621   
       
   622   if ( $paths->namespace == 'Category' )
       
   623   {
       
   624     // Show member pages and subcategories
       
   625     $q = $db->sql_query('SELECT p.urlname, p.namespace, p.name, p.namespace=\'Category\' AS is_category FROM '.table_prefix.'categories AS c
       
   626                            LEFT JOIN '.table_prefix.'pages AS p
       
   627                              ON ( p.urlname = c.page_id AND p.namespace = c.namespace )
       
   628                            WHERE c.category_id=\'' . $db->escape($paths->cpage['urlname_nons']) . '\'
       
   629                            ORDER BY is_category DESC, p.name ASC;');
       
   630     if ( !$q )
       
   631     {
       
   632       $db->_die();
       
   633     }
       
   634     echo '<h3>Subcategories</h3>';
       
   635     echo '<div class="tblholder">';
       
   636     echo '<table border="0" cellspacing="1" cellpadding="4">';
       
   637     echo '<tr>';
       
   638     $ticker = 0;
       
   639     $counter = 0;
       
   640     $switched = false;
       
   641     $class  = 'row1';
       
   642     while ( $row = $db->fetchrow() )
       
   643     {
       
   644       if ( $row['is_category'] == 0 && !$switched )
       
   645       {
       
   646         if ( $counter > 0 )
       
   647         {
       
   648           // Fill-in
       
   649           while ( $ticker < 3 )
       
   650           {
       
   651             $ticker++;
       
   652             echo '<td class="' . $class . '" style="width: 33.3%;"></td>';
       
   653           }
       
   654         }
       
   655         else
       
   656         {
       
   657           echo '<td class="' . $class . '">No subcategories.</td>';
       
   658         }
       
   659         echo '</tr></table></div>' . "\n\n";
       
   660         echo '<h3>Pages</h3>';
       
   661         echo '<div class="tblholder">';
       
   662         echo '<table border="0" cellspacing="1" cellpadding="4">';
       
   663         echo '<tr>';
       
   664         $counter = 0;
       
   665         $ticker = 0;
       
   666         $switched = true;
       
   667       }
       
   668       $counter++;
       
   669       $ticker++;
       
   670       if ( $ticker == 3 )
       
   671       {
       
   672         echo '</tr><tr>';
       
   673         $ticker = 0;
       
   674         $class = ( $class == 'row3' ) ? 'row1' : 'row3';
       
   675       }
       
   676       echo "<td class=\"{$class}\" style=\"width: 33.3%;\">"; // " to workaround stupid jEdit bug
       
   677       
       
   678       $link = makeUrlNS($row['namespace'], sanitize_page_id($row['urlname']));
       
   679       echo '<a href="' . $link . '"';
       
   680       $key = $paths->nslist[$row['namespace']] . sanitize_page_id($row['urlname']);
       
   681       if ( !isPage( $key ) )
       
   682       {
       
   683         echo ' class="wikilink-nonexistent"';
       
   684       }
       
   685       echo '>';
       
   686       $title = get_page_title_ns($row['urlname'], $row['namespace']);
       
   687       echo htmlspecialchars($title);
       
   688       echo '</a>';
       
   689       
       
   690       echo "</td>";
       
   691     }
       
   692     if ( !$switched )
       
   693     {
       
   694       if ( $counter > 0 )
       
   695       {
       
   696         // Fill-in
       
   697         while ( $ticker < 3 )
       
   698         {
       
   699           $ticker++;
       
   700           echo '<td class="' . $class . '" style="width: 33.3%;"></td>';
       
   701         }
       
   702       }
       
   703       else
       
   704       {
       
   705         echo '<td class="' . $class . '">No subcategories.</td>';
       
   706       }
       
   707       echo '</tr></table></div>' . "\n\n";
       
   708       echo '<h3>Pages</h3>';
       
   709       echo '<div class="tblholder">';
       
   710       echo '<table border="0" cellspacing="1" cellpadding="4">';
       
   711       echo '<tr>';
       
   712       $counter = 0;
       
   713       $ticker = 0;
       
   714       $switched = true;
       
   715     }
       
   716     if ( $counter > 0 )
       
   717     {
       
   718       // Fill-in
       
   719       while ( $ticker < 3 )
       
   720       {
       
   721         $ticker++;
       
   722         echo '<td class="' . $class . '" style="width: 33.3%;"></td>';
       
   723       }
       
   724     }
       
   725     else
       
   726     {
       
   727       echo '<td class="' . $class . '">No pages in this category.</td>';
       
   728     }
       
   729     echo '</tr></table></div>' . "\n\n";
       
   730   }
       
   731   
       
   732   if ( $paths->namespace != 'Special' && $paths->namespace != 'Admin' )
       
   733   {
       
   734     echo '<div class="mdg-comment" style="margin: 10px 0 0 0;">';
       
   735     if ( $session->user_level >= USER_LEVEL_ADMIN )
       
   736     {
       
   737       echo '<div style="float: right;">';
       
   738       echo '(<a href="#" onclick="ajaxCatToTag(); return false;">show page tags</a>)';
       
   739       echo '</div>';
       
   740     }
       
   741     echo '<div id="mdgCatBox">Categories: ';
       
   742     
       
   743     $where = '( c.page_id=\'' . $db->escape($paths->cpage['urlname_nons']) . '\' AND c.namespace=\'' . $db->escape($paths->namespace) . '\' )';
       
   744     $prefix = table_prefix;
       
   745     $sql = <<<EOF
       
   746 SELECT c.category_id FROM {$prefix}categories AS c
       
   747   LEFT JOIN {$prefix}pages AS p
       
   748     ON ( ( p.urlname = c.page_id AND p.namespace = c.namespace ) OR ( p.urlname IS NULL AND p.namespace IS NULL ) )
       
   749   WHERE $where
       
   750   ORDER BY p.name ASC, c.page_id ASC;
       
   751 EOF;
       
   752     $q = $db->sql_query($sql);
       
   753     if ( !$q )
       
   754       $db->_die();
       
   755     
       
   756     if ( $row = $db->fetchrow() )
       
   757     {
       
   758       $list = array();
       
   759       do
       
   760       {
       
   761         $cid = sanitize_page_id($row['category_id']);
       
   762         $title = get_page_title_ns($cid, 'Category');
       
   763         $link = makeUrlNS('Category', $cid);
       
   764         $list[] = '<a href="' . $link . '">' . htmlspecialchars($title) . '</a>';
       
   765       }
       
   766       while ( $row = $db->fetchrow() );
       
   767       echo implode(', ', $list);
       
   768     }
       
   769     else
       
   770     {
       
   771       echo '(Uncategorized)';
       
   772     }
       
   773     
       
   774     $can_edit = ( $session->get_permissions('edit_cat') && ( !$paths->page_protected || $session->get_permissions('even_when_protected') ) );
       
   775     if ( $can_edit )
       
   776     {
       
   777       $edit_link = '<a href="' . makeUrl($paths->page, 'do=catedit', true) . '" onclick="ajaxCatEdit(); return false;">edit categorization</a>';
       
   778       echo ' [ ' . $edit_link . ' ]';
       
   779     }
       
   780     
       
   781     echo '</div></div>';
       
   782     
       
   783   }
       
   784   
       
   785 }
       
   786 
       
   787 /**
       
   788  * Prints out the file information box seen on File: pages. Doesn't take or return anything, but assumes that the page information is already set in $paths, and expects $paths->namespace to be File.
       
   789  */
   562 
   790 
   563 function show_file_info()
   791 function show_file_info()
   564 {
   792 {
   565   global $db, $session, $paths, $template, $plugins; // Common objects
   793   global $db, $session, $paths, $template, $plugins; // Common objects
   566   if($paths->namespace != 'File') return null; // Prevent unnecessary work
   794   if($paths->namespace != 'File') return null; // Prevent unnecessary work
   628   }
   856   }
   629   $db->free_result();
   857   $db->free_result();
   630   echo '</div><br />';
   858   echo '</div><br />';
   631 }
   859 }
   632 
   860 
       
   861 /**
       
   862  * Shows header information on the current page. Currently this is only the delete-vote feature. Doesn't take or return anything, but assumes that the page information is already set in $paths.
       
   863  */
       
   864 
   633 function display_page_headers()
   865 function display_page_headers()
   634 {
   866 {
   635   global $db, $session, $paths, $template, $plugins; // Common objects
   867   global $db, $session, $paths, $template, $plugins; // Common objects
   636   if($session->get_permissions('vote_reset') && $paths->cpage['delvotes'] > 0)
   868   if($session->get_permissions('vote_reset') && $paths->cpage['delvotes'] > 0)
   637   {
   869   {
   651             <a href="'.makeUrl($paths->page, 'do=deletepage').'" onclick="ajaxDeletePage(); return false;">Delete page</a>  |  <a href="'.makeUrl($paths->page, 'do=resetvotes').'" onclick="ajaxResetDelVotes(); return false;">Reset votes</a>
   883             <a href="'.makeUrl($paths->page, 'do=deletepage').'" onclick="ajaxDeletePage(); return false;">Delete page</a>  |  <a href="'.makeUrl($paths->page, 'do=resetvotes').'" onclick="ajaxResetDelVotes(); return false;">Reset votes</a>
   652           </div>';
   884           </div>';
   653   }
   885   }
   654 }
   886 }
   655 
   887 
       
   888 /**
       
   889  * Displays page footer information including file and category info. This also has the send_page_footers hook. Doesn't take or return anything, but assumes that the page information is already set in $paths.
       
   890  */
       
   891 
   656 function display_page_footers()
   892 function display_page_footers()
   657 {
   893 {
   658   global $db, $session, $paths, $template, $plugins; // Common objects
   894   global $db, $session, $paths, $template, $plugins; // Common objects
   659   if(isset($_GET['nofooters'])) return;
   895   if(isset($_GET['nofooters'])) return;
   660   $code = $plugins->setHook('send_page_footers');
   896   $code = $plugins->setHook('send_page_footers');
   664   }
   900   }
   665   show_file_info();
   901   show_file_info();
   666   show_category_info();
   902   show_category_info();
   667 }
   903 }
   668 
   904 
       
   905 /**
       
   906  * Deprecated, do not use.
       
   907  */
       
   908 
   669 function password_prompt($id = false)
   909 function password_prompt($id = false)
   670 {
   910 {
   671   global $db, $session, $paths, $template, $plugins; // Common objects
   911   global $db, $session, $paths, $template, $plugins; // Common objects
   672   if(!$id) $id = $paths->page;
   912   if(!$id) $id = $paths->page;
   673   if(isset($paths->pages[$id]['password']) && strlen($paths->pages[$id]['password']) == 40 && !isset($_REQUEST['pagepass']))
   913   if(isset($paths->pages[$id]['password']) && strlen($paths->pages[$id]['password']) == 40 && !isset($_REQUEST['pagepass']))
   677     $p = (preg_match('#^([a-f0-9]*){40}$#', $_REQUEST['pagepass'])) ? $_REQUEST['pagepass'] : sha1($_REQUEST['pagepass']);
   917     $p = (preg_match('#^([a-f0-9]*){40}$#', $_REQUEST['pagepass'])) ? $_REQUEST['pagepass'] : sha1($_REQUEST['pagepass']);
   678     if($p != $paths->pages[$id]['password']) die_friendly('Password required', '<p style="color: red;">The password you entered is incorrect.</p><form action="'.makeUrl($paths->page).'" method="post"><p>Password: <input name="pagepass" type="password" /></p><p><input type="submit" value="Submit" /></p>');
   918     if($p != $paths->pages[$id]['password']) die_friendly('Password required', '<p style="color: red;">The password you entered is incorrect.</p><form action="'.makeUrl($paths->page).'" method="post"><p>Password: <input name="pagepass" type="password" /></p><p><input type="submit" value="Submit" /></p>');
   679   }
   919   }
   680 }
   920 }
   681 
   921 
       
   922 /**
       
   923  * Some sort of primitive hex converter from back in the day. Deprecated, do not use.
       
   924  * @param string Text to encode
       
   925  * @return string
       
   926  */
       
   927 
   682 function str_hex($string){
   928 function str_hex($string){
   683     $hex='';
   929     $hex='';
   684     for ($i=0; $i < strlen($string); $i++){
   930     for ($i=0; $i < strlen($string); $i++){
   685         $hex .= ' '.dechex(ord($string[$i]));
   931         $hex .= ' '.dechex(ord($string[$i]));
   686     }
   932     }
   687     return substr($hex, 1, strlen($hex));
   933     return substr($hex, 1, strlen($hex));
   688 }
   934 }
   689 
   935 
   690 // Function pulled from phpBB's smtp.php
   936 /**
   691 function smtp_get_response($socket, $response, $line = __LINE__) 
   937  * Essentially an return code reader for a socket. Don't use this unless you're writing mail code and smtp_send_email doesn't cut it. Ported from phpBB's smtp.php.
   692 {
   938  * @param socket A socket resource
   693 	$server_response = '';
   939  * @param string The expected response from the server, this needs to be exactly three characters.
   694 	while (substr($server_response, 3, 1) != ' ') 
   940  */
   695 	{
   941 
   696 		if (!($server_response = fgets($socket, 256))) 
   942 function smtp_get_response($socket, $response, $line = __LINE__)
   697 		{
   943 {
       
   944   $server_response = '';
       
   945   while (substr($server_response, 3, 1) != ' ')
       
   946   {
       
   947     if (!($server_response = fgets($socket, 256)))
       
   948     {
   698       die_friendly('SMTP Error', "<p>Couldn't get mail server response codes</p>");
   949       die_friendly('SMTP Error', "<p>Couldn't get mail server response codes</p>");
   699 		}
   950     }
   700 	} 
   951   }
   701 
   952 
   702 	if (!(substr($server_response, 0, 3) == $response)) 
   953   if (!(substr($server_response, 0, 3) == $response))
   703 	{ 
   954   {
   704     die_friendly('SMTP Error', "<p>Ran into problems sending mail. Response: $server_response</p>");
   955     die_friendly('SMTP Error', "<p>Ran into problems sending mail. Response: $server_response</p>");
   705 	} 
   956   }
   706 }
   957 }
       
   958 
       
   959 /**
       
   960  * Wrapper for smtp_send_email_core that takes the sender as the fourth parameter instead of additional headers.
       
   961  * @param string E-mail address to send to
       
   962  * @param string Subject line
       
   963  * @param string The body of the message
       
   964  * @param string Address of the sender
       
   965  */
   707 
   966 
   708 function smtp_send_email($to, $subject, $message, $from)
   967 function smtp_send_email($to, $subject, $message, $from)
   709 {
   968 {
   710   return smtp_send_email_core($to, $subject, $message, "From: <$from>\n");
   969   return smtp_send_email_core($to, $subject, $message, "From: <$from>\n");
   711 }
   970 }
   712 
   971 
   713 // Replacement or substitute for PHP's mail command
   972 /**
   714 // Ported from phpBB - copyright (C) phpBB group, GPL.
   973  * Replacement or substitute for PHP's mail() builtin function.
       
   974  * @param string E-mail address to send to
       
   975  * @param string Subject line
       
   976  * @param string The body of the message
       
   977  * @param string Message headers, separated by a single newline ("\n")
       
   978  * @copyright (C) phpBB Group
       
   979  * @license GPL
       
   980  */
       
   981 
   715 function smtp_send_email_core($mail_to, $subject, $message, $headers = '')
   982 function smtp_send_email_core($mail_to, $subject, $message, $headers = '')
   716 {
   983 {
   717 	global $board_config;
   984   // Fix any bare linefeeds in the message to make it RFC821 Compliant.
   718 
   985   $message = preg_replace("#(?<!\r)\n#si", "\r\n", $message);
   719 	// Fix any bare linefeeds in the message to make it RFC821 Compliant.
   986 
   720 	$message = preg_replace("#(?<!\r)\n#si", "\r\n", $message);
   987   if ($headers != '')
   721 
   988   {
   722 	if ($headers != '')
   989     if (is_array($headers))
   723 	{
   990     {
   724 		if (is_array($headers))
   991       if (sizeof($headers) > 1)
   725 		{
   992       {
   726 			if (sizeof($headers) > 1)
   993         $headers = join("\n", $headers);
   727 			{
   994       }
   728 				$headers = join("\n", $headers);
   995       else
   729 			}
   996       {
   730 			else
   997         $headers = $headers[0];
   731 			{
   998       }
   732 				$headers = $headers[0];
   999     }
   733 			}
  1000     $headers = chop($headers);
   734 		}
  1001 
   735 		$headers = chop($headers);
  1002     // Make sure there are no bare linefeeds in the headers
   736 
  1003     $headers = preg_replace('#(?<!\r)\n#si', "\r\n", $headers);
   737 		// Make sure there are no bare linefeeds in the headers
  1004 
   738 		$headers = preg_replace('#(?<!\r)\n#si', "\r\n", $headers);
  1005     // Ok this is rather confusing all things considered,
   739 
  1006     // but we have to grab bcc and cc headers and treat them differently
   740 		// Ok this is rather confusing all things considered,
  1007     // Something we really didn't take into consideration originally
   741 		// but we have to grab bcc and cc headers and treat them differently
  1008     $header_array = explode("\r\n", $headers);
   742 		// Something we really didn't take into consideration originally
  1009     @reset($header_array);
   743 		$header_array = explode("\r\n", $headers);
  1010 
   744 		@reset($header_array);
  1011     $headers = '';
   745 
  1012     while(list(, $header) = each($header_array))
   746 		$headers = '';
  1013     {
   747 		while(list(, $header) = each($header_array))
  1014       if (preg_match('#^cc:#si', $header))
   748 		{
  1015       {
   749 			if (preg_match('#^cc:#si', $header))
  1016         $cc = preg_replace('#^cc:(.*)#si', '\1', $header);
   750 			{
  1017       }
   751 				$cc = preg_replace('#^cc:(.*)#si', '\1', $header);
  1018       else if (preg_match('#^bcc:#si', $header))
   752 			}
  1019       {
   753 			else if (preg_match('#^bcc:#si', $header))
  1020         $bcc = preg_replace('#^bcc:(.*)#si', '\1', $header);
   754 			{
  1021         $header = '';
   755 				$bcc = preg_replace('#^bcc:(.*)#si', '\1', $header);
  1022       }
   756 				$header = '';
  1023       $headers .= ($header != '') ? $header . "\r\n" : '';
   757 			}
  1024     }
   758 			$headers .= ($header != '') ? $header . "\r\n" : '';
  1025 
   759 		}
  1026     $headers = chop($headers);
   760 
  1027     $cc = explode(', ', $cc);
   761 		$headers = chop($headers);
  1028     $bcc = explode(', ', $bcc);
   762 		$cc = explode(', ', $cc);
  1029   }
   763 		$bcc = explode(', ', $bcc);
  1030 
   764 	}
  1031   if (trim($subject) == '')
   765 
  1032   {
   766 	if (trim($subject) == '')
  1033     die_friendly(GENERAL_ERROR, "No email Subject specified");
   767 	{
  1034   }
   768 		die_friendly(GENERAL_ERROR, "No email Subject specified");
  1035 
   769 	}
  1036   if (trim($message) == '')
   770 
  1037   {
   771 	if (trim($message) == '')
  1038     die_friendly(GENERAL_ERROR, "Email message was blank");
   772 	{
  1039   }
   773 		die_friendly(GENERAL_ERROR, "Email message was blank");
  1040 
   774 	}
       
   775   
       
   776   // setup SMTP
  1041   // setup SMTP
   777   $host = getConfig('smtp_server');
  1042   $host = getConfig('smtp_server');
   778   if ( empty($host) )
  1043   if ( empty($host) )
   779     return 'No smtp_host in config';
  1044     return 'No smtp_host in config';
   780   if ( strstr($host, ':' ) )
  1045   if ( strstr($host, ':' ) )
   786   else
  1051   else
   787   {
  1052   {
   788     $smtp_host = $host;
  1053     $smtp_host = $host;
   789     $port = 25;
  1054     $port = 25;
   790   }
  1055   }
   791   
  1056 
   792   $smtp_user = getConfig('smtp_user');
  1057   $smtp_user = getConfig('smtp_user');
   793   $smtp_pass = getConfig('smtp_password');
  1058   $smtp_pass = getConfig('smtp_password');
   794   
  1059 
   795 	// Ok we have error checked as much as we can to this point let's get on
  1060   // Ok we have error checked as much as we can to this point let's get on
   796 	// it already.
  1061   // it already.
   797 	if( !$socket = @fsockopen($smtp_host, $port, $errno, $errstr, 20) )
  1062   if( !$socket = @fsockopen($smtp_host, $port, $errno, $errstr, 20) )
   798 	{
  1063   {
   799 		die_friendly(GENERAL_ERROR, "Could not connect to smtp host : $errno : $errstr");
  1064     die_friendly(GENERAL_ERROR, "Could not connect to smtp host : $errno : $errstr");
   800 	}
  1065   }
   801 
  1066 
   802 	// Wait for reply
  1067   // Wait for reply
   803 	smtp_get_response($socket, "220", __LINE__);
  1068   smtp_get_response($socket, "220", __LINE__);
   804 
  1069 
   805 	// Do we want to use AUTH?, send RFC2554 EHLO, else send RFC821 HELO
  1070   // Do we want to use AUTH?, send RFC2554 EHLO, else send RFC821 HELO
   806 	// This improved as provided by SirSir to accomodate
  1071   // This improved as provided by SirSir to accomodate
   807 	if( !empty($smtp_user) && !empty($smtp_pass) )
  1072   if( !empty($smtp_user) && !empty($smtp_pass) )
   808 	{ 
  1073   {
   809 		enano_fputs($socket, "EHLO " . $smtp_host . "\r\n");
  1074     enano_fputs($socket, "EHLO " . $smtp_host . "\r\n");
   810 		smtp_get_response($socket, "250", __LINE__);
  1075     smtp_get_response($socket, "250", __LINE__);
   811 
  1076 
   812 		enano_fputs($socket, "AUTH LOGIN\r\n");
  1077     enano_fputs($socket, "AUTH LOGIN\r\n");
   813 		smtp_get_response($socket, "334", __LINE__);
  1078     smtp_get_response($socket, "334", __LINE__);
   814 
  1079 
   815 		enano_fputs($socket, base64_encode($smtp_user) . "\r\n");
  1080     enano_fputs($socket, base64_encode($smtp_user) . "\r\n");
   816 		smtp_get_response($socket, "334", __LINE__);
  1081     smtp_get_response($socket, "334", __LINE__);
   817 
  1082 
   818 		enano_fputs($socket, base64_encode($smtp_pass) . "\r\n");
  1083     enano_fputs($socket, base64_encode($smtp_pass) . "\r\n");
   819 		smtp_get_response($socket, "235", __LINE__);
  1084     smtp_get_response($socket, "235", __LINE__);
   820 	}
  1085   }
   821 	else
  1086   else
   822 	{
  1087   {
   823 		enano_fputs($socket, "HELO " . $smtp_host . "\r\n");
  1088     enano_fputs($socket, "HELO " . $smtp_host . "\r\n");
   824 		smtp_get_response($socket, "250", __LINE__);
  1089     smtp_get_response($socket, "250", __LINE__);
   825 	}
  1090   }
   826 
  1091 
   827 	// From this point onward most server response codes should be 250
  1092   // From this point onward most server response codes should be 250
   828 	// Specify who the mail is from....
  1093   // Specify who the mail is from....
   829 	enano_fputs($socket, "MAIL FROM: <" . getConfig('contact_email') . ">\r\n");
  1094   enano_fputs($socket, "MAIL FROM: <" . getConfig('contact_email') . ">\r\n");
   830 	smtp_get_response($socket, "250", __LINE__);
  1095   smtp_get_response($socket, "250", __LINE__);
   831 
  1096 
   832 	// Specify each user to send to and build to header.
  1097   // Specify each user to send to and build to header.
   833 	$to_header = '';
  1098   $to_header = '';
   834 
  1099 
   835 	// Add an additional bit of error checking to the To field.
  1100   // Add an additional bit of error checking to the To field.
   836 	$mail_to = (trim($mail_to) == '') ? 'Undisclosed-recipients:;' : trim($mail_to);
  1101   $mail_to = (trim($mail_to) == '') ? 'Undisclosed-recipients:;' : trim($mail_to);
   837 	if (preg_match('#[^ ]+\@[^ ]+#', $mail_to))
  1102   if (preg_match('#[^ ]+\@[^ ]+#', $mail_to))
   838 	{
  1103   {
   839 		enano_fputs($socket, "RCPT TO: <$mail_to>\r\n");
  1104     enano_fputs($socket, "RCPT TO: <$mail_to>\r\n");
   840 		smtp_get_response($socket, "250", __LINE__);
  1105     smtp_get_response($socket, "250", __LINE__);
   841 	}
  1106   }
   842 
  1107 
   843 	// Ok now do the CC and BCC fields...
  1108   // Ok now do the CC and BCC fields...
   844 	@reset($bcc);
  1109   @reset($bcc);
   845 	while(list(, $bcc_address) = each($bcc))
  1110   while(list(, $bcc_address) = each($bcc))
   846 	{
  1111   {
   847 		// Add an additional bit of error checking to bcc header...
  1112     // Add an additional bit of error checking to bcc header...
   848 		$bcc_address = trim($bcc_address);
  1113     $bcc_address = trim($bcc_address);
   849 		if (preg_match('#[^ ]+\@[^ ]+#', $bcc_address))
  1114     if (preg_match('#[^ ]+\@[^ ]+#', $bcc_address))
   850 		{
  1115     {
   851 			enano_fputs($socket, "RCPT TO: <$bcc_address>\r\n");
  1116       enano_fputs($socket, "RCPT TO: <$bcc_address>\r\n");
   852 			smtp_get_response($socket, "250", __LINE__);
  1117       smtp_get_response($socket, "250", __LINE__);
   853 		}
  1118     }
   854 	}
  1119   }
   855 
  1120 
   856 	@reset($cc);
  1121   @reset($cc);
   857 	while(list(, $cc_address) = each($cc))
  1122   while(list(, $cc_address) = each($cc))
   858 	{
  1123   {
   859 		// Add an additional bit of error checking to cc header
  1124     // Add an additional bit of error checking to cc header
   860 		$cc_address = trim($cc_address);
  1125     $cc_address = trim($cc_address);
   861 		if (preg_match('#[^ ]+\@[^ ]+#', $cc_address))
  1126     if (preg_match('#[^ ]+\@[^ ]+#', $cc_address))
   862 		{
  1127     {
   863 			enano_fputs($socket, "RCPT TO: <$cc_address>\r\n");
  1128       enano_fputs($socket, "RCPT TO: <$cc_address>\r\n");
   864 			smtp_get_response($socket, "250", __LINE__);
  1129       smtp_get_response($socket, "250", __LINE__);
   865 		}
  1130     }
   866 	}
  1131   }
   867 
  1132 
   868 	// Ok now we tell the server we are ready to start sending data
  1133   // Ok now we tell the server we are ready to start sending data
   869 	enano_fputs($socket, "DATA\r\n");
  1134   enano_fputs($socket, "DATA\r\n");
   870 
  1135 
   871 	// This is the last response code we look for until the end of the message.
  1136   // This is the last response code we look for until the end of the message.
   872 	smtp_get_response($socket, "354", __LINE__);
  1137   smtp_get_response($socket, "354", __LINE__);
   873 
  1138 
   874 	// Send the Subject Line...
  1139   // Send the Subject Line...
   875 	enano_fputs($socket, "Subject: $subject\r\n");
  1140   enano_fputs($socket, "Subject: $subject\r\n");
   876 
  1141 
   877 	// Now the To Header.
  1142   // Now the To Header.
   878 	enano_fputs($socket, "To: $mail_to\r\n");
  1143   enano_fputs($socket, "To: $mail_to\r\n");
   879 
  1144 
   880 	// Now any custom headers....
  1145   // Now any custom headers....
   881 	enano_fputs($socket, "$headers\r\n\r\n");
  1146   enano_fputs($socket, "$headers\r\n\r\n");
   882 
  1147 
   883 	// Ok now we are ready for the message...
  1148   // Ok now we are ready for the message...
   884 	enano_fputs($socket, "$message\r\n");
  1149   enano_fputs($socket, "$message\r\n");
   885 
  1150 
   886 	// Ok the all the ingredients are mixed in let's cook this puppy...
  1151   // Ok the all the ingredients are mixed in let's cook this puppy...
   887 	enano_fputs($socket, ".\r\n");
  1152   enano_fputs($socket, ".\r\n");
   888 	smtp_get_response($socket, "250", __LINE__);
  1153   smtp_get_response($socket, "250", __LINE__);
   889 
  1154 
   890 	// Now tell the server we are done and close the socket...
  1155   // Now tell the server we are done and close the socket...
   891 	enano_fputs($socket, "QUIT\r\n");
  1156   enano_fputs($socket, "QUIT\r\n");
   892 	fclose($socket);
  1157   fclose($socket);
   893 
  1158 
   894 	return TRUE;
  1159   return TRUE;
   895 }
  1160 }
   896 
  1161 
   897 /**
  1162 /**
   898  * Tell which version of Enano we're running.
  1163  * Tell which version of Enano we're running.
   899  * @param bool $long if true, uses English version names (e.g. alpha, beta, release candidate). If false (default) uses abbreviations (1.0a1, 1.0b3, 1.0RC2, etc.)
  1164  * @param bool $long if true, uses English version names (e.g. alpha, beta, release candidate). If false (default) uses abbreviations (1.0a1, 1.0b3, 1.0RC2, etc.)
   916     $r = ( $long ) ? $r . $nightlylong : $r . '-nightly-' . $nightlytag;
  1181     $r = ( $long ) ? $r . $nightlylong : $r . '-nightly-' . $nightlytag;
   917   }
  1182   }
   918   return $r;
  1183   return $r;
   919 }
  1184 }
   920 
  1185 
       
  1186 /**
       
  1187  * What kinda sh** was I thinking when I wrote this. Deprecated.
       
  1188  */
       
  1189 
   921 function _dualurlenc($t) {
  1190 function _dualurlenc($t) {
   922   return rawurlencode(rawurlencode($t));
  1191   return rawurlencode(rawurlencode($t));
   923 }
  1192 }
   924   
  1193 
       
  1194 /**
       
  1195  * Badly named function to send back eval'able Javascript code with an error message. Deprecated, use JSON instead.
       
  1196  * @param string Message to send
       
  1197  */
       
  1198 
   925 function _die($t) {
  1199 function _die($t) {
   926   $_ob = 'document.getElementById("ajaxEditContainer").innerHTML = unescape(\'' . rawurlencode('' . $t . '') . '\')';
  1200   $_ob = 'document.getElementById("ajaxEditContainer").innerHTML = unescape(\'' . rawurlencode('' . $t . '') . '\')';
   927   die($_ob);
  1201   die($_ob);
   928 }
  1202 }
       
  1203 
       
  1204 /**
       
  1205  * Same as _die(), but sends an SQL backtrace with the error message, and doesn't halt execution.
       
  1206  * @param string Message to send
       
  1207  */
   929 
  1208 
   930 function jsdie($text) {
  1209 function jsdie($text) {
   931   global $db, $session, $paths, $template, $plugins; // Common objects
  1210   global $db, $session, $paths, $template, $plugins; // Common objects
   932   $text = rawurlencode($text . "\n\nSQL Backtrace:\n" . $db->sql_backtrace());
  1211   $text = rawurlencode($text . "\n\nSQL Backtrace:\n" . $db->sql_backtrace());
   933   echo 'document.getElementById("ajaxEditContainer").innerHTML = unescape(\''.$text.'\');';
  1212   echo 'document.getElementById("ajaxEditContainer").innerHTML = unescape(\''.$text.'\');';
   934 }
  1213 }
   935 
  1214 
   936 // HTML sanitizing function - written by Kallahar
       
   937 // Original function at: http://quickwired.com/kallahar/smallprojects/php_xss_filter_function.php
       
   938 
       
   939 // UNUSED - todo: remove this in gold or put it to use
       
   940 
       
   941 function RemoveXSS($val) {
       
   942   // remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
       
   943   // this prevents some character re-spacing such as <java\0script>
       
   944   // note that you have to handle splits with \n, \r, and \t later since they *are* allowed in some inputs
       
   945   $val = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $val);
       
   946   
       
   947   // straight replacements, the user should never need these since they're normal characters
       
   948   // this prevents like <IMG SRC=&#X40&#X61&#X76&#X61&#X73&#X63&#X72&#X69&#X70&#X74&#X3A&#X61&#X6C&#X65&#X72&#X74&#X28&#X27&#X58&#X53&#X53&#X27&#X29>
       
   949   $search  = 'abcdefghijklmnopqrstuvwxyz';
       
   950   $search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
       
   951   $search .= '1234567890!@#$%^&*()';
       
   952   $search .= '~`";:?+/={}[]-_|\'\\';
       
   953   for ($i = 0; $i < strlen($search); $i++) {
       
   954     // ;? matches the ;, which is optional
       
   955     // 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
       
   956   
       
   957     // &#x0040 @ search for the hex values
       
   958     $val = preg_replace('/(&#[x|X]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
       
   959     // &#00064 @ 0{0,7} matches '0' zero to seven times
       
   960     $val = preg_replace('/(&#0{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
       
   961   }
       
   962   
       
   963   // now the only remaining whitespace attacks are \t, \n, and \r
       
   964   $ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'meta', 'xml', 'blink', 'link', 'script', 'embed', 'object', 'iframe', 'frame', 'frameset', 'ilayer', 'layer', 'bgsound', 'title', 'base');
       
   965   $ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
       
   966   $ra = array_merge($ra1, $ra2);
       
   967   
       
   968   $found = true; // keep replacing as long as the previous round replaced something
       
   969   while ($found == true) {
       
   970     $val_before = $val;
       
   971     for ($i = 0; $i < sizeof($ra); $i++) {
       
   972       $pattern = '/';
       
   973       for ($j = 0; $j < strlen($ra[$i]); $j++) {
       
   974         if ($j > 0) {
       
   975           $pattern .= '(';
       
   976           $pattern .= '(&#[x|X]0{0,8}([9][a][b]);?)?';
       
   977           $pattern .= '|(&#0{0,8}([9][10][13]);?)?';
       
   978           $pattern .= ')?';
       
   979         }
       
   980         $pattern .= $ra[$i][$j];
       
   981       }
       
   982       $pattern .= '/i';
       
   983       $replacement = substr($ra[$i], 0, 2).'<b></b>'.substr($ra[$i], 2); // add in <> to nerf the tag
       
   984       $val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
       
   985       if ($val_before == $val) {
       
   986         // no replacements were made, so exit the loop
       
   987         $found = false;
       
   988       }
       
   989     }
       
   990   }
       
   991   return $val;
       
   992 }
       
   993 
       
   994 /**
  1215 /**
   995  * Capitalizes the first letter of a string
  1216  * Capitalizes the first letter of a string
   996  * @param $text string the text to be transformed
  1217  * @param $text string the text to be transformed
   997  * @return string
  1218  * @return string
   998  */
  1219  */
   999  
  1220 
  1000 function capitalize_first_letter($text)
  1221 function capitalize_first_letter($text)
  1001 {
  1222 {
  1002   return strtoupper(substr($text, 0, 1)) . substr($text, 1);
  1223   return strtoupper(substr($text, 0, 1)) . substr($text, 1);
  1003 }
  1224 }
  1004 
  1225 
  1006  * Checks if a value in a bitfield is on or off
  1227  * Checks if a value in a bitfield is on or off
  1007  * @param $bitfield int the bit-field value
  1228  * @param $bitfield int the bit-field value
  1008  * @param $value int the value to switch off
  1229  * @param $value int the value to switch off
  1009  * @return bool
  1230  * @return bool
  1010  */
  1231  */
  1011  
  1232 
  1012 function is_bit($bitfield, $value)
  1233 function is_bit($bitfield, $value)
  1013 {
  1234 {
  1014   return ( $bitfield & $value ) ? true : false;
  1235   return ( $bitfield & $value ) ? true : false;
  1015 }
  1236 }
  1016 
  1237 
  1017 /**
  1238 /**
  1018  * Trims spaces/newlines from the beginning and end of a string
  1239  * Trims spaces/newlines from the beginning and end of a string
  1019  * @param $text the text to process
  1240  * @param $text the text to process
  1020  * @return string
  1241  * @return string
  1021  */
  1242  */
  1022  
  1243 
  1023 function trim_spaces($text)
  1244 function trim_spaces($text)
  1024 {
  1245 {
  1025   $d = true;
  1246   $d = true;
  1026   while($d)
  1247   while($d)
  1027   {
  1248   {
  1038  * Enano-ese equivalent of str_split() which is only found in PHP5
  1259  * Enano-ese equivalent of str_split() which is only found in PHP5
  1039  * @param $text string the text to split
  1260  * @param $text string the text to split
  1040  * @param $inc int size of each block
  1261  * @param $inc int size of each block
  1041  * @return array
  1262  * @return array
  1042  */
  1263  */
  1043  
  1264 
  1044 function enano_str_split($text, $inc = 1)
  1265 function enano_str_split($text, $inc = 1)
  1045 {
  1266 {
  1046   if($inc < 1) 
  1267   if($inc < 1)
  1047   {
  1268   {
  1048     return false;
  1269     return false;
  1049   }
  1270   }
  1050   if($inc >= strlen($text))
  1271   if($inc >= strlen($text))
  1051   {
  1272   {
  1076   return $ret;
  1297   return $ret;
  1077 }
  1298 }
  1078 
  1299 
  1079 /**
  1300 /**
  1080  * Generates and/or prints a human-readable backtrace
  1301  * Generates and/or prints a human-readable backtrace
  1081  * @param bool $return - if true, this function returns a string, otherwise returns null
  1302  * @param bool $return - if true, this function returns a string, otherwise returns null and prints the backtrace
  1082  * @return mixed
  1303  * @return mixed
  1083  */
  1304  */
  1084  
  1305 
  1085 function enano_debug_print_backtrace($return = false)
  1306 function enano_debug_print_backtrace($return = false)
  1086 {
  1307 {
  1087   ob_start();
  1308   ob_start();
  1088   echo '<pre>';
  1309   echo '<pre>';
  1089   if ( function_exists('debug_print_backtrace') )
  1310   if ( function_exists('debug_print_backtrace') )
  1107  * @param string $text the text to encode
  1328  * @param string $text the text to encode
  1108  * @param optional string $prefix text before each hex character
  1329  * @param optional string $prefix text before each hex character
  1109  * @param optional string $suffix text after each hex character
  1330  * @param optional string $suffix text after each hex character
  1110  * @return string
  1331  * @return string
  1111  */
  1332  */
  1112  
  1333 
  1113 function hexencode($text, $prefix = '%', $suffix = '')
  1334 function hexencode($text, $prefix = '%', $suffix = '')
  1114 {
  1335 {
  1115   $arr = enano_str_split($text);
  1336   $arr = enano_str_split($text);
  1116   $r = '';
  1337   $r = '';
  1117   foreach($arr as $a)
  1338   foreach($arr as $a)
  1125 
  1346 
  1126 /**
  1347 /**
  1127  * Enano-ese equivalent of get_magic_quotes_gpc()
  1348  * Enano-ese equivalent of get_magic_quotes_gpc()
  1128  * @return bool
  1349  * @return bool
  1129  */
  1350  */
  1130  
  1351 
  1131 function enano_get_magic_quotes_gpc()
  1352 function enano_get_magic_quotes_gpc()
  1132 {
  1353 {
  1133   if(function_exists('get_magic_quotes_gpc'))
  1354   if(function_exists('get_magic_quotes_gpc'))
  1134   {
  1355   {
  1135     return ( get_magic_quotes_gpc() == 1 );
  1356     return ( get_magic_quotes_gpc() == 1 );
  1143 /**
  1364 /**
  1144  * Recursive stripslashes()
  1365  * Recursive stripslashes()
  1145  * @param array
  1366  * @param array
  1146  * @return array
  1367  * @return array
  1147  */
  1368  */
  1148  
  1369 
  1149 function stripslashes_recurse($arr)
  1370 function stripslashes_recurse($arr)
  1150 {
  1371 {
  1151   foreach($arr as $k => $xxxx)
  1372   foreach($arr as $k => $xxxx)
  1152   {
  1373   {
  1153     $val =& $arr[$k];
  1374     $val =& $arr[$k];
  1162 /**
  1383 /**
  1163  * Recursive function to remove all NUL bytes from a string
  1384  * Recursive function to remove all NUL bytes from a string
  1164  * @param array
  1385  * @param array
  1165  * @return array
  1386  * @return array
  1166  */
  1387  */
  1167  
  1388 
  1168 function strip_nul_chars($arr)
  1389 function strip_nul_chars($arr)
  1169 {
  1390 {
  1170   foreach($arr as $k => $xxxx_unused)
  1391   foreach($arr as $k => $xxxx_unused)
  1171   {
  1392   {
  1172     $val =& $arr[$k];
  1393     $val =& $arr[$k];
  1177   }
  1398   }
  1178   return $arr;
  1399   return $arr;
  1179 }
  1400 }
  1180 
  1401 
  1181 /**
  1402 /**
  1182  * If magic_quotes_gpc is on, calls stripslashes() on everything in $_GET/$_POST/$_COOKIE
  1403  * If magic_quotes_gpc is on, calls stripslashes() on everything in $_GET/$_POST/$_COOKIE. Also strips any NUL characters from incoming requests, as these are typically malicious.
  1183  * @ignore - this doesn't work too well in my tests
  1404  * @ignore - this doesn't work too well in my tests
  1184  * @todo port version from the PHP manual
  1405  * @todo port version from the PHP manual
  1185  * @return void
  1406  * @return void
  1186  */
  1407  */
  1187 function strip_magic_quotes_gpc()
  1408 function strip_magic_quotes_gpc()
  1199   $_REQUEST = strip_nul_chars($_REQUEST);
  1420   $_REQUEST = strip_nul_chars($_REQUEST);
  1200 }
  1421 }
  1201 
  1422 
  1202 /**
  1423 /**
  1203  * A very basic single-character compression algorithm for binary strings/bitfields
  1424  * A very basic single-character compression algorithm for binary strings/bitfields
  1204  * @param string $bits the text to compress
  1425  * @param string $bits the text to compress, should be only 1s and 0s
  1205  * @return string
  1426  * @return string
  1206  */
  1427  */
  1207  
  1428 
  1208 function compress_bitfield($bits)
  1429 function compress_bitfield($bits)
  1209 {
  1430 {
  1210   $crc32 = crc32($bits);
  1431   $crc32 = crc32($bits);
  1211   $bits .= '0';
  1432   $bits .= '0';
  1212   $start_pos = 0;
  1433   $start_pos = 0;
  1270 /**
  1491 /**
  1271  * Uncompresses a bitfield compressed with compress_bitfield()
  1492  * Uncompresses a bitfield compressed with compress_bitfield()
  1272  * @param string $bits the compressed bitfield
  1493  * @param string $bits the compressed bitfield
  1273  * @return string the uncompressed, original (we hope) bitfield OR bool false on error
  1494  * @return string the uncompressed, original (we hope) bitfield OR bool false on error
  1274  */
  1495  */
  1275  
  1496 
  1276 function uncompress_bitfield($bits)
  1497 function uncompress_bitfield($bits)
  1277 {
  1498 {
  1278   if(substr($bits, 0, 4) != 'cbf:')
  1499   if(substr($bits, 0, 4) != 'cbf:')
  1279   {
  1500   {
  1280     echo __FUNCTION__.'(): ERROR: Invalid stream';
  1501     echo __FUNCTION__.'(): ERROR: Invalid stream';
  1350       'default'=>$def,
  1571       'default'=>$def,
  1351       'extra'=>$extra,
  1572       'extra'=>$extra,
  1352       );
  1573       );
  1353     $collist[] = $field;
  1574     $collist[] = $field;
  1354   }
  1575   }
  1355   
  1576 
  1356   if ( $structure )
  1577   if ( $structure )
  1357   {
  1578   {
  1358     $db->sql_query('SET SQL_QUOTE_SHOW_CREATE = 0;');
  1579     $db->sql_query('SET SQL_QUOTE_SHOW_CREATE = 0;');
  1359     $struct = $db->sql_query('SHOW CREATE TABLE '.$table.';');
  1580     $struct = $db->sql_query('SHOW CREATE TABLE '.$table.';');
  1360     if ( !$struct )
  1581     if ( !$struct )
  1380         $struct_arr[$i] = preg_replace('/^([\s]*)/', ' ', $leg);
  1601         $struct_arr[$i] = preg_replace('/^([\s]*)/', ' ', $leg);
  1381       }
  1602       }
  1382       $struct = implode("", $struct_arr);
  1603       $struct = implode("", $struct_arr);
  1383     }
  1604     }
  1384   }
  1605   }
  1385   
  1606 
  1386   // Structuring complete
  1607   // Structuring complete
  1387   if($data)
  1608   if($data)
  1388   {
  1609   {
  1389     $datq = $db->sql_query('SELECT * FROM '.$table.';');
  1610     $datq = $db->sql_query('SELECT * FROM '.$table.';');
  1390     if(!$datq)
  1611     if(!$datq)
  1439 
  1660 
  1440 /**
  1661 /**
  1441  * Encodes a string value for use in an INSERT statement for given column type $type.
  1662  * Encodes a string value for use in an INSERT statement for given column type $type.
  1442  * @access private
  1663  * @access private
  1443  */
  1664  */
  1444  
  1665 
  1445 function mysql_encode_column($input, $type)
  1666 function mysql_encode_column($input, $type)
  1446 {
  1667 {
  1447   global $db, $session, $paths, $template, $plugins; // Common objects
  1668   global $db, $session, $paths, $template, $plugins; // Common objects
  1448   // Decide whether to quote the string or not
  1669   // Decide whether to quote the string or not
  1449   if(substr($type, 0, 7) == 'varchar' || $type == 'datetime' || $type == 'text' || $type == 'tinytext' || $type == 'smalltext' || $type == 'longtext' || substr($type, 0, 4) == 'char')
  1670   if(substr($type, 0, 7) == 'varchar' || $type == 'datetime' || $type == 'text' || $type == 'tinytext' || $type == 'smalltext' || $type == 'longtext' || substr($type, 0, 4) == 'char')
  1527  * @return string cleaned HTML
  1748  * @return string cleaned HTML
  1528  */
  1749  */
  1529 
  1750 
  1530 function sanitize_html($html, $filter_php = true)
  1751 function sanitize_html($html, $filter_php = true)
  1531 {
  1752 {
  1532   
  1753 
  1533   $html = preg_replace('#<([a-z]+)([\s]+)([^>]+?)'.htmlalternatives('javascript:').'(.+?)>(.*?)</\\1>#is', '&lt;\\1\\2\\3javascript:\\59&gt;\\60&lt;/\\1&gt;', $html);
  1754   $html = preg_replace('#<([a-z]+)([\s]+)([^>]+?)'.htmlalternatives('javascript:').'(.+?)>(.*?)</\\1>#is', '&lt;\\1\\2\\3javascript:\\59&gt;\\60&lt;/\\1&gt;', $html);
  1534   $html = preg_replace('#<([a-z]+)([\s]+)([^>]+?)'.htmlalternatives('javascript:').'(.+?)>#is', '&lt;\\1\\2\\3javascript:\\59&gt;', $html);
  1755   $html = preg_replace('#<([a-z]+)([\s]+)([^>]+?)'.htmlalternatives('javascript:').'(.+?)>#is', '&lt;\\1\\2\\3javascript:\\59&gt;', $html);
  1535   
  1756 
  1536   if($filter_php)
  1757   if($filter_php)
  1537     $html = str_replace(
  1758     $html = str_replace(
  1538       Array('<?php',    '<?',    '<%',    '?>',    '%>'),
  1759       Array('<?php',    '<?',    '<%',    '?>',    '%>'),
  1539       Array('&lt;?php', '&lt;?', '&lt;%', '?&gt;', '%&gt;'),
  1760       Array('&lt;?php', '&lt;?', '&lt;%', '?&gt;', '%&gt;'),
  1540       $html);
  1761       $html);
  1541   
  1762 
  1542   $tag_whitelist = array_keys ( setupAttributeWhitelist() );
  1763   $tag_whitelist = array_keys ( setupAttributeWhitelist() );
  1543   if ( !$filter_php )
  1764   if ( !$filter_php )
  1544     $tag_whitelist[] = '?php';
  1765     $tag_whitelist[] = '?php';
  1545   $len = strlen($html);
  1766   $len = strlen($html);
  1546   $in_quote = false;
  1767   $in_quote = false;
  1563     {
  1784     {
  1564       $in_quote = true;
  1785       $in_quote = true;
  1565       $quote_char = $chr;
  1786       $quote_char = $chr;
  1566     }
  1787     }
  1567     if ( $chr == '<' && !$in_tag && $next != '/' )
  1788     if ( $chr == '<' && !$in_tag && $next != '/' )
  1568     {                                          
  1789     {
  1569       // start of a tag
  1790       // start of a tag
  1570       $tag_start = $i;
  1791       $tag_start = $i;
  1571       $in_tag = true;
  1792       $in_tag = true;
  1572       $trk_name = true;
  1793       $trk_name = true;
  1573     }
  1794     }
  1574     elseif ( !$in_quote && $in_tag && $chr == '>' )
  1795     elseif ( !$in_quote && $in_tag && $chr == '>' )
  1575     {
  1796     {
  1576       $full_tag = substr($html, $tag_start, ( $i - $tag_start ) + 1 );
  1797       $full_tag = substr($html, $tag_start, ( $i - $tag_start ) + 1 );
  1577       $l = strlen($tag_name) + 2;
  1798       $l = strlen($tag_name) + 2;
  1578       $attribs_only = trim( substr($full_tag, $l, ( strlen($full_tag) - $l - 1 ) ) );
  1799       $attribs_only = trim( substr($full_tag, $l, ( strlen($full_tag) - $l - 1 ) ) );
  1579       
  1800 
  1580       // Debugging message
  1801       // Debugging message
  1581       // echo htmlspecialchars($full_tag) . '<br />';
  1802       // echo htmlspecialchars($full_tag) . '<br />';
  1582       
  1803 
  1583       if ( !in_array($tag_name, $tag_whitelist) )
  1804       if ( !in_array($tag_name, $tag_whitelist) )
  1584       {
  1805       {
  1585         // Illegal tag
  1806         // Illegal tag
  1586         //echo $tag_name . ' ';
  1807         //echo $tag_name . ' ';
  1587         
  1808 
  1588         $s = ( empty($attribs_only) ) ? '' : ' ';
  1809         $s = ( empty($attribs_only) ) ? '' : ' ';
  1589         
  1810 
  1590         $sanitized = '&lt;' . $tag_name . $s . $attribs_only . '&gt;';
  1811         $sanitized = '&lt;' . $tag_name . $s . $attribs_only . '&gt;';
  1591         
  1812 
  1592         $html = substr($html, 0, $tag_start) . $sanitized . substr($html, $i + 1);
  1813         $html = substr($html, 0, $tag_start) . $sanitized . substr($html, $i + 1);
  1593         $html = str_replace('</' . $tag_name . '>', '&lt;/' . $tag_name . '&gt;', $html);
  1814         $html = str_replace('</' . $tag_name . '>', '&lt;/' . $tag_name . '&gt;', $html);
  1594         $new_i = $tag_start + strlen($sanitized);
  1815         $new_i = $tag_start + strlen($sanitized);
  1595         
  1816 
  1596         $len = strlen($html);
  1817         $len = strlen($html);
  1597         $i = $new_i;
  1818         $i = $new_i;
  1598         
  1819 
  1599         $in_tag = false;
  1820         $in_tag = false;
  1600         $tag_name = '';
  1821         $tag_name = '';
  1601         continue;
  1822         continue;
  1602       }
  1823       }
  1603       else
  1824       else
  1604       {
  1825       {
  1605         if ( $tag_name == '?php' && !$filter_php )
  1826         if ( $tag_name == '?php' && !$filter_php )
  1606           continue;
  1827           continue;
  1607         $f = fixTagAttributes( $attribs_only, $tag_name );
  1828         $f = fixTagAttributes( $attribs_only, $tag_name );
  1608         $s = ( empty($f) ) ? '' : ' ';
  1829         $s = ( empty($f) ) ? '' : ' ';
  1609         
  1830 
  1610         $sanitized = '<' . $tag_name . $f . '>';
  1831         $sanitized = '<' . $tag_name . $f . '>';
  1611         $new_i = $tag_start + strlen($sanitized);
  1832         $new_i = $tag_start + strlen($sanitized);
  1612         
  1833 
  1613         $html = substr($html, 0, $tag_start) . $sanitized . substr($html, $i + 1);
  1834         $html = substr($html, 0, $tag_start) . $sanitized . substr($html, $i + 1);
  1614         $len = strlen($html);
  1835         $len = strlen($html);
  1615         $i = $new_i;
  1836         $i = $new_i;
  1616         
  1837 
  1617         $in_tag = false;
  1838         $in_tag = false;
  1618         $tag_name = '';
  1839         $tag_name = '';
  1619         continue;
  1840         continue;
  1620       }
  1841       }
  1621     }
  1842     }
  1627       else
  1848       else
  1628       {
  1849       {
  1629         $trk_name = false;
  1850         $trk_name = false;
  1630       }
  1851       }
  1631     }
  1852     }
  1632     
  1853 
  1633   }
  1854   }
  1634   
  1855 
  1635   // Vulnerability from ha.ckers.org/xss.html:
  1856   // Vulnerability from ha.ckers.org/xss.html:
  1636   // <script src="http://foo.com/xss.js"
  1857   // <script src="http://foo.com/xss.js"
  1637   // <
  1858   // <
  1638   // The rule is so specific because everything else will have been filtered by now
  1859   // The rule is so specific because everything else will have been filtered by now
  1639   $html = preg_replace('/<(script|iframe)(.+?)src=([^>]*)</i', '&lt;\\1\\2src=\\3&lt;', $html);
  1860   $html = preg_replace('/<(script|iframe)(.+?)src=([^>]*)</i', '&lt;\\1\\2src=\\3&lt;', $html);
  1640   
  1861 
  1641   // Unstrip comments
  1862   // Unstrip comments
  1642   $html = preg_replace('/&lt;!--([^>]*?)--&gt;/i', '', $html);
  1863   $html = preg_replace('/&lt;!--([^>]*?)--&gt;/i', '', $html);
  1643   
  1864 
  1644   return $html;
  1865   return $html;
  1645   
  1866 
  1646 }
  1867 }
  1647 
  1868 
  1648 /**
  1869 /**
  1649  * Using the same parsing code as sanitize_html(), this function adds <litewiki> tags around certain block-level elements
  1870  * Using the same parsing code as sanitize_html(), this function adds <litewiki> tags around certain block-level elements
  1650  * @param string $html The input HTML
  1871  * @param string $html The input HTML
  1651  * @return string formatted HTML
  1872  * @return string formatted HTML
  1652  */
  1873  */
  1653 
  1874 
  1654 function wikiformat_process_block($html)
  1875 function wikiformat_process_block($html)
  1655 {
  1876 {
  1656   
  1877 
  1657   $tok1 = "<litewiki>";
  1878   $tok1 = "<litewiki>";
  1658   $tok2 = "</litewiki>";
  1879   $tok2 = "</litewiki>";
  1659   
  1880 
  1660   $block_tags = array('div', 'p', 'table', 'blockquote', 'pre');
  1881   $block_tags = array('div', 'p', 'table', 'blockquote', 'pre');
  1661   
  1882 
  1662   $len = strlen($html);
  1883   $len = strlen($html);
  1663   $in_quote = false;
  1884   $in_quote = false;
  1664   $quote_char = '';
  1885   $quote_char = '';
  1665   $tag_start = 0;
  1886   $tag_start = 0;
  1666   $tag_name = '';
  1887   $tag_name = '';
  1667   $in_tag = false;
  1888   $in_tag = false;
  1668   $trk_name = false;
  1889   $trk_name = false;
  1669   
  1890 
  1670   $diag = 0;
  1891   $diag = 0;
  1671   
  1892 
  1672   $block_tagname = '';
  1893   $block_tagname = '';
  1673   $in_blocksec = 0;
  1894   $in_blocksec = 0;
  1674   $block_start = 0;
  1895   $block_start = 0;
  1675   
  1896 
  1676   for ( $i = 0; $i < $len; $i++ )
  1897   for ( $i = 0; $i < $len; $i++ )
  1677   {
  1898   {
  1678     $chr = $html{$i};
  1899     $chr = $html{$i};
  1679     $prev = ( $i == 0 ) ? '' : $html{ $i - 1 };
  1900     $prev = ( $i == 0 ) ? '' : $html{ $i - 1 };
  1680     $next = ( ( $i + 1 ) == $len ) ? '' : $html { $i + 1 };
  1901     $next = ( ( $i + 1 ) == $len ) ? '' : $html { $i + 1 };
  1681     
  1902 
  1682     // Are we inside of a quoted section?
  1903     // Are we inside of a quoted section?
  1683     if ( $in_quote && $in_tag )
  1904     if ( $in_quote && $in_tag )
  1684     {
  1905     {
  1685       if ( $quote_char == $chr && $prev != '\\' )
  1906       if ( $quote_char == $chr && $prev != '\\' )
  1686         $in_quote = false;
  1907         $in_quote = false;
  1688     elseif ( ( $chr == '"' || $chr == "'" ) && $prev != '\\' && $in_tag )
  1909     elseif ( ( $chr == '"' || $chr == "'" ) && $prev != '\\' && $in_tag )
  1689     {
  1910     {
  1690       $in_quote = true;
  1911       $in_quote = true;
  1691       $quote_char = $chr;
  1912       $quote_char = $chr;
  1692     }
  1913     }
  1693     
  1914 
  1694     if ( $chr == '<' && !$in_tag && $next == '/' )
  1915     if ( $chr == '<' && !$in_tag && $next == '/' )
  1695     {
  1916     {
  1696       // Iterate through until we've got a tag name
  1917       // Iterate through until we've got a tag name
  1697       $tag_name = '';
  1918       $tag_name = '';
  1698       $i++;
  1919       $i++;
  1719             $i += 2;
  1940             $i += 2;
  1720             // echo 'Finished wiki litewiki wraparound calc at pos: ' . $i;
  1941             // echo 'Finished wiki litewiki wraparound calc at pos: ' . $i;
  1721             $full_litewiki = substr($html, $block_start, ( $i - $block_start ));
  1942             $full_litewiki = substr($html, $block_start, ( $i - $block_start ));
  1722             $new_text = "{$tok1}{$full_litewiki}{$tok2}";
  1943             $new_text = "{$tok1}{$full_litewiki}{$tok2}";
  1723             $html = substr($html, 0, $block_start) . $new_text . substr($html, $i);
  1944             $html = substr($html, 0, $block_start) . $new_text . substr($html, $i);
  1724             
  1945 
  1725             $i += ( strlen($tok1) + strlen($tok2) ) - 1;
  1946             $i += ( strlen($tok1) + strlen($tok2) ) - 1;
  1726             $len = strlen($html);
  1947             $len = strlen($html);
  1727             
  1948 
  1728             //die('<pre>' . htmlspecialchars($html) . '</pre>');
  1949             //die('<pre>' . htmlspecialchars($html) . '</pre>');
  1729           }
  1950           }
  1730         }
  1951         }
  1731       }
  1952       }
  1732       
  1953 
  1733       $in_tag = false;
  1954       $in_tag = false;
  1734       $in_quote = false;
  1955       $in_quote = false;
  1735       $tag_name = '';
  1956       $tag_name = '';
  1736       
  1957 
  1737       continue;
  1958       continue;
  1738     }
  1959     }
  1739     else if ( $chr == '<' && !$in_tag && $next != '/' )
  1960     else if ( $chr == '<' && !$in_tag && $next != '/' )
  1740     {
  1961     {
  1741       // start of a tag
  1962       // start of a tag
  1747     {
  1968     {
  1748       if ( !in_array($tag_name, $block_tags) )
  1969       if ( !in_array($tag_name, $block_tags) )
  1749       {
  1970       {
  1750         // Inline tag - reset and go to the next one
  1971         // Inline tag - reset and go to the next one
  1751         // echo '&lt;inline ' . $tag_name . '&gt; ';
  1972         // echo '&lt;inline ' . $tag_name . '&gt; ';
  1752         
  1973 
  1753         $in_tag = false;
  1974         $in_tag = false;
  1754         $tag_name = '';
  1975         $tag_name = '';
  1755         continue;
  1976         continue;
  1756       }
  1977       }
  1757       else
  1978       else
  1766         }
  1987         }
  1767         else if ( $block_tagname == $tag_name )
  1988         else if ( $block_tagname == $tag_name )
  1768         {
  1989         {
  1769           $in_blocksec++;
  1990           $in_blocksec++;
  1770         }
  1991         }
  1771         
  1992 
  1772         $in_tag = false;
  1993         $in_tag = false;
  1773         $tag_name = '';
  1994         $tag_name = '';
  1774         continue;
  1995         continue;
  1775       }
  1996       }
  1776     }
  1997     }
  1782       else
  2003       else
  1783       {
  2004       {
  1784         $trk_name = false;
  2005         $trk_name = false;
  1785       }
  2006       }
  1786     }
  2007     }
  1787     
  2008 
  1788     // Tokenization complete
  2009     // Tokenization complete
  1789     
  2010 
  1790   }
  2011   }
  1791   
  2012 
  1792   $regex = '/' . str_replace('/', '\\/', preg_quote($tok2)) . '([\s]*)' . preg_quote($tok1) . '/is';
  2013   $regex = '/' . str_replace('/', '\\/', preg_quote($tok2)) . '([\s]*)' . preg_quote($tok1) . '/is';
  1793   // die(htmlspecialchars($regex));
  2014   // die(htmlspecialchars($regex));
  1794   $html = preg_replace($regex, '\\1', $html);
  2015   $html = preg_replace($regex, '\\1', $html);
  1795   
  2016 
  1796   return $html;
  2017   return $html;
  1797   
  2018 
  1798 }
  2019 }
  1799 
  2020 
  1800 function htmlalternatives($string)
  2021 function htmlalternatives($string)
  1801 {
  2022 {
  1802   $ret = '';
  2023   $ret = '';
  1832   $parser = $template->makeParserText($tpl_text);
  2053   $parser = $template->makeParserText($tpl_text);
  1833   $num_pages = ceil ( $num_results / $perpage );
  2054   $num_pages = ceil ( $num_results / $perpage );
  1834   $out = '';
  2055   $out = '';
  1835   $i = 0;
  2056   $i = 0;
  1836   $this_page = ceil ( $start / $perpage );
  2057   $this_page = ceil ( $start / $perpage );
  1837   
  2058 
  1838   // Build paginator
  2059   // Build paginator
  1839   $begin = '<div class="tblholder" style="display: table; margin: 10px 0 0 auto;">
  2060   $begin = '<div class="tblholder" style="display: table; margin: 10px 0 0 auto;">
  1840     <table border="0" cellspacing="1" cellpadding="4">
  2061     <table border="0" cellspacing="1" cellpadding="4">
  1841       <tr><th>Page:</th>';
  2062       <tr><th>Page:</th>';
  1842   $block = '<td class="row1" style="text-align: center;">{LINK}</td>';
  2063   $block = '<td class="row1" style="text-align: center;">{LINK}</td>';
  1848   {
  2069   {
  1849     for ( $i = 0; $i < $num_pages; $i++ )
  2070     for ( $i = 0; $i < $num_pages; $i++ )
  1850     {
  2071     {
  1851       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2072       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  1852       $offset = strval($i * $perpage);
  2073       $offset = strval($i * $perpage);
  1853       $url = sprintf($result_url, $offset);
  2074       $url = htmlspecialchars(sprintf($result_url, $offset));
  1854       $j = $i + 1;
  2075       $j = $i + 1;
  1855       $link = ( $offset == strval($start) ) ? "<b>$j</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>$j</a>";
  2076       $link = ( $offset == strval($start) ) ? "<b>$j</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>$j</a>";
  1856       $blk->assign_vars(array(
  2077       $blk->assign_vars(array(
  1857         'CLASS'=>$cls,
  2078         'CLASS'=>$cls,
  1858         'LINK'=>$link
  2079         'LINK'=>$link
  1889     $blk->assign_vars(array(
  2110     $blk->assign_vars(array(
  1890       'CLASS'=>$cls,
  2111       'CLASS'=>$cls,
  1891       'LINK'=>$link
  2112       'LINK'=>$link
  1892       ));
  2113       ));
  1893     $inner .= $blk->run();
  2114     $inner .= $blk->run();
  1894     
  2115 
  1895     // if ( !in_array(1, $list) )
  2116     // if ( !in_array(1, $list) )
  1896     // {
  2117     // {
  1897     //   $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2118     //   $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  1898     //   $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
  2119     //   $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
  1899     //   $inner .= $blk->run();
  2120     //   $inner .= $blk->run();
  1900     // }
  2121     // }
  1901     
  2122 
  1902     foreach ( $list as $i )
  2123     foreach ( $list as $i )
  1903     {
  2124     {
  1904       if ( $i == $num_pages )
  2125       if ( $i == $num_pages )
  1905         break;
  2126         break;
  1906       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2127       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  1912         'CLASS'=>$cls,
  2133         'CLASS'=>$cls,
  1913         'LINK'=>$link
  2134         'LINK'=>$link
  1914         ));
  2135         ));
  1915       $inner .= $blk->run();
  2136       $inner .= $blk->run();
  1916     }
  2137     }
  1917     
  2138 
  1918     $total = $num_pages * $perpage - $perpage;
  2139     $total = $num_pages * $perpage - $perpage;
  1919     
  2140 
  1920     if ( $this_page < $num_pages )
  2141     if ( $this_page < $num_pages )
  1921     {
  2142     {
  1922       // $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2143       // $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  1923       // $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
  2144       // $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
  1924       // $inner .= $blk->run();
  2145       // $inner .= $blk->run();
  1925     
  2146 
  1926       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2147       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  1927       $offset = strval($total);
  2148       $offset = strval($total);
  1928       $url = sprintf($result_url, $offset);
  2149       $url = sprintf($result_url, $offset);
  1929       $j = $i + 1;
  2150       $j = $i + 1;
  1930       $link = ( $offset == strval($start) ) ? "<b>Last</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Last &raquo;</a>";
  2151       $link = ( $offset == strval($start) ) ? "<b>Last</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Last &raquo;</a>";
  1932         'CLASS'=>$cls,
  2153         'CLASS'=>$cls,
  1933         'LINK'=>$link
  2154         'LINK'=>$link
  1934         ));
  2155         ));
  1935       $inner .= $blk->run();
  2156       $inner .= $blk->run();
  1936     }
  2157     }
  1937     
  2158 
  1938   }
  2159   }
  1939   
  2160 
  1940   $inner .= '<td class="row2" style="cursor: pointer;" onclick="paginator_goto(this, '.$this_page.', '.$num_pages.', '.$perpage.', unescape(\'' . rawurlencode($result_url) . '\'));">&darr;</td>';
  2161   $inner .= '<td class="row2" style="cursor: pointer;" onclick="paginator_goto(this, '.$this_page.', '.$num_pages.', '.$perpage.', unescape(\'' . rawurlencode($result_url) . '\'));">&darr;</td>';
  1941   
  2162 
  1942   $paginator = "\n$begin$inner$end\n";
  2163   $paginator = "\n$begin$inner$end\n";
  1943   $out .= $paginator;
  2164   $out .= $paginator;
  1944   
  2165 
  1945   $cls = 'row2';
  2166   $cls = 'row2';
  1946   
  2167 
  1947   if ( $row = $db->fetchrow($q) )
  2168   if ( $row = $db->fetchrow($q) )
  1948   {
  2169   {
  1949     $i = 0;
  2170     $i = 0;
  1950     $out .= $header;
  2171     $out .= $header;
  1951     do {
  2172     do {
  1962       foreach ( $row as $j => $val )
  2183       foreach ( $row as $j => $val )
  1963       {
  2184       {
  1964         if ( isset($callers[$j]) )
  2185         if ( isset($callers[$j]) )
  1965         {
  2186         {
  1966           $tmp = ( is_callable($callers[$j]) ) ? @call_user_func($callers[$j], $val, $row) : $val;
  2187           $tmp = ( is_callable($callers[$j]) ) ? @call_user_func($callers[$j], $val, $row) : $val;
  1967           
  2188 
  1968           if ( $tmp )
  2189           if ( $tmp )
  1969           {
  2190           {
  1970             $row[$j] = $tmp;
  2191             $row[$j] = $tmp;
  1971           }
  2192           }
  1972         }
  2193         }
  1975       $parser->assign_vars(array('_css_class' => $cls));
  2196       $parser->assign_vars(array('_css_class' => $cls));
  1976       $out .= $parser->run();
  2197       $out .= $parser->run();
  1977     } while ( $row = $db->fetchrow($q) );
  2198     } while ( $row = $db->fetchrow($q) );
  1978     $out .= $footer;
  2199     $out .= $footer;
  1979   }
  2200   }
  1980   
  2201 
  1981   $out .= $paginator;
  2202   $out .= $paginator;
  1982   
  2203 
  1983   return $out;
  2204   return $out;
  1984 }
  2205 }
  1985 
  2206 
  1986 /**
  2207 /**
  1987  * This is the same as paginate(), but it processes an array instead of a MySQL result resource.
  2208  * This is the same as paginate(), but it processes an array instead of a MySQL result resource.
  2001   $parser = $template->makeParserText($tpl_text);
  2222   $parser = $template->makeParserText($tpl_text);
  2002   $num_pages = ceil ( $num_results / $perpage );
  2223   $num_pages = ceil ( $num_results / $perpage );
  2003   $out = '';
  2224   $out = '';
  2004   $i = 0;
  2225   $i = 0;
  2005   $this_page = ceil ( $start / $perpage );
  2226   $this_page = ceil ( $start / $perpage );
  2006   
  2227 
  2007   // Build paginator
  2228   // Build paginator
  2008   $begin = '<div class="tblholder" style="display: table; margin: 10px 0 0 auto;">
  2229   $begin = '<div class="tblholder" style="display: table; margin: 10px 0 0 auto;">
  2009     <table border="0" cellspacing="1" cellpadding="4">
  2230     <table border="0" cellspacing="1" cellpadding="4">
  2010       <tr><th>Page:</th>';
  2231       <tr><th>Page:</th>';
  2011   $block = '<td class="row1" style="text-align: center;">{LINK}</td>';
  2232   $block = '<td class="row1" style="text-align: center;">{LINK}</td>';
  2028   {
  2249   {
  2029     for ( $i = 0; $i < $num_pages; $i++ )
  2250     for ( $i = 0; $i < $num_pages; $i++ )
  2030     {
  2251     {
  2031       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2252       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2032       $offset = strval($i * $perpage);
  2253       $offset = strval($i * $perpage);
  2033       $url = sprintf($result_url, $offset);
  2254       $url = htmlspecialchars(sprintf($result_url, $offset));
  2034       $j = $i + 1;
  2255       $j = $i + 1;
  2035       $link = ( $offset == strval($start) ) ? "<b>$j</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>$j</a>";
  2256       $link = ( $offset == strval($start) ) ? "<b>$j</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>$j</a>";
  2036       $blk->assign_vars(array(
  2257       $blk->assign_vars(array(
  2037         'CLASS'=>$cls,
  2258         'CLASS'=>$cls,
  2038         'LINK'=>$link
  2259         'LINK'=>$link
  2069     $blk->assign_vars(array(
  2290     $blk->assign_vars(array(
  2070       'CLASS'=>$cls,
  2291       'CLASS'=>$cls,
  2071       'LINK'=>$link
  2292       'LINK'=>$link
  2072       ));
  2293       ));
  2073     $inner .= $blk->run();
  2294     $inner .= $blk->run();
  2074     
  2295 
  2075     // if ( !in_array(1, $list) )
  2296     // if ( !in_array(1, $list) )
  2076     // {
  2297     // {
  2077     //   $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2298     //   $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2078     //   $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
  2299     //   $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
  2079     //   $inner .= $blk->run();
  2300     //   $inner .= $blk->run();
  2080     // }
  2301     // }
  2081     
  2302 
  2082     foreach ( $list as $i )
  2303     foreach ( $list as $i )
  2083     {
  2304     {
  2084       if ( $i == $num_pages )
  2305       if ( $i == $num_pages )
  2085         break;
  2306         break;
  2086       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2307       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2092         'CLASS'=>$cls,
  2313         'CLASS'=>$cls,
  2093         'LINK'=>$link
  2314         'LINK'=>$link
  2094         ));
  2315         ));
  2095       $inner .= $blk->run();
  2316       $inner .= $blk->run();
  2096     }
  2317     }
  2097     
  2318 
  2098     $total = $num_pages * $perpage - $perpage;
  2319     $total = $num_pages * $perpage - $perpage;
  2099     
  2320 
  2100     if ( $this_page < $num_pages )
  2321     if ( $this_page < $num_pages )
  2101     {
  2322     {
  2102       // $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2323       // $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2103       // $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
  2324       // $blk->assign_vars(array('CLASS'=>$cls,'LINK'=>'...'));
  2104       // $inner .= $blk->run();
  2325       // $inner .= $blk->run();
  2105     
  2326 
  2106       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2327       $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2107       $offset = strval($total);
  2328       $offset = strval($total);
  2108       $url = sprintf($result_url, $offset);
  2329       $url = sprintf($result_url, $offset);
  2109       $j = $i + 1;
  2330       $j = $i + 1;
  2110       $link = ( $offset == strval($start) ) ? "<b>Last</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Last &raquo;</a>";
  2331       $link = ( $offset == strval($start) ) ? "<b>Last</b>" : "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Last &raquo;</a>";
  2112         'CLASS'=>$cls,
  2333         'CLASS'=>$cls,
  2113         'LINK'=>$link
  2334         'LINK'=>$link
  2114         ));
  2335         ));
  2115       $inner .= $blk->run();
  2336       $inner .= $blk->run();
  2116     }
  2337     }
  2117     
  2338 
  2118   }
  2339   }
  2119   
  2340 
  2120   if ( $start < $total )
  2341   if ( $start < $total )
  2121   {
  2342   {
  2122     $url = sprintf($result_url, abs($start + $perpage));
  2343     $url = sprintf($result_url, abs($start + $perpage));
  2123     $link = "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Next &raquo;</a>";
  2344     $link = "<a href=".'"'."$url".'"'." style='text-decoration: none;'>Next &raquo;</a>";
  2124     $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2345     $cls = ( $cls == 'row1' ) ? 'row2' : 'row1';
  2126       'CLASS'=>$cls,
  2347       'CLASS'=>$cls,
  2127       'LINK'=>$link
  2348       'LINK'=>$link
  2128       ));
  2349       ));
  2129     $inner .= $blk->run();
  2350     $inner .= $blk->run();
  2130   }
  2351   }
  2131   
  2352 
  2132   $inner .= '<td class="row2" style="cursor: pointer;" onclick="paginator_goto(this, '.$this_page.', '.$num_pages.', '.$perpage.', unescape(\'' . rawurlencode($result_url) . '\'));">&darr;</td>';
  2353   $inner .= '<td class="row2" style="cursor: pointer;" onclick="paginator_goto(this, '.$this_page.', '.$num_pages.', '.$perpage.', unescape(\'' . rawurlencode($result_url) . '\'));">&darr;</td>';
  2133   
  2354 
  2134   $paginator = "\n$begin$inner$end\n";
  2355   $paginator = "\n$begin$inner$end\n";
  2135   if ( $total > 1 )
  2356   if ( $total > 1 )
  2136     $out .= $paginator;
  2357     $out .= $paginator;
  2137   
  2358 
  2138   $cls = 'row2';
  2359   $cls = 'row2';
  2139   
  2360 
  2140   if ( sizeof($q) > 0 )
  2361   if ( sizeof($q) > 0 )
  2141   {
  2362   {
  2142     $i = 0;
  2363     $i = 0;
  2143     $out .= $header;
  2364     $out .= $header;
  2144     foreach ( $q as $val ) {
  2365     foreach ( $q as $val ) {
  2153       }
  2374       }
  2154       $out .= $val;
  2375       $out .= $val;
  2155     }
  2376     }
  2156     $out .= $footer;
  2377     $out .= $footer;
  2157   }
  2378   }
  2158   
  2379 
  2159   if ( $total > 1 )
  2380   if ( $total > 1 )
  2160     $out .= $paginator;
  2381     $out .= $paginator;
  2161   
  2382 
  2162   return $out;
  2383   return $out;
  2163 }
  2384 }
  2164 
  2385 
  2165 /** 
  2386 /**
  2166  * Enano version of fputs for debugging
  2387  * Enano version of fputs for debugging
  2167  */
  2388  */
  2168 
  2389 
  2169 function enano_fputs($socket, $data)
  2390 function enano_fputs($socket, $data)
  2170 {
  2391 {
  2181  * @return string Cleaned text
  2402  * @return string Cleaned text
  2182  */
  2403  */
  2183 
  2404 
  2184 function sanitize_page_id($page_id)
  2405 function sanitize_page_id($page_id)
  2185 {
  2406 {
  2186   
  2407 
  2187   // Remove character escapes
  2408   // Remove character escapes
  2188   $page_id = dirtify_page_id($page_id);
  2409   $page_id = dirtify_page_id($page_id);
  2189   
  2410 
  2190   $pid_clean = preg_replace('/[\w\.\/:;\(\)@\[\]_-]/', 'X', $page_id);
  2411   $pid_clean = preg_replace('/[\w\.\/:;\(\)@\[\]_-]/', 'X', $page_id);
  2191   $pid_dirty = enano_str_split($pid_clean, 1);
  2412   $pid_dirty = enano_str_split($pid_clean, 1);
  2192   
  2413 
  2193   foreach ( $pid_dirty as $id => $char )
  2414   foreach ( $pid_dirty as $id => $char )
  2194   {
  2415   {
  2195     if ( $char == 'X' )
  2416     if ( $char == 'X' )
  2196       continue;
  2417       continue;
  2197     $cid = ord($char);
  2418     $cid = ord($char);
  2201     {
  2422     {
  2202       $cid = strtoupper("0$cid");
  2423       $cid = strtoupper("0$cid");
  2203     }
  2424     }
  2204     $pid_dirty[$id] = ".$cid";
  2425     $pid_dirty[$id] = ".$cid";
  2205   }
  2426   }
  2206   
  2427 
  2207   $pid_chars = enano_str_split($page_id, 1);
  2428   $pid_chars = enano_str_split($page_id, 1);
  2208   $page_id_cleaned = '';
  2429   $page_id_cleaned = '';
  2209   
  2430 
  2210   foreach ( $pid_chars as $id => $char )
  2431   foreach ( $pid_chars as $id => $char )
  2211   {
  2432   {
  2212     if ( $pid_dirty[$id] == 'X' )
  2433     if ( $pid_dirty[$id] == 'X' )
  2213       $page_id_cleaned .= $char;
  2434       $page_id_cleaned .= $char;
  2214     else
  2435     else
  2215       $page_id_cleaned .= $pid_dirty[$id];
  2436       $page_id_cleaned .= $pid_dirty[$id];
  2216   }
  2437   }
  2217   
  2438 
  2218   // global $mime_types;
  2439   // global $mime_types;
  2219           
  2440 
  2220   // $exts = array_keys($mime_types);
  2441   // $exts = array_keys($mime_types);
  2221   // $exts = '(' . implode('|', $exts) . ')';
  2442   // $exts = '(' . implode('|', $exts) . ')';
  2222   
  2443 
  2223   // $page_id_cleaned = preg_replace('/\.2e' . $exts . '$/', '.\\1', $page_id_cleaned);
  2444   // $page_id_cleaned = preg_replace('/\.2e' . $exts . '$/', '.\\1', $page_id_cleaned);
  2224   
  2445 
  2225   return $page_id_cleaned;
  2446   return $page_id_cleaned;
  2226 }
  2447 }
  2227 
  2448 
  2228 /**
  2449 /**
  2229  * Removes character escapes in a page ID string
  2450  * Removes character escapes in a page ID string
  2232  */
  2453  */
  2233 
  2454 
  2234 function dirtify_page_id($page_id)
  2455 function dirtify_page_id($page_id)
  2235 {
  2456 {
  2236   global $db, $session, $paths, $template, $plugins; // Common objects
  2457   global $db, $session, $paths, $template, $plugins; // Common objects
  2237   // First, replace spaces with underscores  
  2458   // First, replace spaces with underscores
  2238   $page_id = str_replace(' ', '_', $page_id);
  2459   $page_id = str_replace(' ', '_', $page_id);
  2239   
  2460 
  2240   // Exception for userpages for IP addresses
  2461   // Exception for userpages for IP addresses
  2241   if ( preg_match('/^' . preg_quote($paths->nslist['User']) . '/', $page_id) )
  2462   if ( preg_match('/^' . preg_quote($paths->nslist['User']) . '/', $page_id) )
  2242   {
  2463   {
  2243     $ip = preg_replace('/^' . preg_quote($paths->nslist['User']) . '/', '', $page_id);
  2464     $ip = preg_replace('/^' . preg_quote($paths->nslist['User']) . '/', '', $page_id);
  2244     if ( is_valid_ip($ip) )
  2465     if ( is_valid_ip($ip) )
  2245       return $page_id;
  2466       return $page_id;
  2246   }
  2467   }
  2247   
  2468 
  2248   preg_match_all('/\.[A-Fa-f0-9][A-Fa-f0-9]/', $page_id, $matches);
  2469   preg_match_all('/\.[A-Fa-f0-9][A-Fa-f0-9]/', $page_id, $matches);
  2249   
  2470 
  2250   foreach ( $matches[0] as $id => $char )
  2471   foreach ( $matches[0] as $id => $char )
  2251   {
  2472   {
  2252     $char = substr($char, 1);
  2473     $char = substr($char, 1);
  2253     $char = strtolower($char);
  2474     $char = strtolower($char);
  2254     $char = intval(hexdec($char));
  2475     $char = intval(hexdec($char));
  2255     $char = chr($char);
  2476     $char = chr($char);
  2256     $page_id = str_replace($matches[0][$id], $char, $page_id);
  2477     $page_id = str_replace($matches[0][$id], $char, $page_id);
  2257   }
  2478   }
  2258   
  2479 
  2259   return $page_id;
  2480   return $page_id;
  2260 }
  2481 }
  2261 
  2482 
  2262 /**
  2483 /**
  2263  * Inserts commas into a number to make it more human-readable. Floating point-safe.
  2484  * Inserts commas into a number to make it more human-readable. Floating point-safe and doesn't flirt with the number like number_format() does.
  2264  * @param int The number to process
  2485  * @param int The number to process
  2265  * @return string Input number with commas added
  2486  * @return string Input number with commas added
  2266  */
  2487  */
  2267 
  2488 
  2268 function commatize($num)
  2489 function commatize($num)
  2317 /**
  2538 /**
  2318  * Tells if a given IP address is valid.
  2539  * Tells if a given IP address is valid.
  2319  * @param string suspected IP address
  2540  * @param string suspected IP address
  2320  * @return bool true if valid, false otherwise
  2541  * @return bool true if valid, false otherwise
  2321  */
  2542  */
  2322  
  2543 
  2323 function is_valid_ip($ip)
  2544 function is_valid_ip($ip)
  2324 {
  2545 {
  2325   // These came from phpBB3.
  2546   // These came from phpBB3.
  2326   $ipv4 = '(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])';
  2547   $ipv4 = '(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])';
  2327   $ipv6 = '(?:(?:(?:[\dA-F]{1,4}:){6}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:::(?:[\dA-F]{1,4}:){5}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:):(?:[\dA-F]{1,4}:){4}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,2}:(?:[\dA-F]{1,4}:){3}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,3}:(?:[\dA-F]{1,4}:){2}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,4}:(?:[\dA-F]{1,4}:)(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,5}:(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,6}:[\dA-F]{1,4})|(?:(?:[\dA-F]{1,4}:){1,7}:))';
  2548   $ipv6 = '(?:(?:(?:[\dA-F]{1,4}:){6}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:::(?:[\dA-F]{1,4}:){5}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:):(?:[\dA-F]{1,4}:){4}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,2}:(?:[\dA-F]{1,4}:){3}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,3}:(?:[\dA-F]{1,4}:){2}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,4}:(?:[\dA-F]{1,4}:)(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,5}:(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,6}:[\dA-F]{1,4})|(?:(?:[\dA-F]{1,4}:){1,7}:))';
  2328   
  2549 
  2329   if ( preg_match("/^{$ipv4}$/", $ip) || preg_match("/^{$ipv6}$/", $ip) )
  2550   if ( preg_match("/^{$ipv4}$/", $ip) || preg_match("/^{$ipv6}$/", $ip) )
  2330     return true;
  2551     return true;
  2331   else
  2552   else
  2332     return false;
  2553     return false;
  2333 }
  2554 }