Mise à jour 1.6.9 vers 1.12.1

Note de ce sujet :
  • Moyenne : 0 (0 vote(s))
  • 1
  • 2
  • 3
  • 4
  • 5
#1
Citation :#~~~~~ DEBUT BLOC A NE PAS SUPPRIMER ~~~~~
#~ Version du CMS: !1.11.x
#~ Url du site :
#~ Hébergeur / Soft : online.com
#~ Informations Système :
#~ ----------------------------------------------
#~ Cms Version: 1.6.9
#~ Installed Modules:
#~ CMSMailer: 1.73.14
#~ FileManager: 1.0.2
#~ MenuManager: 1.6.2
#~ ModuleManager: 1.3.2
#~ News: 2.10.4.1
#~ nuSOAP: 1.0.1
#~ Printing: 1.0.4
#~ Search: 1.6.1
#~ ThemeManager: 1.1.1
#~ TinyMCE: 2.6.2
#~ Album: 0.9.3
#~ FormBuilder: 0.6.2
#~ Guestbook: 1.3.2
#~ Config Information:
#~ php_memory_limit:
#~ process_whole_template: false
#~ max_upload_size: 50000000
#~ default_upload_permission: 664
#~ assume_mod_rewrite: true
#~ page_extension: .html
#~ internal_pretty_urls: false
#~ use_hierarchy: true
#~ Php Information:
#~ phpversion: 5.2.9-1.illimite
#~ md5_function: On (Vrai)
#~ gd_version: 2
#~ tempnam_function: On (Vrai)
#~ magic_quotes_runtime: Off (Faux)
#~ memory_limit: 192M
#~ max_execution_time: 360
#~ safe_mode: Off (Faux)
#~ session_save_path: Aucune vérification à cause du chemin OS
#~ session_use_cookies: On (Vrai)
#~ Server Information:
#~ Server Api: cgi-fcgi
#~ Server Db Type: MySQL (mysql)
#~ Server Db Version: 5.5.38
#~~~~~ FIN BLOC A NE PAS SUPPRIMER ~~~~~



Bonjour à tous,

je viens de récupérer un projet en cmsms 1.6.9, le client souhaite une mise à jour mais je suis septique...
vu l’ancêtre ça sent le pot de pus Sad ...
je pense que repartir de zéro me ferais gagner du temps...
Quand pensez-vous?

Merci d'avance...
#1
Citation :#~~~~~ DEBUT BLOC A NE PAS SUPPRIMER ~~~~~
#~ Version du CMS: !1.11.x
#~ Url du site :
#~ Hébergeur / Soft : online.com
#~ Informations Système :
#~ ----------------------------------------------
#~ Cms Version: 1.6.9
#~ Installed Modules:
#~ CMSMailer: 1.73.14
#~ FileManager: 1.0.2
#~ MenuManager: 1.6.2
#~ ModuleManager: 1.3.2
#~ News: 2.10.4.1
#~ nuSOAP: 1.0.1
#~ Printing: 1.0.4
#~ Search: 1.6.1
#~ ThemeManager: 1.1.1
#~ TinyMCE: 2.6.2
#~ Album: 0.9.3
#~ FormBuilder: 0.6.2
#~ Guestbook: 1.3.2
#~ Config Information:
#~ php_memory_limit:
#~ process_whole_template: false
#~ max_upload_size: 50000000
#~ default_upload_permission: 664
#~ assume_mod_rewrite: true
#~ page_extension: .html
#~ internal_pretty_urls: false
#~ use_hierarchy: true
#~ Php Information:
#~ phpversion: 5.2.9-1.illimite
#~ md5_function: On (Vrai)
#~ gd_version: 2
#~ tempnam_function: On (Vrai)
#~ magic_quotes_runtime: Off (Faux)
#~ memory_limit: 192M
#~ max_execution_time: 360
#~ safe_mode: Off (Faux)
#~ session_save_path: Aucune vérification à cause du chemin OS
#~ session_use_cookies: On (Vrai)
#~ Server Information:
#~ Server Api: cgi-fcgi
#~ Server Db Type: MySQL (mysql)
#~ Server Db Version: 5.5.38
#~~~~~ FIN BLOC A NE PAS SUPPRIMER ~~~~~



Bonjour à tous,

je viens de récupérer un projet en cmsms 1.6.9, le client souhaite une mise à jour mais je suis septique...
vu l’ancêtre ça sent le pot de pus Sad ...
je pense que repartir de zéro me ferais gagner du temps...
Quand pensez-vous?

Merci d'avance...
#2
Citation :je pense que repartir de zéro me ferais gagner du temps...
je ne pense pas que ce soit la bonne solution
Je viens de terminer un migration de 1.6.12 vers 1.12.1 sans problème
Pour cela
- je rapatrie en local les fichiers + BD
- je nettoie suppression des modules qui ne seront pas migrés
- une mise à jour
- tests et corrections
- sav de la BD avec nouveau préfix
- je renvoi le tout sur un dossier /1x du du site + la BD
- Tests
- renommage du dossier /1x en dossier orignal
tout ça en 2-3heures
J-C Etiemble v 2.2.xx
#2
Citation :je pense que repartir de zéro me ferais gagner du temps...
je ne pense pas que ce soit la bonne solution
Je viens de terminer un migration de 1.6.12 vers 1.12.1 sans problème
Pour cela
- je rapatrie en local les fichiers + BD
- je nettoie suppression des modules qui ne seront pas migrés
- une mise à jour
- tests et corrections
- sav de la BD avec nouveau préfix
- je renvoi le tout sur un dossier /1x du du site + la BD
- Tests
- renommage du dossier /1x en dossier orignal
tout ça en 2-3heures
J-C Etiemble v 2.2.xx
#3
Merci du retour jce76350,

je me lance sur ta procédure..

Cdt
#3
Merci du retour jce76350,

je me lance sur ta procédure..

Cdt
#4
Rolleyes ça se passer bien jusqu'aprés le choix du langage pendant l'upgrage

Code :
( ! ) Fatal error: Class 'CmsApp' not found in C:\wamp\www\**\lib\misc.functions.php on line 208
Call Stack
#    Time    Memory    Function    Location
1    0.0007    287688    {main}( )    ..\index.php:0
2    0.0077    1214448    require_once( 'C:\wamp\www\**\include.php' )    ..\index.php:145
3    0.0080    1239208    debug_buffer( )    ..\include.php:67
4    0.0080    1239240    cmsms( )    ..\misc.functions.php:580

en 208
Code :
/**
* Return the global cmsms() object
*
* @since 1.7
* @return object
*/
function &cmsms()
{
   return CmsApp::get_instance(); <--ligne 208
}


une idée...?
#4
Rolleyes ça se passer bien jusqu'aprés le choix du langage pendant l'upgrage

Code :
( ! ) Fatal error: Class 'CmsApp' not found in C:\wamp\www\**\lib\misc.functions.php on line 208
Call Stack
#    Time    Memory    Function    Location
1    0.0007    287688    {main}( )    ..\index.php:0
2    0.0077    1214448    require_once( 'C:\wamp\www\**\include.php' )    ..\index.php:145
3    0.0080    1239208    debug_buffer( )    ..\include.php:67
4    0.0080    1239240    cmsms( )    ..\misc.functions.php:580

en 208
Code :
/**
* Return the global cmsms() object
*
* @since 1.7
* @return object
*/
function &cmsms()
{
   return CmsApp::get_instance(); <--ligne 208
}


une idée...?
#5
>ça se passer bien jusqu'aprés le choix du langage pendant l'upgrage
Quelle étape ??
le choix de langue c'est en 1er
>une idée...?
... tes fichiers ?
J-C Etiemble v 2.2.xx
#5
>ça se passer bien jusqu'aprés le choix du langage pendant l'upgrage
Quelle étape ??
le choix de langue c'est en 1er
>une idée...?
... tes fichiers ?
J-C Etiemble v 2.2.xx
#6
bjr jce,
j'ai cette erreur lors de l'étape mise à jour .des que je choisis la langue (fr_FR) et que je valide
Fatal error: Class 'CmsApp' not found in C:\wamp\www\v2\lib\misc.functions.php on line 208
Code :
<?php
#CMS - CMS Made Simple
#(c)2004-2012 by Ted Kulp (wishy@users.sf.net)
#This project's homepage is: http://www.cmsmadesimple.org
#
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#$Id: misc.functions.php 9859 2015-03-28 16:16:09Z calguy1000 $

/**
* Misc functions
*
* @package CMS
*/



/**
* Redirects to relative URL on the current site
*
* @author http://www.edoceo.com/
* @since 0.1
* @param string The url to redirect to
* @return void
*/
function redirect($to, $noappend=false)
{
  $_SERVER['PHP_SELF'] = null;

  $schema = 'http';

  if( class_exists('CmsApp'))
  {
      if( cmsms()->is_https_request() ) $schema = 'https';
  }
  else
  {
    if( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ) $schema = 'https';
  }

  $host = strlen($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']:$_SERVER['SERVER_NAME'];

    $components = parse_url($to);
    if(count($components) > 0)
    {
        $to =  (isset($components['scheme']) && startswith($components['scheme'], 'http') ? $components['scheme'] : $schema) . '://';
        $to .= isset($components['host']) ? $components['host'] : $host;
        $to .= isset($components['port']) ? ':' . $components['port'] : '';
        if(isset($components['path']))
        {
            if(in_array(substr($components['path'],0,1),array('\\','/')))//Path is absolute, just append.
            {
                $to .= $components['path'];
            }
            //Path is relative, append current directory first.
            else if (isset($_SERVER['PHP_SELF']) && !is_null($_SERVER['PHP_SELF'])) //Apache
            {
                $to .= (strlen(dirname($_SERVER['PHP_SELF'])) > 1 ?  dirname($_SERVER['PHP_SELF']).'/' : '/') . $components['path'];
            }
            else if (isset($_SERVER['REQUEST_URI']) && !is_null($_SERVER['REQUEST_URI'])) //Lighttpd
            {
                if (endswith($_SERVER['REQUEST_URI'], '/'))
                    $to .= (strlen($_SERVER['REQUEST_URI']) > 1 ? $_SERVER['REQUEST_URI'] : '/') . $components['path'];
                else
                    $to .= (strlen(dirname($_SERVER['REQUEST_URI'])) > 1 ? dirname($_SERVER['REQUEST_URI']).'/' : '/') . $components['path'];
            }
        }
        $to .= isset($components['query']) ? '?' . $components['query'] : '';
        $to .= isset($components['fragment']) ? '#' . $components['fragment'] : '';
    }
    else
    {
        $to = $schema."://".$host."/".$to;
    }

    session_write_close();

    $debug = false;
    if( class_exists('CmsApp') )
      {
    $config = cmsms()->GetConfig();
    $debug = $config['debug'];
      }

    if (headers_sent() && !$debug)
    {
        // use javascript instead
        echo '<script type="text/javascript">
            <!--
                location.replace("'.$to.'");
            // -->
            </script>
            <noscript>
                <meta http-equiv="Refresh" content="0;URL='.$to.'">
            </noscript>';
        exit;

    }
    else
    {
        if ( $debug )
        {
            echo "Debug is on.  Redirecting disabled...  Please click this link to continue.<br />";
            echo "<a href=\"".$to."\">".$to."</a><br />";
            echo '<div id="DebugFooter">';
            global $sql_queries;
            if (FALSE == empty($sql_queries))
              {
                echo "<div>".$sql_queries."</div>\n";
              }
            foreach (cmsms()->get_errors() as $error)
            {
                echo $error;
            }
            echo '</div> <!-- end DebugFooter -->';
            exit();
        }
        else
        {
            header("Location: $to");
            exit();
        }
    }
}



/**
* Given a page ID or an alias, redirect to it
* Retrieves the URL of the specified page, and performs a redirect
*
* @param mixed An integer page id or a string page alias.
* @return void
*/
function redirect_to_alias($alias)
{
  $manager = cmsms()->GetHierarchyManager();
  $node = $manager->sureGetNodeByAlias($alias);
  if( !$node ) {
    // put mention into the admin log
    audit('','Core','Attempt to redirect to invalid alias: '.$alias);
    return;
  }
  $content = $node->GetContent();
  if (!is_object($content)) {
    audit('','Core','Attempt to redirect to invalid alias: '.$alias);
    return;
  }
  if ($content->GetURL() != '') {
    redirect($content->GetURL());
  }
}



/**
* Calculate the difference in seconds between two microtime() values
*
* @since 0.3
* @param string Microtime value A
* @param string Microtime value B
* @return integer The difference.
*/
function microtime_diff($a, $b) {
    list($a_dec, $a_sec) = explode(" ", $a);
    list($b_dec, $b_sec) = explode(" ", $b);
    return $b_sec - $a_sec + $b_dec - $a_dec;
}



/**
* Joins a path together using proper directory separators
* Taken from: http://www.php.net/manual/en/ref.dir.php
*
* This method accepts a variable number of string arguments.
*
* @since 0.14
* @return string
*/
function cms_join_path()
{
    $args = func_get_args();
        return implode(DIRECTORY_SEPARATOR,$args);
}



/**
* Return the global cmsms() object
*
* @since 1.7
* @return object
*/
function &cmsms()
{
   return CmsApp::get_instance();
}



/**
* Shows a very close approximation of an Apache generated 404 error.
*
* Shows a very close approximation of an Apache generated 404 error.
* It also sends the actual header along as well, so that generic
* browser error pages (like what IE does) will be displayed.
*
* @since 0.3
* @deprecated
* @internal
* Rolf: function used in /index.php
*/
function ErrorHandler404()
{
        @ob_end_clean();
        header("HTTP/1.0 404 Not Found");
        header("Status: 404 Not Found");
        echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>';
        exit();
}



/**
* A method to perform HTML entity conversion on a string
*
* @see htmlentities
* @param string The input string
* @param string A flag indicating how quotes should be handled (see htmlentities) (ignored)
* @param string The input character set (ignored)
* @param boolean A flag indicating wether single quotes should be converted to entities.
* @return string the converted string.
*/
function cms_htmlentities($val, $param=ENT_QUOTES, $charset="UTF-8", $convert_single_quotes = false)
{
  if ($val == "") return "";

  $val = str_replace( " ", " ", $val );
  $val = str_replace( "&"            , "&amp;"         , $val );
  $val = str_replace( "<!--"         , "<!--"  , $val );
  $val = str_replace( "-->"          , "-->"       , $val );
  $val = preg_replace( "/<script/i"  , "<script"   , $val );
  $val = str_replace( ">"            , "&gt;"          , $val );
  $val = str_replace( "<"            , "&lt;"          , $val );
  $val = str_replace( "\""           , "&quot;"        , $val );
  $val = preg_replace( "/\\$/"      , "$"        , $val );
  $val = str_replace( "!"            , "!"         , $val );
  $val = str_replace( "'"            , "'"         , $val );

  if ($convert_single_quotes)
    {
      $val = str_replace("\\'", "&apos;", $val);
      $val = str_replace("'", "&apos;", $val);
    }

  return $val;
}



/**
* @ignore
*/
define('CLEANED_FILENAME','BAD_FILE');



/**
* Clean up the filename, and ensure that the filename resides underneath
* the cms_root directory, if it does not replace it with the hardcoded
* string CLEANED_FILENAME
*
* @internal
* @param string The complete file specification
* @return string the cleaned file path.
* Rolf: only used in this file
*/
function cms_cleanfile($filename)
{
    $realpath = realpath($filename);
    if( $realpath === FALSE ) {
        return CLEANED_FILENAME;
    }

    // This ensures that the file specified is somewhere
    // underneath the cms root path
    $config = cmsms()->GetConfig();
    if( strpos($realpath, $config['root_path']) !== 0 ) {
        return CLEANED_FILENAME;
    }
    return $realpath;
}




/**
* A replacement for the built in htmlentities method.
*
* @ignore
* @deprecated
* @param string  input string
* @param boolean A flag wether or not to handle single quotes.
* @return string
*/
function my_htmlentities($val, $convert_single_quotes = false)
{
  return cms_htmlentities($val,ENT_QUOTES,'UTF-8',$convert_single_quotes);
}



/**
* A method to convert a string into UTF-8 entities
*
* @internal
* @deprecated
* @param string Input string
* @return string
* Rolf: used in admin/listmodules.php
*/
function cms_utf8entities($val)
{
    if ($val == "")
    {
        return "";
    }
    $val = str_replace( " ", " ", $val );
    $val = str_replace( "&"            , "\u0026"         , $val );
    $val = str_replace( ">"            , "\u003E"          , $val );
    $val = str_replace( "<"            , "\u003C"          , $val );


    $val = str_replace( "\""           , "\u0022"        , $val );
    $val = str_replace( "!"            , "\u0021"         , $val );
    $val = str_replace( "'"            , "\u0027"         , $val );

    return $val;
}



/**
* A function to put a backtrace into the generated log file.
*
* @see debug_to_log, debug_bt
* @return void
* Rolf: Looks like not used
*/
function debug_bt_to_log()
{
    if( cmsms()->config['debug_to_log'] || (function_exists('check_login') && check_login(TRUE)) ) {
        $bt=debug_backtrace();
        $file = $bt[0]['file'];
        $line = $bt[0]['line'];

        $out = array();
        $out[] = "Backtrace in $file on line $line";

        $bt = array_reverse($bt);
        foreach($bt as $trace) {
            if( $trace['function'] == 'debug_bt_to_log' ) continue;

            $file = $line = '';
            if( isset($trace['file']) ) $file = $trace['file'];
            if( isset($trace['line']) ) $line = $trace['line'];
            $function = $trace['function'];
            $out[] = "$function at $file:$line";
        }

        $filename = TMP_CACHE_LOCATION . '/debug.log';
        foreach ($out as $txt) {
            error_log($txt . "\n", 3, $filename);
        }
    }
}



/**
* A function to generate a backtrace in a readable format.
*
* @return void
* Rolf: looks like not used
*/
function debug_bt()
{
    $bt=debug_backtrace();
    $file = $bt[0]['file'];
    $line = $bt[0]['line'];

    echo "\n\n<p><b>Backtrace in $file on line $line</b></p>\n";

    $bt = array_reverse($bt);
    echo "<pre><dl>\n";
    foreach($bt as $trace)
    {
        $file = $trace['file'];
        $line = $trace['line'];
        $function = $trace['function'];
        $args = implode(',', $trace['args']);
        echo "
        <dt><b>$function</b>($args) </dt>
        <dd>$file on line $line</dd>
        ";
    }
    echo "</dl></pre>\n";
}



/**
* Debug function to display $var nicely in html.
*
* @param mixed $var
* @param string $title (optional)
* @param boolean $echo_to_screen (optional)
* @return string
*/
function debug_display($var, $title="", $echo_to_screen = true, $use_html = true)
{
    $variables =& cmsms()->variables;

    $starttime = microtime();
    if (isset($variables['starttime']))
        $starttime = $variables['starttime'];
    else
        $variables['starttime'] = $starttime;

    $titleText = "Debug: ";
    if($title)
    {
        $titleText = "Debug display of '$title':";
    }
    $titleText .= '(' . microtime_diff($starttime,microtime()) . ')';

    if (function_exists('memory_get_usage'))
    {
      $titleText .= ' - (usage: '.memory_get_usage().')';
    }

    $memory_peak = (function_exists('memory_get_peak_usage')?memory_get_peak_usage():'');
    if( $memory_peak )
      {
        $titleText .= ' - (peak: '.$memory_peak.')';
      }

    ob_start();
    if ($use_html)
      {
        echo "<div><b>$titleText</b>\n";
      }
    else
      {
        echo "$titleText\n";
      }

    if(FALSE == empty($var))
    {
        if ($use_html)
        {
            echo '<pre>';
        }
        if(is_array($var))
        {
            echo "Number of elements: " . count($var) . "\n";
            print_r($var);
        }
        elseif(is_object($var))
        {
            print_r($var);
        }
        elseif(is_string($var))
        {
          if( $use_html )
            {
            print_r(htmlentities(str_replace("\t", '  ', $var)));
            }
          else
            {
              print_r($var);
            }
        }
        elseif(is_bool($var))
        {
            echo $var === true ? 'true' : 'false';
        }
        else
        {
            print_r($var);
        }
        if ($use_html)
        {
            echo '</pre>';
        }
    }
    if ($use_html)
        echo "</div>\n";

    $output = ob_get_contents();
    ob_end_clean();

    if($echo_to_screen)
    {
      echo $output;
    }

    return $output;
}



/**
* Display $var nicely only if $config["debug"] is set
*
* @param mixed $var
* @param string $title
*/
function debug_output($var, $title="")
{
  if(cmsms()->config["debug"] == true)
    {
        debug_display($var, $title, true);
    }

}



/**
* Debug function to output debug information about a variable in a formatted matter
* to a debug file.
*
* @param mixed data to display
* @param string Optional title.
*/
function debug_to_log($var, $title='',$filename = '')
{
    if( cmsms()->config['debug_to_log'] || (function_exists('check_login') && check_login(TRUE)) ) {
        if( $filename == '' ) {
            $filename = TMP_CACHE_LOCATION . '/debug.log';
            $x = @filemtime($filename);
            if( $x !== FALSE && $x < (time() - 24 * 3600) ) @unlink($filename);
        }
        $errlines = explode("\n",debug_display($var, $title, false, false));
        foreach ($errlines as $txt) {
            error_log($txt . "\n", 3, $filename);
        }
    }
}



/**
* Display $var nicely to the cmsms()->errors array if $config['debug'] is set
*
* @param mixed $var
* @param string $title
*/
function debug_buffer($var, $title="")
{
  $config = cmsms()->GetConfig();
  if($config["debug"] == true)
    {
      cmsms()->add_error(debug_display($var, $title, false, true));
    }
}



/**
* Debug an sql command
*
* @internal
* @param string SQL query
* @param boolean (unused)
* Rolf: only used in lib/adodb.functions.php
*/
function debug_sql($str, $newline = false)
{
  $config = cmsms()->GetConfig();
  if($config["debug"] == true)
    {
      cmsms()->add_error(debug_display($str, '', false, true));
    }
}



/**
* Retrieve value from $_REQUEST. Returns $default_value if
*        value is not in $_REQUEST or is not the same basic type as
*        $default_value.
*        If $session_key is set, then will return session value in preference
*        to $default_value if $_REQUEST[$value] is not set.
*
* @param string $value
* @param mixed $default_value (optional)
* @param string $session_key (optional)
* @deprecated
* @return mixed
* Rolf: looks like not used
*/
function get_request_value($value, $default_value = '', $session_key = '')
{
    if($session_key != '')
    {
        if(isset($_SESSION['request_values'][$session_key][$value]))
        {
            $default_value = $_SESSION['request_values'][$session_key][$value];
        }
    }
    if(isset($_REQUEST[$value]))
    {
        $result = get_value_with_default($_REQUEST[$value], $default_value);
    }
    else
    {
        $result = $default_value;
    }

    if($session_key != '')
    {
        $_SESSION['request_values'][$session_key][$value] = $result;
    }

    return $result;
}



/**
* Return $value if it's set and same basic type as $default_value,
*            otherwise return $default_value. Note. Also will trim($value)
*            if $value is not numeric.
*
* @param string $value
* @param mixed $default_value
* @deprecated
* @return mixed
* Rolf: only used in this file
*/
function get_value_with_default($value, $default_value = '', $session_key = '')
{
    if($session_key != '')
    {
        if(isset($_SESSION['default_values'][$session_key]))
        {
            $default_value = $_SESSION['default_values'][$session_key];
        }
    }

    // set our return value to the default initially and overwrite with $value if we like it.
    $return_value = $default_value;

    if(isset($value))
    {
        if(is_array($value))
        {
            // $value is an array - validate each element.
            $return_value = array();
            foreach($value as $element)
            {
                $return_value[] = get_value_with_default($element, $default_value);
            }
        }
        else
        {
            if(is_numeric($default_value))
            {
                if(is_numeric($value))
                {
                    $return_value = $value;
                }
            }
            else
            {
                $return_value = trim($value);
            }
        }
    }

    if($session_key != '')
    {
        $_SESSION['default_values'][$session_key] = $return_value;
    }

    return $return_value;
}



/**
* Retrieve the $value from the $parameters array checking for
* $parameters[$value] and $params[$id.$value]. Returns $default
* if $value is not in $params array.
* Note: This function will also trim() string values.
*
* @param array $parameters
* @param string $value
* @param mixed $default_value
* @param string $session_key
* @return mixed
* Rolf: looks like not used
*/
function get_parameter_value($parameters, $value, $default_value = '', $session_key = '')
{
    if($session_key != '')
    {
        if(isset($_SESSION['parameter_values'][$session_key]))
        {
            $default_value = $_SESSION['parameter_values'][$session_key];
        }
    }

    // set our return value to the default initially and overwrite with $value if we like it.
    $return_value = $default_value;
    if(isset($parameters[$value]))
    {
        if(is_bool($default_value))
        {
            // want a boolean return_value
            if(isset($parameters[$value]))
            {
                $return_value = (boolean)$parameters[$value];
            }
        }
        else
        {
            // is $default_value a number?
            $is_number = false;
            if(is_numeric($default_value))
            {
                $is_number = true;
            }

            if(is_array($parameters[$value]))
            {
                // $parameters[$value] is an array - validate each element.
                $return_value = array();
                foreach($parameters[$value] as $element)
                {
                    $return_value[] = get_value_with_default($element, $default_value);
                }
            }
            else
            {
                if(is_numeric($default_value))
                {
                    // default value is a number, we only like $parameters[$value] if it's a number too.
                    if(is_numeric($parameters[$value]))
                    {
                        $return_value = $parameters[$value];
                    }
                }
                elseif(is_string($default_value))
                {
                    $return_value = trim($parameters[$value]);
                }
                else
                {
                    $return_value = $parameters[$value];
                }
            }
        }
    }

    if($session_key != '')
    {
        $_SESSION['parameter_values'][$session_key] = $return_value;
    }

    return $return_value;
}



/**
* A convenience function to create a dropdown control with supported encodings.
*
* @internal
* @param string A name for the control
* @param string The name of the option that should be selected.
* @return string
* Rolf: only used in admin/edittemplate.php
*/
function create_encoding_dropdown($name = 'encoding', $selected = '')
{
    $result = '';

    $encodings = array(''=>'Default','UTF-8'=>'Unicode','ISO-8859-1'=>'Latin 1/West European','ISO-8859-2'=>'Latin 2/Central European','ISO-8859-3'=>'Latin 3/South European','ISO-8859-4'=>'Latin 4/North European','ISO-8859-5'=>'Cyrilic','ISO-8859-6'=>'Arabic','ISO-8859-7'=>'Greek','ISO-8859-8'=>'Hebrew','ISO-8859-9'=>'Latin 5/Turkish','ISO-8859-11'=>'TIS-620/Thai','ISO-8859-14'=>'Latin 8','ISO-8859-15'=>'Latin 9','Big5'=>'Taiwanese','GB2312'=>'Chinese','EUC-JP'=>'Japanese','EUC-KR'=>'Korean','KOI8-R'=>'Russian','Windows-1250'=>'Central Europe','Windows-1251'=>'Cyrilic','Windows-1252'=>'Latin 1','Windows-1253'=>'Greek','Windows-1254'=>'Turkish','Windows-1255'=>'Hebrew','Windows-1256'=>'Arabic','Windows-1257'=>'Baltic','Windows-1258'=>'Vietnam');

    $result .= '<select name="'.$name.'">';
    foreach ($encodings as $key=>$value)
    {
        $result .= '<option value="'.$key.'"';
        if ($selected == $key)
        {
            $result .= ' selected="selected"';
        }
        $result .= '>'.$key.($key!=''?' - ':'').$value.'</option>';
    }
    $result .= '</select>';

    return $result;
}



/**
* A method to remove a permission from the database.
*
* @internal
* @access private
* @param string The permission name
*/
function cms_mapi_remove_permission($permission_name)
{
  $db = cmsms()->GetDB();

  $query = "SELECT permission_id FROM ".cms_db_prefix()."permissions WHERE permission_name = ?";
  $row = &$db->GetRow($query, array($permission_name));

  if ($row)
    {
      $id = $row["permission_id"];

      $query = "DELETE FROM ".cms_db_prefix()."group_perms WHERE permission_id = ?";
      $db->Execute($query, array($id));

      $query = "DELETE FROM ".cms_db_prefix()."permissions WHERE permission_id = ?";
      $db->Execute($query, array($id));
    }
}



/**
* A method to add a permission to the CMSMS permissions table
*
* @internal
* @access private
* @param unknown (ignored)
* @param string  The permission name
* @param string  The permission human readable text.
*/
function cms_mapi_create_permission($cms, $permission_name, $permission_text)
{
  $db = cmsms()->GetDb();

    $query = "SELECT permission_id FROM ".cms_db_prefix()."permissions WHERE permission_name =" . $db->qstr($permission_name);
    $result = $db->Execute($query);

    if ($result && $result->RecordCount() < 1) {

        $new_id = $db->GenID(cms_db_prefix()."permissions_seq");
        $query = "INSERT INTO ".cms_db_prefix()."permissions (permission_id, permission_name, permission_text, create_date, modified_date) VALUES ($new_id, ".$db->qstr($permission_name).",".$db->qstr($permission_text).",".$db->DBTimeStamp(time()).",".$db->DBTimeStamp(time()).")";
        $db->Execute($query);
    }

    if ($result)
    {
        $result->Close();
        return true;
    }
    return false;
}



/**
* A function to test if a file specification matches an array of
* file specifications that indicate it should be excluded
*
* @internal
* @deprecated
* @access private
* @param string Flle specification
* @param array  Array of regular expressions.
* @return boolean
* Rolf: only used in this file
*/
function filespec_is_excluded( $file, $excludes )
{
  // strip the path from the file
  if( empty($excludes) ) return false;
  foreach( $excludes as $excl )
    {
      if( @preg_match( "/".$excl."/i", basename($file) ) )
    {
      return true;
    }
    }
  return false;
}



/**
* Check the permissions of a directory recursively to make sure that
* we have write permission to all files
*
* @param  string  Start directory.
* @return boolean
*/
function is_directory_writable( $path )
{
  if ( substr ( $path , strlen ( $path ) - 1 ) != '/' )
    {
      $path .= '/' ;
    }

  $result = true;
  if( $handle = @opendir( $path ) )
    {
      while( false !== ( $file = readdir( $handle ) ) )
    {
      if( $file == '.' || $file == '..' )
        {
          continue;
        }

      $p = $path.$file;

      if( !@is_writable( $p ) )
        {
          return false;
        }

      if( @is_dir( $p ) )
        {
          $result = is_directory_writable( $p );
          if( !$result )
        {
          return false;
        }
        }
    }
      @closedir( $handle );
    }
  else
    {
      return false;
    }

  return true;
}



/**
* Return an array containing a list of files in a directory
* performs a non recursive search
*
* @internal
* @param path - path to search
* @param extensions - include only files matching these extensions
*                     case insensitive, comma delimited
* Rolf: only used in this file
*/
function get_matching_files($dir,$extensions = '',$excludedot = true,$excludedir = true, $fileprefix='',$excludefiles=1)
{
  $dh = @opendir($dir);
  if( !$dh ) return false;

  if( !empty($extensions) )
    {
      $extensions = explode(',',strtolower($extensions));
    }
  $results = array();
  while( false !== ($file = readdir($dh)) )
    {
      if( $file == '.' || $file == '..' ) continue;
      if( startswith($file,'.') && $excludedot ) continue;
      if( is_dir(cms_join_path($dir,$file)) && $excludedir ) continue;
      if( !empty($fileprefix) )
    {
      if( $excludefiles == 1 && startswith($file,$fileprefix) ) continue;
      if( $excludefiles == 0 && !startswith($file,$fileprefix) ) continue;
    }

      $ext = strtolower(substr($file,strrpos($file,'.')+1));
      if( is_array($extensions) && count($extensions) && !in_array($ext,$extensions) ) continue;

      $results[] = $file;
    }
  closedir($dh);
  if( !count($results) ) return false;
  return $results;
}



/**
* Return an array containing a list of files in a directory
* performs a recursive search
*
* @internal
* @param  string    Start Path.
* @param  array     Array of regular expressions indicating files to exclude.
* @param  int       How deep to browse (-1=unlimited)
* @param  string    "FULL"|"DIRS"|"FILES"
* @param  d         for internal use only
* @return  array
**/
function get_recursive_file_list ( $path , $excludes, $maxdepth = -1 , $mode = "FULL" , $d = 0 )
{
   if ( substr ( $path , strlen ( $path ) - 1 ) != '/' ) { $path .= '/' ; }
   $dirlist = array () ;
   if ( $mode != "FILES" ) { $dirlist[] = $path ; }
   if ( $handle = opendir ( $path ) )
   {
       while ( false !== ( $file = readdir ( $handle ) ) )
       {
     if( $file == '.' || $file == '..' ) continue;
     if( filespec_is_excluded( $file, $excludes ) ) continue;

     $file = $path . $file ;
     if ( ! @is_dir ( $file ) ) { if ( $mode != "DIRS" ) { $dirlist[] = $file ; } }
     elseif ( $d >=0 && ($d < $maxdepth || $maxdepth < 0) )
       {
         $result = get_recursive_file_list ( $file . '/' , $excludes, $maxdepth , $mode , $d + 1 ) ;
         $dirlist = array_merge ( $dirlist , $result ) ;
       }
       }
       closedir ( $handle ) ;
   }
   if ( $d == 0 ) { natcasesort ( $dirlist ) ; }
   return ( $dirlist ) ;
}



/**
* A function to recursively delete all files and folders in a directory
* synonymous with rm -r
*
* @param string The directory name
* @return boolean
*/
function recursive_delete( $dirname )
{
  // all subdirectories and contents:
  if(is_dir($dirname))$dir_handle=opendir($dirname);
  while($file=readdir($dir_handle))
  {
    if($file!="." && $file!="..")
    {
      if(!is_dir($dirname."/".$file))
    {
      if( !@unlink ($dirname."/".$file) )
        {
          closedir( $dir_handle );
          return false;
        }
    }
      else
    {
      recursive_delete($dirname."/".$file);
    }
    }
  }
  closedir($dir_handle);
  if( ! @rmdir($dirname) )
    {
      return false;
    }
  return true;
}



/**
* A function to recursively chmod all files and folders in a directory
*
* @see chmod
* @param string The start location
* @param integer The mode
* Rolf: only used in admin/listmodules.php
*/
function chmod_r( $path, $mode )
{
  if( !is_dir( $path ) )
    return chmod( $path, $mode );

  $dh = @opendir( $path );
  if( !$dh ) return FALSE;

  while( $file = readdir( $dh ) )
  {
    if( $file == '.' || $file == '..' ) continue;

    $p = $path.DIRECTORY_SEPARATOR.$file;
    if( is_dir( $p ) )
    {
      if( !@chmod_r( $p, $mode ) )
    {
      closedir( $dh );
      return false;
    }
    }
    else if( !is_link( $p ) )
    {
      if( !@chmod( $p, $mode ) )
    {
      closedir( $dh );
      return false;
    }
    }
  }
  @closedir( $dh );
  return @chmod( $path, $mode );
}



/**
* A method to serialize an object and encode it for storage or transport.
*
* @internal
* @param object The object to serialize
* @return string
*/
function SerializeObject(&$object)
{
    return base64_encode(serialize($object));
}



/**
* A function unserialize data into an object
*
* @internal
* @param string The serialized text.
* @return object  A valid object on success, or null
* Rolf: only used in admin/editcontent_extra.php
*/
function UnserializeObject(&$serialized)
{
    return  unserialize(base64_decode($serialized));
}



/**
* A convenience function to test wether one string starts with another
*
* i.e:  startswith('The Quick Brown Fox','The');
*
* @param string The string to test against
* @param string The search string
* @return boolean
*/
function startswith( $str, $sub )
{
    return ( substr( $str, 0, strlen( $sub ) ) == $sub );
}



/**
* Similar to the startswith method, this function tests with string A ends with string B
*
* i.e: endswith('The Quick Brown Fox','Fox');
*
* @param string The string to test against
* @param string The search string
* @return boolean
*/
function endswith( $str, $sub )
{
    return ( substr( $str, strlen( $str ) - strlen( $sub ) ) == $sub );
}



/**
* convert a human readable string into something that is suitable for use in URLS
* because many browsers don't support UTF-8 characters in URLS
*
* @internal
* @param string String to convert
* @param boolean indicates whether output string should be converted to lower case
* @param boolean indicates wether slashes should be allowed in the input.
* @return string
*/
function munge_string_to_url($alias, $tolower = false, $withslash = false)
{
    // replacement.php is encoded utf-8 and must be the first modification of alias
    include(dirname(__FILE__) . '/replacement.php');
    $alias = str_replace($toreplace, $replacement, $alias);

    // lowercase only on empty aliases
    if ($tolower == true)
    {
        $alias = strtolower($alias);
    }

    $expr = '/[^a-z0-9-_]+/i';
    if( $withslash )
      {
        $expr = '/[^a-z0-9-_\/]+/i';
      }
    $alias = preg_replace($expr,'-',$alias);

    for( $i = 0; $i < 5; $i++ )
      {
        $tmp = str_replace('--','-',$alias);
        if( $tmp == $alias ) break;
        $alias = $tmp;
      }
    $alias = trim($alias, '-');
    $alias = trim($alias);

    return $alias;
}


/**
* Rolf: only used in admin/style.php
*/
function cms_readfile($filename)
{
  @ob_start();
  echo file_get_contents($filename);
  $result = @ob_get_contents();
  @ob_end_clean();
  if( !empty($result) ) {
    echo $result;
    return TRUE;
  }
  return FALSE;
}


/*
* Sanitize input to prevent against XSS and other nasty stuff.
* Taken from cakephp (http://cakephp.org)
* Licensed under the MIT License
*
* @internal
* @param string input
* @return string
*/
function cleanValue($val) {
    if ($val == "") {
        return $val;
    }
    //Replace odd spaces with safe ones
    $val = str_replace(" ", " ", $val);
    $val = str_replace(chr(0xCA), "", $val);
    //Encode any HTML to entities (including \n --> <br />)
    $val = cleanHtml($val);
    //Double-check special chars and remove carriage returns
    //For increased SQL security
    $val = preg_replace("/\\\$/", "$", $val);
    $val = preg_replace("/\r/", "", $val);
    $val = str_replace("!", "!", $val);
    $val = str_replace("'", "'", $val);
    //Allow unicode (?)
    $val = preg_replace("/&amp;#([0-9]+);/s", "&#\\1;", $val);
    //Add slashes for SQL
    //$val = $this->sql($val);
    //Swap user-inputted backslashes (?)
    $val = preg_replace("/\\\(?!&amp;#|\?#)/", "\\", $val);
    return $val;
}



/*
* Method to sanitize incoming html.
* Take from cakephp (http://cakephp.org)
* Licensed under the MIT License
*
* @param string Input HTML code.
* @param boolean Wether HTML tags should be removed.
* @return string
* Rolf: only used in this file
*/
function cleanHtml($string, $remove = false) {
    if ($remove) {
        $string = strip_tags($string);
    } else {
        $patterns = array("/\&/", "/%/", "/</", "/>/", '/"/', "/'/", "/\(/", "/\)/", "/\+/", "/-/");
        $replacements = array("&amp;", "%", "&lt;", "&gt;", "&quot;", "'", "(", ")", "+", "-");
        $string = preg_replace($patterns, $replacements, $string);
    }
    return $string;
}

define('CLEAN_INT','CLEAN_INT');
define('CLEAN_FLOAT','CLEAN_FLOAT');
define('CLEAN_NONE','CLEAN_NONE');
define('CLEAN_STRING','CLEAN_STRING');
define('CLEAN_REGEXP','regexp:');
define('CLEAN_FILE','CLEAN_FILE');



/**
* Method to sanitize all entries in a hash
* This method is called by the module api to clean incomming parameters in the frontend.
* It uses the map created with the SetParameterType() method in the module api.
*
* @internal
* @param string Module Name
* @param array  Hash data
* @param array  A map of param names and type information
* @param boolean A flag indicating wether unknown keys in the input data should be allowed.
* @param boolean A flag indicating wether keys should be treated as strings and cleaned.
* Rolf: only used in lib/classes/class.CMSModule.php
*/
function cleanParamHash($modulename,$data,$map = false,
            $allow_unknown = false,$clean_keys = true)
{
  $mappedcount = 0;
  $result = array();
  foreach( $data as $key => $value )
    {
      $mapped = false;
      $paramtype = '';
      if( is_array($map) )
        {
          if( isset($map[$key]) )
            {
                $paramtype = $map[$key];
            }
          else {
              // Key not found in the map
              // see if one matches via regular expressions
              foreach( $map as $mk => $mv ) {
                  if(strstr($mk,CLEAN_REGEXP) === FALSE) continue;

                  // mk is a regular expression
                  $ss = substr($mk,strlen(CLEAN_REGEXP));
                  if( $ss !== FALSE ) {
                      if( preg_match($ss, $key) ) {
                          // it matches, we now know what type to use
                          $paramtype = $mv;
                          break;
                      }
                  }
              }
          } // else

          if( $paramtype != '' ) {
              switch( $paramtype ) {
              case 'CLEAN_INT':
                  $mappedcount++;
                  $mapped = true;
                  $value = (int) $value;
                  break;
              case 'CLEAN_FLOAT':
                  $mappedcount++;
                  $mapped = true;
                  $value = (float) $value;
                  break;
              case 'CLEAN_NONE':
                  // pass through without cleaning.
                  $mappedcount++;
                  $mapped = true;
                  break;
              case 'CLEAN_STRING':
                  $value = cms_htmlentities($value);
                  $mappedcount++;
                  $mapped = true;
                  break;
              case 'CLEAN_FILE':
                  $value = cms_cleanfile($value);
                  $mappedcount++;
                  $mapped = true;
                  break;
              default:
                  $mappedcount++;
                  $mapped = true;
                  $value = cms_htmlentities($value);
                  break;
              } // switch
          } // if $paramtype

        }

      // we didn't clean this yet
      if( $allow_unknown && !$mapped )
        {
          // but we're allowing unknown stuff so we'll just clean it.
          $value = cms_htmlentities($value);
          $mappedcount++;
          $mapped = true;
        }

      if( $clean_keys )
        {
          $key = cms_htmlentities($key);
        }

      if( !$mapped && !$allow_unknown )
        {
          trigger_error('Parameter '.$key.' is not known by module '.$modulename.' dropped',E_USER_WARNING);
          continue;
        }
      $result[$key]=$value;
    }
  return $result;
}



/**
* Returns all parameters sent that are destined for the module with
* the given $id.  This method reads the parameters directly from the $_REQUEST
*
* @internal
* @param string ID (the module instance ID to use for extracting parameters)
* @return array
*/
function GetModuleParameters($id)
{
  $params = array();

  if ($id != '')
    {
      foreach ($_REQUEST as $key=>$value)
    {
      if (strpos($key, (string)$id) !== FALSE && strpos($key, (string)$id) == 0)
        {
          $key = str_replace($id, '', $key);
          if( $key == 'id' || $key == 'returnid' )
        {
          $value = (int)$value;
        }
          $params[$key] = $value;
        }
    }
    }

  return $params;
}



/**
* A function to test if permissions, and php configuration is setup correctly
* to allow an administrator to upload files to CMSMS
*
* @internal
* @return boolean
*/
function can_admin_upload()
{
  # first, check to see if safe mode is enabled
  # if it is, then check to see the owner of the index.php, moduleinterface.php
  # and the uploads and modules directory.  if they all match, then we
  # can upload files.
  # if safe mode is off, then we just have to check the permissions.
  $file_index = cmsms()->config['root_path'].DIRECTORY_SEPARATOR.'index.php';
  $file_moduleinterface = cmsms()->config['root_path'].DIRECTORY_SEPARATOR.
    cmsms()->config['admin_dir'].DIRECTORY_SEPARATOR.'moduleinterface.php';
  $dir_uploads = cmsms()->config['uploads_path'];
  $dir_modules = cmsms()->config['root_path'].DIRECTORY_SEPARATOR.'modules';

  $stat_index = @stat($file_index);
  $stat_moduleinterface = @stat($file_moduleinterface);
  $stat_uploads = @stat($dir_uploads);
  $stat_modules = @stat($dir_modules);

  $my_uid = @getmyuid();

  if( $my_uid === FALSE || $stat_index == FALSE ||
      $stat_moduleinterface == FALSE || $stat_uploads == FALSE ||
      $stat_modules == FALSE )
    {
      // couldn't get some necessary information.
      return FALSE;
    }

  $safe_mode = ini_get_boolean('safe_mode');
  if( $safe_mode )
    {
      // we're in safe mode.
      if( ($stat_moduleinterface[4] != $stat_modules[4]) ||
      ($stat_moduleinterface[4] != $stat_uploads[4]) ||
      ($my_uid != $stat_moduleinterface[4]) )
    {
      // owners don't match
      return FALSE;
    }
    }

  // now check to see if we can write to the directories
  if( !is_writable( $dir_modules ) )
    {
      return FALSE;
    }
  if( !is_writable( $dir_uploads ) )
    {
      return FALSE;
    }

  // It all worked.
  return TRUE;
}



/**
* A convenience function to interpret octal permissions, and return
* a human readable string.  Uses the lang() function for translation.
*
* @internal
* @param int The permissions to test.
* @return string
* Rolf: only used in admin/siteprefs.php
*/
function interpret_permissions($perms)
{
  $owner = array();
  $group = array();
  $other = array();

  if( $perms & 0400 )
    {
      $owner[] = lang('read');
    }

  if( $perms & 0200 )
    {
      $owner[] = lang('write');
    }

  if( $perms & 0100 )
    {
      $owner[] = lang('execute');
    }

  if( $perms & 0040 )
    {
      $group[] = lang('read');
    }

  if( $perms & 0020 )
    {
      $group[] = lang('write');
    }

  if( $perms & 0010 )
    {
      $group[] = lang('execute');
    }

  if( $perms & 0004 )
    {
      $other[] = lang('read');
    }

  if( $perms & 0002 )
    {
      $other[] = lang('write');
    }

  if( $perms & 0001 )
    {
      $other[] = lang('execute');
    }

  return array($owner,$group,$other);
}



/**
* A convenience function to return a boolean variable given a php ini key that represents a boolean
*
* @param string  The php ini key
* @return integer
* Rolf: only used in admin/header.php
*/
function ini_get_boolean($str)
{
  $val1 = ini_get($str);
  $val2 = strtolower($val1);

  $ret = 0;
  if( $val2 == 1 || $val2 == '1' || $val2 == 'yes' || $val2 == 'true' || $val2 == 'on' )
     $ret = 1;
  return $ret;
}



/**
* Another convenience function to output a human readable function stack trace
*
* @return void
*/
function stack_trace()
{
  $stack = debug_backtrace();
  foreach( $stack as $elem )
    {
      if( $elem['function'] == 'stack_trace' ) continue;
      if( isset($elem['file'])  )
    {
      echo $elem['file'].':'.$elem['line'].' - '.$elem['function'].'<br/>';
    }
      else
    {
      echo ' - '.$elem['function'].'<br/>';
    }
    }
}



/**
* A wrapper around move_uploaded_file that attempts to ensure permissions on uploaded
* files are set correctly.
*
* @param string The temporary file specification
* @param string The destination file specification
* @return boolean.
*/
function cms_move_uploaded_file( $tmpfile, $destination )
{
   $config = cmsms()->GetConfig();

   if( !@move_uploaded_file( $tmpfile, $destination ) )
   {
      return false;
   }

   @chmod($destination,octdec($config['default_upload_permission']));
   return true;
}



/**
* A function to read CSS cache information
*
* @deprecated
* @internal
* @param string Filename containing cash information
* @return array of css cache information
* Rolf: only used in admin/editcss.php
*/
function csscache_csvfile_to_hash($filename)
{
  if( !is_readable($filename) ) return false;
  $tmp = @file($filename);
  if( !is_array($tmp) || !count($tmp) ) return false;

  $result = array();
  foreach( $tmp as $one )
    {
      $vals = explode(',',trim($one));
      $result[$vals[0]] = $vals[1];
    }
  return $result;
}



/**
* A function to take hash information representing CSS cache data and store it in a CSV file
*
* @deprecated
* @internal
* @param string Filename to output information to
* @param array  Hash of CSS cache information.
* @return void
* Rolf: only used in admin/editcss.php
*/
function csscache_hash_to_csvfile($filename,$hash)
{
  $fh = @fopen($filename,'w');
  if( !$fh ) return false;
  foreach( $hash as $key => $val )
    {
      $key = trim($key); $val = trim($val);
      $line = "$key,$val\n";
      fwrite($fh,$line);
    }
  fclose($fh);
}


/**
* A function to test wether an IP address matches a list of expressions
* Credits to J.Adams <jna@retins.net>
*
* Expressions can be of the form
*   xxx.xxx.xxx.xxx        (exact)
*   xxx.xxx.xxx.[yyy-zzz]  (range)
*   xxx.xxx.xxx.xxx/nn    (nn = # bits, cisco style -- i.e. /24 = class C)
*
* @param string IP address to test
* @param array  Array of match expressions
* @return boolean
* Rolf: only used in lib/content.functions.php
*/
function cms_ipmatches($ip,$checklist)
{
  if( !function_exists('__testip') ) {
  function __testip($range,$ip)
  {
    $result = 1;

    // IP Pattern Matcher
    // J.Adams <jna@retina.net>
    //
    // Matches:
    //
    // xxx.xxx.xxx.xxx        (exact)
    // xxx.xxx.xxx.[yyy-zzz]  (range)
    // xxx.xxx.xxx.xxx/nn    (nn = # bits, cisco style -- i.e. /24 = class C)
    //
    // Does not match:
    // xxx.xxx.xxx.xx[yyy-zzz]  (range, partial octets not supported)

    $regs = array();
    if (preg_match("/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)\/([0-9]+)/",$range,$regs)) {
      // perform a mask match
      $ipl = ip2long($ip);
      $rangel = ip2long($regs[1] . "." . $regs[2] . "." . $regs[3] . "." . $regs[4]);

      $maskl = 0;

      for ($i = 0; $i< 31; $i++) {
    if ($i < $regs[5]-1) {
      $maskl = $maskl + pow(2,(30-$i));
    }
      }

      if (($maskl & $rangel) == ($maskl & $ipl)) {
    return 1;
      } else {
    return 0;
      }
    } else {
      // range based
      $maskocts = explode('.',$range);
      $ipocts = explode('.',$ip);

      if( count($maskocts) != count($ipocts) && count($maskocts) != 4 )
    {
      return 0;
    }

      // perform a range match
      for ($i=0; $i<4; $i++) {
    if (preg_match("/\[([0-9]+)\-([0-9]+)\]/",$maskocts[$i],$regs)) {
      if ( ($ipocts[$i] > $regs[2]) || ($ipocts[$i] < $regs[1])) {
        $result = 0;
      }
    }
    else
      {
        if ($maskocts[$i] <> $ipocts[$i]) {
          $result = 0;
        }
      }
      }
    }
    return $result;
  } // __testip
  } // if

  if( !is_array($checklist) )
    {
      $checklist = explode(',',$checklist);
    }
  foreach( $checklist as $one )
    {
      if( __testip(trim($one),$ip) ) return TRUE;
    }
  return FALSE;
}

/**
* @author    Dominic Sayers <dominic_sayers@hotmail.com>
* @copyright    2009 Dominic Sayers
* @license    http://www.opensource.org/licenses/cpal_1.0 Common Public Attribution License Version 1.0 (CPAL) license
* @link    http://www.dominicsayers.com/isemail
* @version    1.9 - Minor modifications to make it compatible with PHPLint
* @return boolean
* @param string  $email
* @param boolean $checkDNS
*/
function is_email( $email, $checkDNS=false ) {
    // Check that $email is a valid address. Read the following RFCs to understand the constraints:
    //     (http://tools.ietf.org/html/rfc5322)
    //     (http://tools.ietf.org/html/rfc3696)
    //     (http://tools.ietf.org/html/rfc5321)
    //     (http://tools.ietf.org/html/rfc4291#section-2.2)
    //     (http://tools.ietf.org/html/rfc1123#section-2.1)

    // the upper limit on address lengths should normally be considered to be 256
    //     (http://www.rfc-editor.org/errata_search.php?rfc=3696)
    //     NB I think John Klensin is misreading RFC 5321 and the the limit should actually be 254
    //     However, I will stick to the published number until it is changed.
    //
    // The maximum total length of a reverse-path or forward-path is 256
    // characters (including the punctuation and element separators)
    //     (http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3)
    $emailLength = strlen($email);
    if ($emailLength > 256)    return false;    // Too long

    // Contemporary email addresses consist of a "local part" separated from
    // a "domain part" (a fully-qualified domain name) by an at-sign ("@").
    //     (http://tools.ietf.org/html/rfc3696#section-3)
    $atIndex = strrpos($email,'@');

    if ($atIndex === false) return false;    // No at-sign
    if ($atIndex === 0) return false;    // No local part
    if ($atIndex === $emailLength) return false;    // No domain part

    // Sanitize comments
    // - remove nested comments, quotes and dots in comments
    // - remove parentheses and dots from quoted strings
    $braceDepth    = 0;
    $inQuote    = false;
    $escapeThisChar    = false;

    for ($i = 0; $i < $emailLength; ++$i) {
        $char = $email[$i];
        $replaceChar = false;

        if ($char === '\\') {
            $escapeThisChar = !$escapeThisChar;    // Escape the next character?
        } else {
            switch ($char) {
            case '(':
                if ($escapeThisChar) {
                    $replaceChar = true;
                } else {
                    if ($inQuote) {
                        $replaceChar = true;
                    } else {
                        if ($braceDepth++ > 0) $replaceChar = true;    // Increment brace depth
                    }
                }

                break;
            case ')':
                if ($escapeThisChar) {
                    $replaceChar = true;
                } else {
                    if ($inQuote) {
                        $replaceChar = true;
                    } else {
                        if (--$braceDepth > 0) $replaceChar = true;    // Decrement brace depth
                        if ($braceDepth < 0) $braceDepth = 0;
                    }
                }

                break;
            case '"':
                if ($escapeThisChar) {
                    $replaceChar = true;
                } else {
                    if ($braceDepth === 0) {
                        $inQuote = !$inQuote;    // Are we inside a quoted string?
                    } else {
                        $replaceChar = true;
                    }
                }

                break;
            case '.':    // Dots don't help us either
                if ($escapeThisChar) {
                    $replaceChar = true;
                } else {
                    if ($braceDepth > 0) $replaceChar = true;
                }

                break;
            default:
            }

            $escapeThisChar = false;
            if ($replaceChar) $email[$i] = 'x';    // Replace the offending character with something harmless
        }
    }

    $localPart    = substr($email, 0, $atIndex);
    $domain        = substr($email, $atIndex + 1);
    $FWS        = "(?:(?:(?:[ \\t]*(?:\\r\\n))?[ \\t]+)|(?:[ \\t]+(?:(?:\\r\\n)[ \\t]+)*))";    // Folding white space
    // Let's check the local part for RFC compliance...
    //
    // local-part      =       dot-atom / quoted-string / obs-local-part
    // obs-local-part  =       word *("." word)
    //     (http://tools.ietf.org/html/rfc5322#section-3.4.1)
    //
    // Problem: need to distinguish between "first.last" and "first"."last"
    // (i.e. one element or two). And I suck at regexes.
    $dotArray = preg_split('/\\.(?=(?:[^\\"]*\\"[^\\"]*\\")*(?![^\\"]*\\"))/m', $localPart);
    $partLength    = 0;

    foreach ($dotArray as $element) {
        // Remove any leading or trailing FWS
        $element = preg_replace("/^$FWS|$FWS\$/", '', $element);

        // Then we need to remove all valid comments (i.e. those at the start or end of the element
        $elementLength = strlen($element);

        if ($element[0] === '(') {
            $indexBrace = strpos($element, ')');
            if ($indexBrace !== false) {
                if (preg_match('/(?<!\\\\)[\\(\\)]/', substr($element, 1, $indexBrace - 1)) > 0) {
                    return false;    // Illegal characters in comment
                }
                $element = substr($element, $indexBrace + 1, $elementLength - $indexBrace - 1);
                $elementLength = strlen($element);
            }
        }

        if ($element[$elementLength - 1] === ')') {
            $indexBrace = strrpos($element, '(');
            if ($indexBrace !== false) {
                if (preg_match('/(?<!\\\\)(?:[\\(\\)])/', substr($element, $indexBrace + 1, $elementLength - $indexBrace - 2)) > 0) {
                    return false;    // Illegal characters in comment
                }
                $element = substr($element, 0, $indexBrace);
                $elementLength = strlen($element);
            }
        }

        // Remove any leading or trailing FWS around the element (inside any comments)
        $element = preg_replace("/^$FWS|$FWS\$/", '', $element);

        // What's left counts towards the maximum length for this part
        if ($partLength > 0) $partLength++;    // for the dot
        $partLength += strlen($element);

        // Each dot-delimited component can be an atom or a quoted string
        // (because of the obs-local-part provision)
        if (preg_match('/^"(?:.)*"$/s', $element) > 0) {
            // Quoted-string tests:
            //
            // Remove any FWS
            $element = preg_replace("/(?<!\\\\)$FWS/", '', $element);
            // My regex skillz aren't up to distinguishing between \" \\" \\\" \\\\" etc.
            // So remove all \\ from the string first...
            $element = preg_replace('/\\\\\\\\/', ' ', $element);
            if (preg_match('/(?<!\\\\|^)["\\r\\n\\x00](?!$)|\\\\"$|""/', $element) > 0)    return false;    // ", CR, LF and NUL must be escaped, "" is too short
        } else {
            // Unquoted string tests:
            //
            // Period (".") may...appear, but may not be used to start or end the
            // local part, nor may two or more consecutive periods appear.
            //     (http://tools.ietf.org/html/rfc3696#section-3)
            //
            // A zero-length element implies a period at the beginning or end of the
            // local part, or two periods together. Either way it's not allowed.
            if ($element === '') return false;    // Dots in wrong place

            // Any ASCII graphic (printing) character other than the
            // at-sign ("@"), backslash, double quote, comma, or square brackets may
            // appear without quoting.  If any of that list of excluded characters
            // are to appear, they must be quoted
            //     (http://tools.ietf.org/html/rfc3696#section-3)
            //
            // Any excluded characters? i.e. 0x00-0x20, (, ), <, >, [, ], :, ;, @, \, comma, period, "
            if (preg_match('/[\\x00-\\x20\\(\\)<>\\[\\]:;@\\\\,\\."]/', $element) > 0) return false;    // These characters must be in a quoted string
        }
    }

    if ($partLength > 64) return false;    // Local part must be 64 characters or less

    // Now let's check the domain part...
    // The domain name can also be replaced by an IP address in square brackets
    //     (http://tools.ietf.org/html/rfc3696#section-3)
    //     (http://tools.ietf.org/html/rfc5321#section-4.1.3)
    //     (http://tools.ietf.org/html/rfc4291#section-2.2)
    if (preg_match('/^\\[(.)+]$/', $domain) === 1) {
        // It's an address-literal
        $addressLiteral = substr($domain, 1, strlen($domain) - 2);
        $matchesIP = array();

        // Extract IPv4 part from the end of the address-literal (if there is one)
        if (preg_match('/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', $addressLiteral, $matchesIP) > 0) {
            $index = strrpos($addressLiteral, $matchesIP[0]);

            if ($index === 0) {
                // Nothing there except a valid IPv4 address, so...
                return true;
            } else {
                // Assume it's an attempt at a mixed address (IPv6 + IPv4)
                if ($addressLiteral[$index - 1] !== ':') return false;    // Character preceding IPv4 address must be ':'
                if (substr($addressLiteral, 0, 5) !== 'IPv6:') return false;    // RFC5321 section 4.1.3
                $IPv6 = substr($addressLiteral, 5, ($index ===7) ? 2 : $index - 6);
                $groupMax = 6;
            }
        } else {
            // It must be an attempt at pure IPv6
            if (substr($addressLiteral, 0, 5) !== 'IPv6:') return false;    // RFC5321 section 4.1.3
            $IPv6 = substr($addressLiteral, 5);
            $groupMax = 8;
        }

        $groupCount    = preg_match_all('/^[0-9a-fA-F]{0,4}|\\:[0-9a-fA-F]{0,4}|(.)/', $IPv6, $matchesIP);
        $index = strpos($IPv6,'::');

        if ($index === false) {
            // We need exactly the right number of groups
            if ($groupCount !== $groupMax) return false;    // RFC5321 section 4.1.3
        } else {
            if ($index !== strrpos($IPv6,'::')) return false;    // More than one '::'
            $groupMax = ($index === 0 || $index === (strlen($IPv6) - 2)) ? $groupMax : $groupMax - 1;
            if ($groupCount > $groupMax) return false;    // Too many IPv6 groups in address
        }

        // Check for unmatched characters
        array_multisort($matchesIP[1], SORT_DESC);
        if ($matchesIP[1][0] !== '') return false;    // Illegal characters in address

        // It's a valid IPv6 address, so...
        return true;
    } else {
        // It's a domain name...

        // The syntax of a legal Internet host name was specified in RFC-952
        // One aspect of host name syntax is hereby changed: the
        // restriction on the first character is relaxed to allow either a
        // letter or a digit.
        //     (http://tools.ietf.org/html/rfc1123#section-2.1)
        //
        // NB RFC 1123 updates RFC 1035, but this is not currently apparent from reading RFC 1035.
        //
        // Most common applications, including email and the Web, will generally not
        // permit...escaped strings
        //     (http://tools.ietf.org/html/rfc3696#section-2)
        //
        // the better strategy has now become to make the "at least one period" test,
        // to verify LDH conformance (including verification that the apparent TLD name
        // is not all-numeric)
        //     (http://tools.ietf.org/html/rfc3696#section-2)
        //
        // Characters outside the set of alphabetic characters, digits, and hyphen MUST NOT appear in domain name
        // labels for SMTP clients or servers
        //     (http://tools.ietf.org/html/rfc5321#section-4.1.2)
        //
        // RFC5321 precludes the use of a trailing dot in a domain name for SMTP purposes
        //     (http://tools.ietf.org/html/rfc5321#section-4.1.2)
        $dotArray = preg_split('/\\.(?=(?:[^\\"]*\\"[^\\"]*\\")*(?![^\\"]*\\"))/m', $domain);
        $partLength = 0;
        if (count($dotArray) === 1) return false;    // Mail host can't be a TLD

        foreach ($dotArray as $element) {
            // Remove any leading or trailing FWS
            $element = preg_replace("/^$FWS|$FWS\$/", '', $element);

            // Then we need to remove all valid comments (i.e. those at the start or end of the element
            $elementLength = strlen($element);

            if ($element[0] === '(') {
                $indexBrace = strpos($element, ')');
                if ($indexBrace !== false) {
                    if (preg_match('/(?<!\\\\)[\\(\\)]/', substr($element, 1, $indexBrace - 1)) > 0) {
                        return false;    // Illegal characters in comment
                    }
                    $element = substr($element, $indexBrace + 1, $elementLength - $indexBrace - 1);
                    $elementLength = strlen($element);
                }
            }

            if ($element[$elementLength - 1] === ')') {
                $indexBrace = strrpos($element, '(');
                if ($indexBrace !== false) {
                    if (preg_match('/(?<!\\\\)(?:[\\(\\)])/', substr($element, $indexBrace + 1, $elementLength - $indexBrace - 2)) > 0) {
                        return false;    // Illegal characters in comment
                    }
                    $element = substr($element, 0, $indexBrace);
                    $elementLength = strlen($element);
                }
            }

            // Remove any leading or trailing FWS around the element (inside any comments)
            $element = preg_replace("/^$FWS|$FWS\$/", '', $element);

            // What's left counts towards the maximum length for this part
            if ($partLength > 0) $partLength++;    // for the dot
            $partLength += strlen($element);

            // The DNS defines domain name syntax very generally -- a
            // string of labels each containing up to 63 8-bit octets,
            // separated by dots, and with a maximum total of 255
            // octets.
            //     (http://tools.ietf.org/html/rfc1123#section-6.1.3.5)
            if ($elementLength > 63) return false;    // Label must be 63 characters or less

            // Each dot-delimited component must be atext
            // A zero-length element implies a period at the beginning or end of the
            // local part, or two periods together. Either way it's not allowed.
            if ($elementLength === 0) return false;    // Dots in wrong place

            // Any ASCII graphic (printing) character other than the
            // at-sign ("@"), backslash, double quote, comma, or square brackets may
            // appear without quoting.  If any of that list of excluded characters
            // are to appear, they must be quoted
            //     (http://tools.ietf.org/html/rfc3696#section-3)
            //
            // If the hyphen is used, it is not permitted to appear at
            // either the beginning or end of a label.
            //     (http://tools.ietf.org/html/rfc3696#section-2)
            //
            // Any excluded characters? i.e. 0x00-0x20, (, ), <, >, [, ], :, ;, @, \, comma, period, "
            //if (preg_match('/[\\x00-\\x20\\(\\)<>\\[\\]:;@\\\\,\\."]|^-|-$/', $element) > 0) {
            if (preg_match('/[\\x00-\\x20\\(\\)<>\\[\\]:;@\\\\,\\."]$/', $element) > 0) {
                return false;
            }
        }

        if ($partLength > 255) return false;    // Local part must be 64 characters or less
        if (preg_match('/^[0-9]+$/', $element) > 0)    return false;    // TLD can't be all-numeric

        // Check DNS?
        if ($checkDNS && function_exists('checkdnsrr')) {
            if (!(checkdnsrr($domain, 'A') || checkdnsrr($domain, 'MX'))) {
                return false;    // Domain doesn't actually exist
            }
        }
    }

    // Eliminate all other factors, and the one which remains must be the truth.
    // (Sherlock Holmes, The Sign of Four)
    return true;
}



/**
* A convenience method to output the secure param tag that is used on all admin links
*
* @internal
* @access private
* @return string
* Rolf: only used in admin/imagefiles.php
*/
function get_secure_param()
{
  $urlext = '?';
  $str = strtolower(ini_get('session.use_cookies'));
  if( $str == '0' || $str == 'off' ) {
    $urlext .= htmlspecialchars(SID).'&';
  }
  $urlext .= CMS_SECURE_PARAM_NAME.'='.$_SESSION[CMS_USER_KEY];
  return $urlext;
}



/**
* Rolf: only used in lib/classes/contenttypes/Content.inc.php
*/
function cms_to_bool($str)
{
  if( is_numeric($str) ) return ((int)$str != 0)?TRUE:FALSE;
  $str = strtolower($str);
  if( $str == 'y' || $str == 'yes' || $str == 'true' || $str == 'on' || $str === '1' ) return TRUE;
  return FALSE;
}



/**
*
*/
function cms_get_jquery($exclude = '',$ssl = null,$cdn = false,$append = '',$custom_root='')
{
  $config = cms_config::get_instance();
  $scripts = array();
  $base_url = $config['root_url'];
  if( is_null($ssl) ) {
    $base_url = $config->smart_root_url();
  }
  else if( $ssl === true || $ssl === TRUE ) {
    $base_url = $config['ssl_url'];
  }
  $basePath=$custom_root!=''?trim($custom_root,'/'):$base_url;

  // Scripts to include
  $scripts['jquery.min.js'] = '<script type="text/javascript" src="'.($cdn?'https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js':$basePath.'/lib/jquery/js/jquery-1.11.0.min.js').'"></script>'."\n"
  . '<script type="text/javascript" src="' . $basePath .'/lib/jquery/js/jquery-migrate-1.2.1.min.js"></script>' . "\n";
  $scripts['jquery-ui.min.js'] = '<script type="text/javascript" src="'.($cdn?'https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js':$basePath.'/lib/jquery/js/jquery-ui-1.10.4.custom.min.js').'"></script>'."\n";
  $scripts['jquery.ui.nestedSortable.js'] = '<script type="text/javascript" src="'.$basePath.'/lib/jquery/js/jquery.ui.nestedSortable-1.3.4.js"></script>'."\n";
  $scripts['jquery.json.min.js'] = '<script type="text/javascript" src="'.$basePath.'/lib/jquery/js/jquery.json-2.3.min.js"></script>'."\n";

  // Check if we need exclude some script
  if(!empty($exclude)) {

    $exclude_list = explode(",", trim(str_replace(' ','',$exclude)));
    foreach($exclude_list as $one) {
      if ($one == 'jquery-1.6.2.min.js') {
          $one = 'jquery.min.js';
      }
      if ($one == 'jquery-ui-1.8.14.min.js') {
          $one = 'jquery-ui.min.js';
      }
      if ($one == 'jquery.json-2.2.js') {
          $one = 'jquery.json.min.js';
      }
      if ($one == 'jquery.ui.nestedSortable-1.3.4.js') {
          $one = 'jquery.ui.nestedSortable.js';
      }

      unset($scripts[$one]);
    }
  }
  // let them add scripts to the end ie: a jQuery plugin
  if(!empty($append)) {
    $append_list = explode(",", trim(str_replace(' ','',$append)));
    foreach($append_list as $key => $item) {
      $scripts['user_'+$key]='<script type="text/javascript" src="'.($item).'"></script>'."\n";;
    }
  }
  // Output

  $output = '';
  foreach($scripts as $script) {
    $output .= $script;
  }
  return $output;
}



/**
* Rolf: only used in lib/classes/class.CMSModule.php
*/
if(!function_exists('get_called_class')) {
  function get_called_class() {
    try {
      return cms_function_help::get_called_class();
    }
    catch( Exception $e ) {
      // ignore
    }
  }
  // this class must exist in this file until CMSMS 1.12 when we dont have to worry abut PHP 5.2
  // this file is loaded before the autoloader runs.
  class cms_function_help {

    public static function get_called_class($bt = false,$l = 1)
    {
      if (!$bt) $bt = debug_backtrace();
      if (!isset($bt[$l])) throw new Exception("Cannot find called class -> stack level too deep.");
      if (!isset($bt[$l]['type'])) {
        if( $l >= 2 ) {
      throw new Exception ('type not set');
        }
        else {
          return self::get_called_class($bt,$l+1);
        }
      }
      else switch ($bt[$l]['type']) {
      case '::':
    $lines = file($bt[$l]['file']);
    $i = 0;
    $callerLine = '';
    do {
      $i++;
      $callerLine = $lines[$bt[$l]['line']-$i] . $callerLine;
    } while (stripos($callerLine,$bt[$l]['function']) === false);
    preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['function'].'/',
           $callerLine,
           $matches);
    if (!isset($matches[1])) {

      // must be an edge case.
      throw new Exception ("Could not find caller class: originating method call is obscured.");
    }
    switch ($matches[1]) {
    case 'self':
    case 'parent':
      return self::get_called_class($bt,$l+1);
    default:
      return $matches[1];
    }
    // won't get here.
      case '->': switch ($bt[$l]['function']) {
    case '__get':
      // edge case -> get class of calling object
      if (!is_object($bt[$l]['object'])) throw new Exception ("Edge case fail. __get called on non object.");
      return get_class($bt[$l]['object']);
    default: return $bt[$l]['class'];
    }

      default: throw new Exception ("Unknown backtrace method type");
      }
    }
  }
}

# vim:ts=4 sw=4 noet
?>
#6
bjr jce,
j'ai cette erreur lors de l'étape mise à jour .des que je choisis la langue (fr_FR) et que je valide
Fatal error: Class 'CmsApp' not found in C:\wamp\www\v2\lib\misc.functions.php on line 208
Code :
<?php
#CMS - CMS Made Simple
#(c)2004-2012 by Ted Kulp (wishy@users.sf.net)
#This project's homepage is: http://www.cmsmadesimple.org
#
#This program is free software; you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation; either version 2 of the License, or
#(at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
#$Id: misc.functions.php 9859 2015-03-28 16:16:09Z calguy1000 $

/**
* Misc functions
*
* @package CMS
*/



/**
* Redirects to relative URL on the current site
*
* @author http://www.edoceo.com/
* @since 0.1
* @param string The url to redirect to
* @return void
*/
function redirect($to, $noappend=false)
{
  $_SERVER['PHP_SELF'] = null;

  $schema = 'http';

  if( class_exists('CmsApp'))
  {
      if( cmsms()->is_https_request() ) $schema = 'https';
  }
  else
  {
    if( isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off' ) $schema = 'https';
  }

  $host = strlen($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']:$_SERVER['SERVER_NAME'];

    $components = parse_url($to);
    if(count($components) > 0)
    {
        $to =  (isset($components['scheme']) && startswith($components['scheme'], 'http') ? $components['scheme'] : $schema) . '://';
        $to .= isset($components['host']) ? $components['host'] : $host;
        $to .= isset($components['port']) ? ':' . $components['port'] : '';
        if(isset($components['path']))
        {
            if(in_array(substr($components['path'],0,1),array('\\','/')))//Path is absolute, just append.
            {
                $to .= $components['path'];
            }
            //Path is relative, append current directory first.
            else if (isset($_SERVER['PHP_SELF']) && !is_null($_SERVER['PHP_SELF'])) //Apache
            {
                $to .= (strlen(dirname($_SERVER['PHP_SELF'])) > 1 ?  dirname($_SERVER['PHP_SELF']).'/' : '/') . $components['path'];
            }
            else if (isset($_SERVER['REQUEST_URI']) && !is_null($_SERVER['REQUEST_URI'])) //Lighttpd
            {
                if (endswith($_SERVER['REQUEST_URI'], '/'))
                    $to .= (strlen($_SERVER['REQUEST_URI']) > 1 ? $_SERVER['REQUEST_URI'] : '/') . $components['path'];
                else
                    $to .= (strlen(dirname($_SERVER['REQUEST_URI'])) > 1 ? dirname($_SERVER['REQUEST_URI']).'/' : '/') . $components['path'];
            }
        }
        $to .= isset($components['query']) ? '?' . $components['query'] : '';
        $to .= isset($components['fragment']) ? '#' . $components['fragment'] : '';
    }
    else
    {
        $to = $schema."://".$host."/".$to;
    }

    session_write_close();

    $debug = false;
    if( class_exists('CmsApp') )
      {
    $config = cmsms()->GetConfig();
    $debug = $config['debug'];
      }

    if (headers_sent() && !$debug)
    {
        // use javascript instead
        echo '<script type="text/javascript">
            <!--
                location.replace("'.$to.'");
            // -->
            </script>
            <noscript>
                <meta http-equiv="Refresh" content="0;URL='.$to.'">
            </noscript>';
        exit;

    }
    else
    {
        if ( $debug )
        {
            echo "Debug is on.  Redirecting disabled...  Please click this link to continue.<br />";
            echo "<a href=\"".$to."\">".$to."</a><br />";
            echo '<div id="DebugFooter">';
            global $sql_queries;
            if (FALSE == empty($sql_queries))
              {
                echo "<div>".$sql_queries."</div>\n";
              }
            foreach (cmsms()->get_errors() as $error)
            {
                echo $error;
            }
            echo '</div> <!-- end DebugFooter -->';
            exit();
        }
        else
        {
            header("Location: $to");
            exit();
        }
    }
}



/**
* Given a page ID or an alias, redirect to it
* Retrieves the URL of the specified page, and performs a redirect
*
* @param mixed An integer page id or a string page alias.
* @return void
*/
function redirect_to_alias($alias)
{
  $manager = cmsms()->GetHierarchyManager();
  $node = $manager->sureGetNodeByAlias($alias);
  if( !$node ) {
    // put mention into the admin log
    audit('','Core','Attempt to redirect to invalid alias: '.$alias);
    return;
  }
  $content = $node->GetContent();
  if (!is_object($content)) {
    audit('','Core','Attempt to redirect to invalid alias: '.$alias);
    return;
  }
  if ($content->GetURL() != '') {
    redirect($content->GetURL());
  }
}



/**
* Calculate the difference in seconds between two microtime() values
*
* @since 0.3
* @param string Microtime value A
* @param string Microtime value B
* @return integer The difference.
*/
function microtime_diff($a, $b) {
    list($a_dec, $a_sec) = explode(" ", $a);
    list($b_dec, $b_sec) = explode(" ", $b);
    return $b_sec - $a_sec + $b_dec - $a_dec;
}



/**
* Joins a path together using proper directory separators
* Taken from: http://www.php.net/manual/en/ref.dir.php
*
* This method accepts a variable number of string arguments.
*
* @since 0.14
* @return string
*/
function cms_join_path()
{
    $args = func_get_args();
        return implode(DIRECTORY_SEPARATOR,$args);
}



/**
* Return the global cmsms() object
*
* @since 1.7
* @return object
*/
function &cmsms()
{
   return CmsApp::get_instance();
}



/**
* Shows a very close approximation of an Apache generated 404 error.
*
* Shows a very close approximation of an Apache generated 404 error.
* It also sends the actual header along as well, so that generic
* browser error pages (like what IE does) will be displayed.
*
* @since 0.3
* @deprecated
* @internal
* Rolf: function used in /index.php
*/
function ErrorHandler404()
{
        @ob_end_clean();
        header("HTTP/1.0 404 Not Found");
        header("Status: 404 Not Found");
        echo '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>';
        exit();
}



/**
* A method to perform HTML entity conversion on a string
*
* @see htmlentities
* @param string The input string
* @param string A flag indicating how quotes should be handled (see htmlentities) (ignored)
* @param string The input character set (ignored)
* @param boolean A flag indicating wether single quotes should be converted to entities.
* @return string the converted string.
*/
function cms_htmlentities($val, $param=ENT_QUOTES, $charset="UTF-8", $convert_single_quotes = false)
{
  if ($val == "") return "";

  $val = str_replace( " ", " ", $val );
  $val = str_replace( "&"            , "&amp;"         , $val );
  $val = str_replace( "<!--"         , "<!--"  , $val );
  $val = str_replace( "-->"          , "-->"       , $val );
  $val = preg_replace( "/<script/i"  , "<script"   , $val );
  $val = str_replace( ">"            , "&gt;"          , $val );
  $val = str_replace( "<"            , "&lt;"          , $val );
  $val = str_replace( "\""           , "&quot;"        , $val );
  $val = preg_replace( "/\\$/"      , "$"        , $val );
  $val = str_replace( "!"            , "!"         , $val );
  $val = str_replace( "'"            , "'"         , $val );

  if ($convert_single_quotes)
    {
      $val = str_replace("\\'", "&apos;", $val);
      $val = str_replace("'", "&apos;", $val);
    }

  return $val;
}



/**
* @ignore
*/
define('CLEANED_FILENAME','BAD_FILE');



/**
* Clean up the filename, and ensure that the filename resides underneath
* the cms_root directory, if it does not replace it with the hardcoded
* string CLEANED_FILENAME
*
* @internal
* @param string The complete file specification
* @return string the cleaned file path.
* Rolf: only used in this file
*/
function cms_cleanfile($filename)
{
    $realpath = realpath($filename);
    if( $realpath === FALSE ) {
        return CLEANED_FILENAME;
    }

    // This ensures that the file specified is somewhere
    // underneath the cms root path
    $config = cmsms()->GetConfig();
    if( strpos($realpath, $config['root_path']) !== 0 ) {
        return CLEANED_FILENAME;
    }
    return $realpath;
}




/**
* A replacement for the built in htmlentities method.
*
* @ignore
* @deprecated
* @param string  input string
* @param boolean A flag wether or not to handle single quotes.
* @return string
*/
function my_htmlentities($val, $convert_single_quotes = false)
{
  return cms_htmlentities($val,ENT_QUOTES,'UTF-8',$convert_single_quotes);
}



/**
* A method to convert a string into UTF-8 entities
*
* @internal
* @deprecated
* @param string Input string
* @return string
* Rolf: used in admin/listmodules.php
*/
function cms_utf8entities($val)
{
    if ($val == "")
    {
        return "";
    }
    $val = str_replace( " ", " ", $val );
    $val = str_replace( "&"            , "\u0026"         , $val );
    $val = str_replace( ">"            , "\u003E"          , $val );
    $val = str_replace( "<"            , "\u003C"          , $val );


    $val = str_replace( "\""           , "\u0022"        , $val );
    $val = str_replace( "!"            , "\u0021"         , $val );
    $val = str_replace( "'"            , "\u0027"         , $val );

    return $val;
}



/**
* A function to put a backtrace into the generated log file.
*
* @see debug_to_log, debug_bt
* @return void
* Rolf: Looks like not used
*/
function debug_bt_to_log()
{
    if( cmsms()->config['debug_to_log'] || (function_exists('check_login') && check_login(TRUE)) ) {
        $bt=debug_backtrace();
        $file = $bt[0]['file'];
        $line = $bt[0]['line'];

        $out = array();
        $out[] = "Backtrace in $file on line $line";

        $bt = array_reverse($bt);
        foreach($bt as $trace) {
            if( $trace['function'] == 'debug_bt_to_log' ) continue;

            $file = $line = '';
            if( isset($trace['file']) ) $file = $trace['file'];
            if( isset($trace['line']) ) $line = $trace['line'];
            $function = $trace['function'];
            $out[] = "$function at $file:$line";
        }

        $filename = TMP_CACHE_LOCATION . '/debug.log';
        foreach ($out as $txt) {
            error_log($txt . "\n", 3, $filename);
        }
    }
}



/**
* A function to generate a backtrace in a readable format.
*
* @return void
* Rolf: looks like not used
*/
function debug_bt()
{
    $bt=debug_backtrace();
    $file = $bt[0]['file'];
    $line = $bt[0]['line'];

    echo "\n\n<p><b>Backtrace in $file on line $line</b></p>\n";

    $bt = array_reverse($bt);
    echo "<pre><dl>\n";
    foreach($bt as $trace)
    {
        $file = $trace['file'];
        $line = $trace['line'];
        $function = $trace['function'];
        $args = implode(',', $trace['args']);
        echo "
        <dt><b>$function</b>($args) </dt>
        <dd>$file on line $line</dd>
        ";
    }
    echo "</dl></pre>\n";
}



/**
* Debug function to display $var nicely in html.
*
* @param mixed $var
* @param string $title (optional)
* @param boolean $echo_to_screen (optional)
* @return string
*/
function debug_display($var, $title="", $echo_to_screen = true, $use_html = true)
{
    $variables =& cmsms()->variables;

    $starttime = microtime();
    if (isset($variables['starttime']))
        $starttime = $variables['starttime'];
    else
        $variables['starttime'] = $starttime;

    $titleText = "Debug: ";
    if($title)
    {
        $titleText = "Debug display of '$title':";
    }
    $titleText .= '(' . microtime_diff($starttime,microtime()) . ')';

    if (function_exists('memory_get_usage'))
    {
      $titleText .= ' - (usage: '.memory_get_usage().')';
    }

    $memory_peak = (function_exists('memory_get_peak_usage')?memory_get_peak_usage():'');
    if( $memory_peak )
      {
        $titleText .= ' - (peak: '.$memory_peak.')';
      }

    ob_start();
    if ($use_html)
      {
        echo "<div><b>$titleText</b>\n";
      }
    else
      {
        echo "$titleText\n";
      }

    if(FALSE == empty($var))
    {
        if ($use_html)
        {
            echo '<pre>';
        }
        if(is_array($var))
        {
            echo "Number of elements: " . count($var) . "\n";
            print_r($var);
        }
        elseif(is_object($var))
        {
            print_r($var);
        }
        elseif(is_string($var))
        {
          if( $use_html )
            {
            print_r(htmlentities(str_replace("\t", '  ', $var)));
            }
          else
            {
              print_r($var);
            }
        }
        elseif(is_bool($var))
        {
            echo $var === true ? 'true' : 'false';
        }
        else
        {
            print_r($var);
        }
        if ($use_html)
        {
            echo '</pre>';
        }
    }
    if ($use_html)
        echo "</div>\n";

    $output = ob_get_contents();
    ob_end_clean();

    if($echo_to_screen)
    {
      echo $output;
    }

    return $output;
}



/**
* Display $var nicely only if $config["debug"] is set
*
* @param mixed $var
* @param string $title
*/
function debug_output($var, $title="")
{
  if(cmsms()->config["debug"] == true)
    {
        debug_display($var, $title, true);
    }

}



/**
* Debug function to output debug information about a variable in a formatted matter
* to a debug file.
*
* @param mixed data to display
* @param string Optional title.
*/
function debug_to_log($var, $title='',$filename = '')
{
    if( cmsms()->config['debug_to_log'] || (function_exists('check_login') && check_login(TRUE)) ) {
        if( $filename == '' ) {
            $filename = TMP_CACHE_LOCATION . '/debug.log';
            $x = @filemtime($filename);
            if( $x !== FALSE && $x < (time() - 24 * 3600) ) @unlink($filename);
        }
        $errlines = explode("\n",debug_display($var, $title, false, false));
        foreach ($errlines as $txt) {
            error_log($txt . "\n", 3, $filename);
        }
    }
}



/**
* Display $var nicely to the cmsms()->errors array if $config['debug'] is set
*
* @param mixed $var
* @param string $title
*/
function debug_buffer($var, $title="")
{
  $config = cmsms()->GetConfig();
  if($config["debug"] == true)
    {
      cmsms()->add_error(debug_display($var, $title, false, true));
    }
}



/**
* Debug an sql command
*
* @internal
* @param string SQL query
* @param boolean (unused)
* Rolf: only used in lib/adodb.functions.php
*/
function debug_sql($str, $newline = false)
{
  $config = cmsms()->GetConfig();
  if($config["debug"] == true)
    {
      cmsms()->add_error(debug_display($str, '', false, true));
    }
}



/**
* Retrieve value from $_REQUEST. Returns $default_value if
*        value is not in $_REQUEST or is not the same basic type as
*        $default_value.
*        If $session_key is set, then will return session value in preference
*        to $default_value if $_REQUEST[$value] is not set.
*
* @param string $value
* @param mixed $default_value (optional)
* @param string $session_key (optional)
* @deprecated
* @return mixed
* Rolf: looks like not used
*/
function get_request_value($value, $default_value = '', $session_key = '')
{
    if($session_key != '')
    {
        if(isset($_SESSION['request_values'][$session_key][$value]))
        {
            $default_value = $_SESSION['request_values'][$session_key][$value];
        }
    }
    if(isset($_REQUEST[$value]))
    {
        $result = get_value_with_default($_REQUEST[$value], $default_value);
    }
    else
    {
        $result = $default_value;
    }

    if($session_key != '')
    {
        $_SESSION['request_values'][$session_key][$value] = $result;
    }

    return $result;
}



/**
* Return $value if it's set and same basic type as $default_value,
*            otherwise return $default_value. Note. Also will trim($value)
*            if $value is not numeric.
*
* @param string $value
* @param mixed $default_value
* @deprecated
* @return mixed
* Rolf: only used in this file
*/
function get_value_with_default($value, $default_value = '', $session_key = '')
{
    if($session_key != '')
    {
        if(isset($_SESSION['default_values'][$session_key]))
        {
            $default_value = $_SESSION['default_values'][$session_key];
        }
    }

    // set our return value to the default initially and overwrite with $value if we like it.
    $return_value = $default_value;

    if(isset($value))
    {
        if(is_array($value))
        {
            // $value is an array - validate each element.
            $return_value = array();
            foreach($value as $element)
            {
                $return_value[] = get_value_with_default($element, $default_value);
            }
        }
        else
        {
            if(is_numeric($default_value))
            {
                if(is_numeric($value))
                {
                    $return_value = $value;
                }
            }
            else
            {
                $return_value = trim($value);
            }
        }
    }

    if($session_key != '')
    {
        $_SESSION['default_values'][$session_key] = $return_value;
    }

    return $return_value;
}



/**
* Retrieve the $value from the $parameters array checking for
* $parameters[$value] and $params[$id.$value]. Returns $default
* if $value is not in $params array.
* Note: This function will also trim() string values.
*
* @param array $parameters
* @param string $value
* @param mixed $default_value
* @param string $session_key
* @return mixed
* Rolf: looks like not used
*/
function get_parameter_value($parameters, $value, $default_value = '', $session_key = '')
{
    if($session_key != '')
    {
        if(isset($_SESSION['parameter_values'][$session_key]))
        {
            $default_value = $_SESSION['parameter_values'][$session_key];
        }
    }

    // set our return value to the default initially and overwrite with $value if we like it.
    $return_value = $default_value;
    if(isset($parameters[$value]))
    {
        if(is_bool($default_value))
        {
            // want a boolean return_value
            if(isset($parameters[$value]))
            {
                $return_value = (boolean)$parameters[$value];
            }
        }
        else
        {
            // is $default_value a number?
            $is_number = false;
            if(is_numeric($default_value))
            {
                $is_number = true;
            }

            if(is_array($parameters[$value]))
            {
                // $parameters[$value] is an array - validate each element.
                $return_value = array();
                foreach($parameters[$value] as $element)
                {
                    $return_value[] = get_value_with_default($element, $default_value);
                }
            }
            else
            {
                if(is_numeric($default_value))
                {
                    // default value is a number, we only like $parameters[$value] if it's a number too.
                    if(is_numeric($parameters[$value]))
                    {
                        $return_value = $parameters[$value];
                    }
                }
                elseif(is_string($default_value))
                {
                    $return_value = trim($parameters[$value]);
                }
                else
                {
                    $return_value = $parameters[$value];
                }
            }
        }
    }

    if($session_key != '')
    {
        $_SESSION['parameter_values'][$session_key] = $return_value;
    }

    return $return_value;
}



/**
* A convenience function to create a dropdown control with supported encodings.
*
* @internal
* @param string A name for the control
* @param string The name of the option that should be selected.
* @return string
* Rolf: only used in admin/edittemplate.php
*/
function create_encoding_dropdown($name = 'encoding', $selected = '')
{
    $result = '';

    $encodings = array(''=>'Default','UTF-8'=>'Unicode','ISO-8859-1'=>'Latin 1/West European','ISO-8859-2'=>'Latin 2/Central European','ISO-8859-3'=>'Latin 3/South European','ISO-8859-4'=>'Latin 4/North European','ISO-8859-5'=>'Cyrilic','ISO-8859-6'=>'Arabic','ISO-8859-7'=>'Greek','ISO-8859-8'=>'Hebrew','ISO-8859-9'=>'Latin 5/Turkish','ISO-8859-11'=>'TIS-620/Thai','ISO-8859-14'=>'Latin 8','ISO-8859-15'=>'Latin 9','Big5'=>'Taiwanese','GB2312'=>'Chinese','EUC-JP'=>'Japanese','EUC-KR'=>'Korean','KOI8-R'=>'Russian','Windows-1250'=>'Central Europe','Windows-1251'=>'Cyrilic','Windows-1252'=>'Latin 1','Windows-1253'=>'Greek','Windows-1254'=>'Turkish','Windows-1255'=>'Hebrew','Windows-1256'=>'Arabic','Windows-1257'=>'Baltic','Windows-1258'=>'Vietnam');

    $result .= '<select name="'.$name.'">';
    foreach ($encodings as $key=>$value)
    {
        $result .= '<option value="'.$key.'"';
        if ($selected == $key)
        {
            $result .= ' selected="selected"';
        }
        $result .= '>'.$key.($key!=''?' - ':'').$value.'</option>';
    }
    $result .= '</select>';

    return $result;
}



/**
* A method to remove a permission from the database.
*
* @internal
* @access private
* @param string The permission name
*/
function cms_mapi_remove_permission($permission_name)
{
  $db = cmsms()->GetDB();

  $query = "SELECT permission_id FROM ".cms_db_prefix()."permissions WHERE permission_name = ?";
  $row = &$db->GetRow($query, array($permission_name));

  if ($row)
    {
      $id = $row["permission_id"];

      $query = "DELETE FROM ".cms_db_prefix()."group_perms WHERE permission_id = ?";
      $db->Execute($query, array($id));

      $query = "DELETE FROM ".cms_db_prefix()."permissions WHERE permission_id = ?";
      $db->Execute($query, array($id));
    }
}



/**
* A method to add a permission to the CMSMS permissions table
*
* @internal
* @access private
* @param unknown (ignored)
* @param string  The permission name
* @param string  The permission human readable text.
*/
function cms_mapi_create_permission($cms, $permission_name, $permission_text)
{
  $db = cmsms()->GetDb();

    $query = "SELECT permission_id FROM ".cms_db_prefix()."permissions WHERE permission_name =" . $db->qstr($permission_name);
    $result = $db->Execute($query);

    if ($result && $result->RecordCount() < 1) {

        $new_id = $db->GenID(cms_db_prefix()."permissions_seq");
        $query = "INSERT INTO ".cms_db_prefix()."permissions (permission_id, permission_name, permission_text, create_date, modified_date) VALUES ($new_id, ".$db->qstr($permission_name).",".$db->qstr($permission_text).",".$db->DBTimeStamp(time()).",".$db->DBTimeStamp(time()).")";
        $db->Execute($query);
    }

    if ($result)
    {
        $result->Close();
        return true;
    }
    return false;
}



/**
* A function to test if a file specification matches an array of
* file specifications that indicate it should be excluded
*
* @internal
* @deprecated
* @access private
* @param string Flle specification
* @param array  Array of regular expressions.
* @return boolean
* Rolf: only used in this file
*/
function filespec_is_excluded( $file, $excludes )
{
  // strip the path from the file
  if( empty($excludes) ) return false;
  foreach( $excludes as $excl )
    {
      if( @preg_match( "/".$excl."/i", basename($file) ) )
    {
      return true;
    }
    }
  return false;
}



/**
* Check the permissions of a directory recursively to make sure that
* we have write permission to all files
*
* @param  string  Start directory.
* @return boolean
*/
function is_directory_writable( $path )
{
  if ( substr ( $path , strlen ( $path ) - 1 ) != '/' )
    {
      $path .= '/' ;
    }

  $result = true;
  if( $handle = @opendir( $path ) )
    {
      while( false !== ( $file = readdir( $handle ) ) )
    {
      if( $file == '.' || $file == '..' )
        {
          continue;
        }

      $p = $path.$file;

      if( !@is_writable( $p ) )
        {
          return false;
        }

      if( @is_dir( $p ) )
        {
          $result = is_directory_writable( $p );
          if( !$result )
        {
          return false;
        }
        }
    }
      @closedir( $handle );
    }
  else
    {
      return false;
    }

  return true;
}



/**
* Return an array containing a list of files in a directory
* performs a non recursive search
*
* @internal
* @param path - path to search
* @param extensions - include only files matching these extensions
*                     case insensitive, comma delimited
* Rolf: only used in this file
*/
function get_matching_files($dir,$extensions = '',$excludedot = true,$excludedir = true, $fileprefix='',$excludefiles=1)
{
  $dh = @opendir($dir);
  if( !$dh ) return false;

  if( !empty($extensions) )
    {
      $extensions = explode(',',strtolower($extensions));
    }
  $results = array();
  while( false !== ($file = readdir($dh)) )
    {
      if( $file == '.' || $file == '..' ) continue;
      if( startswith($file,'.') && $excludedot ) continue;
      if( is_dir(cms_join_path($dir,$file)) && $excludedir ) continue;
      if( !empty($fileprefix) )
    {
      if( $excludefiles == 1 && startswith($file,$fileprefix) ) continue;
      if( $excludefiles == 0 && !startswith($file,$fileprefix) ) continue;
    }

      $ext = strtolower(substr($file,strrpos($file,'.')+1));
      if( is_array($extensions) && count($extensions) && !in_array($ext,$extensions) ) continue;

      $results[] = $file;
    }
  closedir($dh);
  if( !count($results) ) return false;
  return $results;
}



/**
* Return an array containing a list of files in a directory
* performs a recursive search
*
* @internal
* @param  string    Start Path.
* @param  array     Array of regular expressions indicating files to exclude.
* @param  int       How deep to browse (-1=unlimited)
* @param  string    "FULL"|"DIRS"|"FILES"
* @param  d         for internal use only
* @return  array
**/
function get_recursive_file_list ( $path , $excludes, $maxdepth = -1 , $mode = "FULL" , $d = 0 )
{
   if ( substr ( $path , strlen ( $path ) - 1 ) != '/' ) { $path .= '/' ; }
   $dirlist = array () ;
   if ( $mode != "FILES" ) { $dirlist[] = $path ; }
   if ( $handle = opendir ( $path ) )
   {
       while ( false !== ( $file = readdir ( $handle ) ) )
       {
     if( $file == '.' || $file == '..' ) continue;
     if( filespec_is_excluded( $file, $excludes ) ) continue;

     $file = $path . $file ;
     if ( ! @is_dir ( $file ) ) { if ( $mode != "DIRS" ) { $dirlist[] = $file ; } }
     elseif ( $d >=0 && ($d < $maxdepth || $maxdepth < 0) )
       {
         $result = get_recursive_file_list ( $file . '/' , $excludes, $maxdepth , $mode , $d + 1 ) ;
         $dirlist = array_merge ( $dirlist , $result ) ;
       }
       }
       closedir ( $handle ) ;
   }
   if ( $d == 0 ) { natcasesort ( $dirlist ) ; }
   return ( $dirlist ) ;
}



/**
* A function to recursively delete all files and folders in a directory
* synonymous with rm -r
*
* @param string The directory name
* @return boolean
*/
function recursive_delete( $dirname )
{
  // all subdirectories and contents:
  if(is_dir($dirname))$dir_handle=opendir($dirname);
  while($file=readdir($dir_handle))
  {
    if($file!="." && $file!="..")
    {
      if(!is_dir($dirname."/".$file))
    {
      if( !@unlink ($dirname."/".$file) )
        {
          closedir( $dir_handle );
          return false;
        }
    }
      else
    {
      recursive_delete($dirname."/".$file);
    }
    }
  }
  closedir($dir_handle);
  if( ! @rmdir($dirname) )
    {
      return false;
    }
  return true;
}



/**
* A function to recursively chmod all files and folders in a directory
*
* @see chmod
* @param string The start location
* @param integer The mode
* Rolf: only used in admin/listmodules.php
*/
function chmod_r( $path, $mode )
{
  if( !is_dir( $path ) )
    return chmod( $path, $mode );

  $dh = @opendir( $path );
  if( !$dh ) return FALSE;

  while( $file = readdir( $dh ) )
  {
    if( $file == '.' || $file == '..' ) continue;

    $p = $path.DIRECTORY_SEPARATOR.$file;
    if( is_dir( $p ) )
    {
      if( !@chmod_r( $p, $mode ) )
    {
      closedir( $dh );
      return false;
    }
    }
    else if( !is_link( $p ) )
    {
      if( !@chmod( $p, $mode ) )
    {
      closedir( $dh );
      return false;
    }
    }
  }
  @closedir( $dh );
  return @chmod( $path, $mode );
}



/**
* A method to serialize an object and encode it for storage or transport.
*
* @internal
* @param object The object to serialize
* @return string
*/
function SerializeObject(&$object)
{
    return base64_encode(serialize($object));
}



/**
* A function unserialize data into an object
*
* @internal
* @param string The serialized text.
* @return object  A valid object on success, or null
* Rolf: only used in admin/editcontent_extra.php
*/
function UnserializeObject(&$serialized)
{
    return  unserialize(base64_decode($serialized));
}



/**
* A convenience function to test wether one string starts with another
*
* i.e:  startswith('The Quick Brown Fox','The');
*
* @param string The string to test against
* @param string The search string
* @return boolean
*/
function startswith( $str, $sub )
{
    return ( substr( $str, 0, strlen( $sub ) ) == $sub );
}



/**
* Similar to the startswith method, this function tests with string A ends with string B
*
* i.e: endswith('The Quick Brown Fox','Fox');
*
* @param string The string to test against
* @param string The search string
* @return boolean
*/
function endswith( $str, $sub )
{
    return ( substr( $str, strlen( $str ) - strlen( $sub ) ) == $sub );
}



/**
* convert a human readable string into something that is suitable for use in URLS
* because many browsers don't support UTF-8 characters in URLS
*
* @internal
* @param string String to convert
* @param boolean indicates whether output string should be converted to lower case
* @param boolean indicates wether slashes should be allowed in the input.
* @return string
*/
function munge_string_to_url($alias, $tolower = false, $withslash = false)
{
    // replacement.php is encoded utf-8 and must be the first modification of alias
    include(dirname(__FILE__) . '/replacement.php');
    $alias = str_replace($toreplace, $replacement, $alias);

    // lowercase only on empty aliases
    if ($tolower == true)
    {
        $alias = strtolower($alias);
    }

    $expr = '/[^a-z0-9-_]+/i';
    if( $withslash )
      {
        $expr = '/[^a-z0-9-_\/]+/i';
      }
    $alias = preg_replace($expr,'-',$alias);

    for( $i = 0; $i < 5; $i++ )
      {
        $tmp = str_replace('--','-',$alias);
        if( $tmp == $alias ) break;
        $alias = $tmp;
      }
    $alias = trim($alias, '-');
    $alias = trim($alias);

    return $alias;
}


/**
* Rolf: only used in admin/style.php
*/
function cms_readfile($filename)
{
  @ob_start();
  echo file_get_contents($filename);
  $result = @ob_get_contents();
  @ob_end_clean();
  if( !empty($result) ) {
    echo $result;
    return TRUE;
  }
  return FALSE;
}


/*
* Sanitize input to prevent against XSS and other nasty stuff.
* Taken from cakephp (http://cakephp.org)
* Licensed under the MIT License
*
* @internal
* @param string input
* @return string
*/
function cleanValue($val) {
    if ($val == "") {
        return $val;
    }
    //Replace odd spaces with safe ones
    $val = str_replace(" ", " ", $val);
    $val = str_replace(chr(0xCA), "", $val);
    //Encode any HTML to entities (including \n --> <br />)
    $val = cleanHtml($val);
    //Double-check special chars and remove carriage returns
    //For increased SQL security
    $val = preg_replace("/\\\$/", "$", $val);
    $val = preg_replace("/\r/", "", $val);
    $val = str_replace("!", "!", $val);
    $val = str_replace("'", "'", $val);
    //Allow unicode (?)
    $val = preg_replace("/&amp;#([0-9]+);/s", "&#\\1;", $val);
    //Add slashes for SQL
    //$val = $this->sql($val);
    //Swap user-inputted backslashes (?)
    $val = preg_replace("/\\\(?!&amp;#|\?#)/", "\\", $val);
    return $val;
}



/*
* Method to sanitize incoming html.
* Take from cakephp (http://cakephp.org)
* Licensed under the MIT License
*
* @param string Input HTML code.
* @param boolean Wether HTML tags should be removed.
* @return string
* Rolf: only used in this file
*/
function cleanHtml($string, $remove = false) {
    if ($remove) {
        $string = strip_tags($string);
    } else {
        $patterns = array("/\&/", "/%/", "/</", "/>/", '/"/', "/'/", "/\(/", "/\)/", "/\+/", "/-/");
        $replacements = array("&amp;", "%", "&lt;", "&gt;", "&quot;", "'", "(", ")", "+", "-");
        $string = preg_replace($patterns, $replacements, $string);
    }
    return $string;
}

define('CLEAN_INT','CLEAN_INT');
define('CLEAN_FLOAT','CLEAN_FLOAT');
define('CLEAN_NONE','CLEAN_NONE');
define('CLEAN_STRING','CLEAN_STRING');
define('CLEAN_REGEXP','regexp:');
define('CLEAN_FILE','CLEAN_FILE');



/**
* Method to sanitize all entries in a hash
* This method is called by the module api to clean incomming parameters in the frontend.
* It uses the map created with the SetParameterType() method in the module api.
*
* @internal
* @param string Module Name
* @param array  Hash data
* @param array  A map of param names and type information
* @param boolean A flag indicating wether unknown keys in the input data should be allowed.
* @param boolean A flag indicating wether keys should be treated as strings and cleaned.
* Rolf: only used in lib/classes/class.CMSModule.php
*/
function cleanParamHash($modulename,$data,$map = false,
            $allow_unknown = false,$clean_keys = true)
{
  $mappedcount = 0;
  $result = array();
  foreach( $data as $key => $value )
    {
      $mapped = false;
      $paramtype = '';
      if( is_array($map) )
        {
          if( isset($map[$key]) )
            {
                $paramtype = $map[$key];
            }
          else {
              // Key not found in the map
              // see if one matches via regular expressions
              foreach( $map as $mk => $mv ) {
                  if(strstr($mk,CLEAN_REGEXP) === FALSE) continue;

                  // mk is a regular expression
                  $ss = substr($mk,strlen(CLEAN_REGEXP));
                  if( $ss !== FALSE ) {
                      if( preg_match($ss, $key) ) {
                          // it matches, we now know what type to use
                          $paramtype = $mv;
                          break;
                      }
                  }
              }
          } // else

          if( $paramtype != '' ) {
              switch( $paramtype ) {
              case 'CLEAN_INT':
                  $mappedcount++;
                  $mapped = true;
                  $value = (int) $value;
                  break;
              case 'CLEAN_FLOAT':
                  $mappedcount++;
                  $mapped = true;
                  $value = (float) $value;
                  break;
              case 'CLEAN_NONE':
                  // pass through without cleaning.
                  $mappedcount++;
                  $mapped = true;
                  break;
              case 'CLEAN_STRING':
                  $value = cms_htmlentities($value);
                  $mappedcount++;
                  $mapped = true;
                  break;
              case 'CLEAN_FILE':
                  $value = cms_cleanfile($value);
                  $mappedcount++;
                  $mapped = true;
                  break;
              default:
                  $mappedcount++;
                  $mapped = true;
                  $value = cms_htmlentities($value);
                  break;
              } // switch
          } // if $paramtype

        }

      // we didn't clean this yet
      if( $allow_unknown && !$mapped )
        {
          // but we're allowing unknown stuff so we'll just clean it.
          $value = cms_htmlentities($value);
          $mappedcount++;
          $mapped = true;
        }

      if( $clean_keys )
        {
          $key = cms_htmlentities($key);
        }

      if( !$mapped && !$allow_unknown )
        {
          trigger_error('Parameter '.$key.' is not known by module '.$modulename.' dropped',E_USER_WARNING);
          continue;
        }
      $result[$key]=$value;
    }
  return $result;
}



/**
* Returns all parameters sent that are destined for the module with
* the given $id.  This method reads the parameters directly from the $_REQUEST
*
* @internal
* @param string ID (the module instance ID to use for extracting parameters)
* @return array
*/
function GetModuleParameters($id)
{
  $params = array();

  if ($id != '')
    {
      foreach ($_REQUEST as $key=>$value)
    {
      if (strpos($key, (string)$id) !== FALSE && strpos($key, (string)$id) == 0)
        {
          $key = str_replace($id, '', $key);
          if( $key == 'id' || $key == 'returnid' )
        {
          $value = (int)$value;
        }
          $params[$key] = $value;
        }
    }
    }

  return $params;
}



/**
* A function to test if permissions, and php configuration is setup correctly
* to allow an administrator to upload files to CMSMS
*
* @internal
* @return boolean
*/
function can_admin_upload()
{
  # first, check to see if safe mode is enabled
  # if it is, then check to see the owner of the index.php, moduleinterface.php
  # and the uploads and modules directory.  if they all match, then we
  # can upload files.
  # if safe mode is off, then we just have to check the permissions.
  $file_index = cmsms()->config['root_path'].DIRECTORY_SEPARATOR.'index.php';
  $file_moduleinterface = cmsms()->config['root_path'].DIRECTORY_SEPARATOR.
    cmsms()->config['admin_dir'].DIRECTORY_SEPARATOR.'moduleinterface.php';
  $dir_uploads = cmsms()->config['uploads_path'];
  $dir_modules = cmsms()->config['root_path'].DIRECTORY_SEPARATOR.'modules';

  $stat_index = @stat($file_index);
  $stat_moduleinterface = @stat($file_moduleinterface);
  $stat_uploads = @stat($dir_uploads);
  $stat_modules = @stat($dir_modules);

  $my_uid = @getmyuid();

  if( $my_uid === FALSE || $stat_index == FALSE ||
      $stat_moduleinterface == FALSE || $stat_uploads == FALSE ||
      $stat_modules == FALSE )
    {
      // couldn't get some necessary information.
      return FALSE;
    }

  $safe_mode = ini_get_boolean('safe_mode');
  if( $safe_mode )
    {
      // we're in safe mode.
      if( ($stat_moduleinterface[4] != $stat_modules[4]) ||
      ($stat_moduleinterface[4] != $stat_uploads[4]) ||
      ($my_uid != $stat_moduleinterface[4]) )
    {
      // owners don't match
      return FALSE;
    }
    }

  // now check to see if we can write to the directories
  if( !is_writable( $dir_modules ) )
    {
      return FALSE;
    }
  if( !is_writable( $dir_uploads ) )
    {
      return FALSE;
    }

  // It all worked.
  return TRUE;
}



/**
* A convenience function to interpret octal permissions, and return
* a human readable string.  Uses the lang() function for translation.
*
* @internal
* @param int The permissions to test.
* @return string
* Rolf: only used in admin/siteprefs.php
*/
function interpret_permissions($perms)
{
  $owner = array();
  $group = array();
  $other = array();

  if( $perms & 0400 )
    {
      $owner[] = lang('read');
    }

  if( $perms & 0200 )
    {
      $owner[] = lang('write');
    }

  if( $perms & 0100 )
    {
      $owner[] = lang('execute');
    }

  if( $perms & 0040 )
    {
      $group[] = lang('read');
    }

  if( $perms & 0020 )
    {
      $group[] = lang('write');
    }

  if( $perms & 0010 )
    {
      $group[] = lang('execute');
    }

  if( $perms & 0004 )
    {
      $other[] = lang('read');
    }

  if( $perms & 0002 )
    {
      $other[] = lang('write');
    }

  if( $perms & 0001 )
    {
      $other[] = lang('execute');
    }

  return array($owner,$group,$other);
}



/**
* A convenience function to return a boolean variable given a php ini key that represents a boolean
*
* @param string  The php ini key
* @return integer
* Rolf: only used in admin/header.php
*/
function ini_get_boolean($str)
{
  $val1 = ini_get($str);
  $val2 = strtolower($val1);

  $ret = 0;
  if( $val2 == 1 || $val2 == '1' || $val2 == 'yes' || $val2 == 'true' || $val2 == 'on' )
     $ret = 1;
  return $ret;
}



/**
* Another convenience function to output a human readable function stack trace
*
* @return void
*/
function stack_trace()
{
  $stack = debug_backtrace();
  foreach( $stack as $elem )
    {
      if( $elem['function'] == 'stack_trace' ) continue;
      if( isset($elem['file'])  )
    {
      echo $elem['file'].':'.$elem['line'].' - '.$elem['function'].'<br/>';
    }
      else
    {
      echo ' - '.$elem['function'].'<br/>';
    }
    }
}



/**
* A wrapper around move_uploaded_file that attempts to ensure permissions on uploaded
* files are set correctly.
*
* @param string The temporary file specification
* @param string The destination file specification
* @return boolean.
*/
function cms_move_uploaded_file( $tmpfile, $destination )
{
   $config = cmsms()->GetConfig();

   if( !@move_uploaded_file( $tmpfile, $destination ) )
   {
      return false;
   }

   @chmod($destination,octdec($config['default_upload_permission']));
   return true;
}



/**
* A function to read CSS cache information
*
* @deprecated
* @internal
* @param string Filename containing cash information
* @return array of css cache information
* Rolf: only used in admin/editcss.php
*/
function csscache_csvfile_to_hash($filename)
{
  if( !is_readable($filename) ) return false;
  $tmp = @file($filename);
  if( !is_array($tmp) || !count($tmp) ) return false;

  $result = array();
  foreach( $tmp as $one )
    {
      $vals = explode(',',trim($one));
      $result[$vals[0]] = $vals[1];
    }
  return $result;
}



/**
* A function to take hash information representing CSS cache data and store it in a CSV file
*
* @deprecated
* @internal
* @param string Filename to output information to
* @param array  Hash of CSS cache information.
* @return void
* Rolf: only used in admin/editcss.php
*/
function csscache_hash_to_csvfile($filename,$hash)
{
  $fh = @fopen($filename,'w');
  if( !$fh ) return false;
  foreach( $hash as $key => $val )
    {
      $key = trim($key); $val = trim($val);
      $line = "$key,$val\n";
      fwrite($fh,$line);
    }
  fclose($fh);
}


/**
* A function to test wether an IP address matches a list of expressions
* Credits to J.Adams <jna@retins.net>
*
* Expressions can be of the form
*   xxx.xxx.xxx.xxx        (exact)
*   xxx.xxx.xxx.[yyy-zzz]  (range)
*   xxx.xxx.xxx.xxx/nn    (nn = # bits, cisco style -- i.e. /24 = class C)
*
* @param string IP address to test
* @param array  Array of match expressions
* @return boolean
* Rolf: only used in lib/content.functions.php
*/
function cms_ipmatches($ip,$checklist)
{
  if( !function_exists('__testip') ) {
  function __testip($range,$ip)
  {
    $result = 1;

    // IP Pattern Matcher
    // J.Adams <jna@retina.net>
    //
    // Matches:
    //
    // xxx.xxx.xxx.xxx        (exact)
    // xxx.xxx.xxx.[yyy-zzz]  (range)
    // xxx.xxx.xxx.xxx/nn    (nn = # bits, cisco style -- i.e. /24 = class C)
    //
    // Does not match:
    // xxx.xxx.xxx.xx[yyy-zzz]  (range, partial octets not supported)

    $regs = array();
    if (preg_match("/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)\/([0-9]+)/",$range,$regs)) {
      // perform a mask match
      $ipl = ip2long($ip);
      $rangel = ip2long($regs[1] . "." . $regs[2] . "." . $regs[3] . "." . $regs[4]);

      $maskl = 0;

      for ($i = 0; $i< 31; $i++) {
    if ($i < $regs[5]-1) {
      $maskl = $maskl + pow(2,(30-$i));
    }
      }

      if (($maskl & $rangel) == ($maskl & $ipl)) {
    return 1;
      } else {
    return 0;
      }
    } else {
      // range based
      $maskocts = explode('.',$range);
      $ipocts = explode('.',$ip);

      if( count($maskocts) != count($ipocts) && count($maskocts) != 4 )
    {
      return 0;
    }

      // perform a range match
      for ($i=0; $i<4; $i++) {
    if (preg_match("/\[([0-9]+)\-([0-9]+)\]/",$maskocts[$i],$regs)) {
      if ( ($ipocts[$i] > $regs[2]) || ($ipocts[$i] < $regs[1])) {
        $result = 0;
      }
    }
    else
      {
        if ($maskocts[$i] <> $ipocts[$i]) {
          $result = 0;
        }
      }
      }
    }
    return $result;
  } // __testip
  } // if

  if( !is_array($checklist) )
    {
      $checklist = explode(',',$checklist);
    }
  foreach( $checklist as $one )
    {
      if( __testip(trim($one),$ip) ) return TRUE;
    }
  return FALSE;
}

/**
* @author    Dominic Sayers <dominic_sayers@hotmail.com>
* @copyright    2009 Dominic Sayers
* @license    http://www.opensource.org/licenses/cpal_1.0 Common Public Attribution License Version 1.0 (CPAL) license
* @link    http://www.dominicsayers.com/isemail
* @version    1.9 - Minor modifications to make it compatible with PHPLint
* @return boolean
* @param string  $email
* @param boolean $checkDNS
*/
function is_email( $email, $checkDNS=false ) {
    // Check that $email is a valid address. Read the following RFCs to understand the constraints:
    //     (http://tools.ietf.org/html/rfc5322)
    //     (http://tools.ietf.org/html/rfc3696)
    //     (http://tools.ietf.org/html/rfc5321)
    //     (http://tools.ietf.org/html/rfc4291#section-2.2)
    //     (http://tools.ietf.org/html/rfc1123#section-2.1)

    // the upper limit on address lengths should normally be considered to be 256
    //     (http://www.rfc-editor.org/errata_search.php?rfc=3696)
    //     NB I think John Klensin is misreading RFC 5321 and the the limit should actually be 254
    //     However, I will stick to the published number until it is changed.
    //
    // The maximum total length of a reverse-path or forward-path is 256
    // characters (including the punctuation and element separators)
    //     (http://tools.ietf.org/html/rfc5321#section-4.5.3.1.3)
    $emailLength = strlen($email);
    if ($emailLength > 256)    return false;    // Too long

    // Contemporary email addresses consist of a "local part" separated from
    // a "domain part" (a fully-qualified domain name) by an at-sign ("@").
    //     (http://tools.ietf.org/html/rfc3696#section-3)
    $atIndex = strrpos($email,'@');

    if ($atIndex === false) return false;    // No at-sign
    if ($atIndex === 0) return false;    // No local part
    if ($atIndex === $emailLength) return false;    // No domain part

    // Sanitize comments
    // - remove nested comments, quotes and dots in comments
    // - remove parentheses and dots from quoted strings
    $braceDepth    = 0;
    $inQuote    = false;
    $escapeThisChar    = false;

    for ($i = 0; $i < $emailLength; ++$i) {
        $char = $email[$i];
        $replaceChar = false;

        if ($char === '\\') {
            $escapeThisChar = !$escapeThisChar;    // Escape the next character?
        } else {
            switch ($char) {
            case '(':
                if ($escapeThisChar) {
                    $replaceChar = true;
                } else {
                    if ($inQuote) {
                        $replaceChar = true;
                    } else {
                        if ($braceDepth++ > 0) $replaceChar = true;    // Increment brace depth
                    }
                }

                break;
            case ')':
                if ($escapeThisChar) {
                    $replaceChar = true;
                } else {
                    if ($inQuote) {
                        $replaceChar = true;
                    } else {
                        if (--$braceDepth > 0) $replaceChar = true;    // Decrement brace depth
                        if ($braceDepth < 0) $braceDepth = 0;
                    }
                }

                break;
            case '"':
                if ($escapeThisChar) {
                    $replaceChar = true;
                } else {
                    if ($braceDepth === 0) {
                        $inQuote = !$inQuote;    // Are we inside a quoted string?
                    } else {
                        $replaceChar = true;
                    }
                }

                break;
            case '.':    // Dots don't help us either
                if ($escapeThisChar) {
                    $replaceChar = true;
                } else {
                    if ($braceDepth > 0) $replaceChar = true;
                }

                break;
            default:
            }

            $escapeThisChar = false;
            if ($replaceChar) $email[$i] = 'x';    // Replace the offending character with something harmless
        }
    }

    $localPart    = substr($email, 0, $atIndex);
    $domain        = substr($email, $atIndex + 1);
    $FWS        = "(?:(?:(?:[ \\t]*(?:\\r\\n))?[ \\t]+)|(?:[ \\t]+(?:(?:\\r\\n)[ \\t]+)*))";    // Folding white space
    // Let's check the local part for RFC compliance...
    //
    // local-part      =       dot-atom / quoted-string / obs-local-part
    // obs-local-part  =       word *("." word)
    //     (http://tools.ietf.org/html/rfc5322#section-3.4.1)
    //
    // Problem: need to distinguish between "first.last" and "first"."last"
    // (i.e. one element or two). And I suck at regexes.
    $dotArray = preg_split('/\\.(?=(?:[^\\"]*\\"[^\\"]*\\")*(?![^\\"]*\\"))/m', $localPart);
    $partLength    = 0;

    foreach ($dotArray as $element) {
        // Remove any leading or trailing FWS
        $element = preg_replace("/^$FWS|$FWS\$/", '', $element);

        // Then we need to remove all valid comments (i.e. those at the start or end of the element
        $elementLength = strlen($element);

        if ($element[0] === '(') {
            $indexBrace = strpos($element, ')');
            if ($indexBrace !== false) {
                if (preg_match('/(?<!\\\\)[\\(\\)]/', substr($element, 1, $indexBrace - 1)) > 0) {
                    return false;    // Illegal characters in comment
                }
                $element = substr($element, $indexBrace + 1, $elementLength - $indexBrace - 1);
                $elementLength = strlen($element);
            }
        }

        if ($element[$elementLength - 1] === ')') {
            $indexBrace = strrpos($element, '(');
            if ($indexBrace !== false) {
                if (preg_match('/(?<!\\\\)(?:[\\(\\)])/', substr($element, $indexBrace + 1, $elementLength - $indexBrace - 2)) > 0) {
                    return false;    // Illegal characters in comment
                }
                $element = substr($element, 0, $indexBrace);
                $elementLength = strlen($element);
            }
        }

        // Remove any leading or trailing FWS around the element (inside any comments)
        $element = preg_replace("/^$FWS|$FWS\$/", '', $element);

        // What's left counts towards the maximum length for this part
        if ($partLength > 0) $partLength++;    // for the dot
        $partLength += strlen($element);

        // Each dot-delimited component can be an atom or a quoted string
        // (because of the obs-local-part provision)
        if (preg_match('/^"(?:.)*"$/s', $element) > 0) {
            // Quoted-string tests:
            //
            // Remove any FWS
            $element = preg_replace("/(?<!\\\\)$FWS/", '', $element);
            // My regex skillz aren't up to distinguishing between \" \\" \\\" \\\\" etc.
            // So remove all \\ from the string first...
            $element = preg_replace('/\\\\\\\\/', ' ', $element);
            if (preg_match('/(?<!\\\\|^)["\\r\\n\\x00](?!$)|\\\\"$|""/', $element) > 0)    return false;    // ", CR, LF and NUL must be escaped, "" is too short
        } else {
            // Unquoted string tests:
            //
            // Period (".") may...appear, but may not be used to start or end the
            // local part, nor may two or more consecutive periods appear.
            //     (http://tools.ietf.org/html/rfc3696#section-3)
            //
            // A zero-length element implies a period at the beginning or end of the
            // local part, or two periods together. Either way it's not allowed.
            if ($element === '') return false;    // Dots in wrong place

            // Any ASCII graphic (printing) character other than the
            // at-sign ("@"), backslash, double quote, comma, or square brackets may
            // appear without quoting.  If any of that list of excluded characters
            // are to appear, they must be quoted
            //     (http://tools.ietf.org/html/rfc3696#section-3)
            //
            // Any excluded characters? i.e. 0x00-0x20, (, ), <, >, [, ], :, ;, @, \, comma, period, "
            if (preg_match('/[\\x00-\\x20\\(\\)<>\\[\\]:;@\\\\,\\."]/', $element) > 0) return false;    // These characters must be in a quoted string
        }
    }

    if ($partLength > 64) return false;    // Local part must be 64 characters or less

    // Now let's check the domain part...
    // The domain name can also be replaced by an IP address in square brackets
    //     (http://tools.ietf.org/html/rfc3696#section-3)
    //     (http://tools.ietf.org/html/rfc5321#section-4.1.3)
    //     (http://tools.ietf.org/html/rfc4291#section-2.2)
    if (preg_match('/^\\[(.)+]$/', $domain) === 1) {
        // It's an address-literal
        $addressLiteral = substr($domain, 1, strlen($domain) - 2);
        $matchesIP = array();

        // Extract IPv4 part from the end of the address-literal (if there is one)
        if (preg_match('/\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/', $addressLiteral, $matchesIP) > 0) {
            $index = strrpos($addressLiteral, $matchesIP[0]);

            if ($index === 0) {
                // Nothing there except a valid IPv4 address, so...
                return true;
            } else {
                // Assume it's an attempt at a mixed address (IPv6 + IPv4)
                if ($addressLiteral[$index - 1] !== ':') return false;    // Character preceding IPv4 address must be ':'
                if (substr($addressLiteral, 0, 5) !== 'IPv6:') return false;    // RFC5321 section 4.1.3
                $IPv6 = substr($addressLiteral, 5, ($index ===7) ? 2 : $index - 6);
                $groupMax = 6;
            }
        } else {
            // It must be an attempt at pure IPv6
            if (substr($addressLiteral, 0, 5) !== 'IPv6:') return false;    // RFC5321 section 4.1.3
            $IPv6 = substr($addressLiteral, 5);
            $groupMax = 8;
        }

        $groupCount    = preg_match_all('/^[0-9a-fA-F]{0,4}|\\:[0-9a-fA-F]{0,4}|(.)/', $IPv6, $matchesIP);
        $index = strpos($IPv6,'::');

        if ($index === false) {
            // We need exactly the right number of groups
            if ($groupCount !== $groupMax) return false;    // RFC5321 section 4.1.3
        } else {
            if ($index !== strrpos($IPv6,'::')) return false;    // More than one '::'
            $groupMax = ($index === 0 || $index === (strlen($IPv6) - 2)) ? $groupMax : $groupMax - 1;
            if ($groupCount > $groupMax) return false;    // Too many IPv6 groups in address
        }

        // Check for unmatched characters
        array_multisort($matchesIP[1], SORT_DESC);
        if ($matchesIP[1][0] !== '') return false;    // Illegal characters in address

        // It's a valid IPv6 address, so...
        return true;
    } else {
        // It's a domain name...

        // The syntax of a legal Internet host name was specified in RFC-952
        // One aspect of host name syntax is hereby changed: the
        // restriction on the first character is relaxed to allow either a
        // letter or a digit.
        //     (http://tools.ietf.org/html/rfc1123#section-2.1)
        //
        // NB RFC 1123 updates RFC 1035, but this is not currently apparent from reading RFC 1035.
        //
        // Most common applications, including email and the Web, will generally not
        // permit...escaped strings
        //     (http://tools.ietf.org/html/rfc3696#section-2)
        //
        // the better strategy has now become to make the "at least one period" test,
        // to verify LDH conformance (including verification that the apparent TLD name
        // is not all-numeric)
        //     (http://tools.ietf.org/html/rfc3696#section-2)
        //
        // Characters outside the set of alphabetic characters, digits, and hyphen MUST NOT appear in domain name
        // labels for SMTP clients or servers
        //     (http://tools.ietf.org/html/rfc5321#section-4.1.2)
        //
        // RFC5321 precludes the use of a trailing dot in a domain name for SMTP purposes
        //     (http://tools.ietf.org/html/rfc5321#section-4.1.2)
        $dotArray = preg_split('/\\.(?=(?:[^\\"]*\\"[^\\"]*\\")*(?![^\\"]*\\"))/m', $domain);
        $partLength = 0;
        if (count($dotArray) === 1) return false;    // Mail host can't be a TLD

        foreach ($dotArray as $element) {
            // Remove any leading or trailing FWS
            $element = preg_replace("/^$FWS|$FWS\$/", '', $element);

            // Then we need to remove all valid comments (i.e. those at the start or end of the element
            $elementLength = strlen($element);

            if ($element[0] === '(') {
                $indexBrace = strpos($element, ')');
                if ($indexBrace !== false) {
                    if (preg_match('/(?<!\\\\)[\\(\\)]/', substr($element, 1, $indexBrace - 1)) > 0) {
                        return false;    // Illegal characters in comment
                    }
                    $element = substr($element, $indexBrace + 1, $elementLength - $indexBrace - 1);
                    $elementLength = strlen($element);
                }
            }

            if ($element[$elementLength - 1] === ')') {
                $indexBrace = strrpos($element, '(');
                if ($indexBrace !== false) {
                    if (preg_match('/(?<!\\\\)(?:[\\(\\)])/', substr($element, $indexBrace + 1, $elementLength - $indexBrace - 2)) > 0) {
                        return false;    // Illegal characters in comment
                    }
                    $element = substr($element, 0, $indexBrace);
                    $elementLength = strlen($element);
                }
            }

            // Remove any leading or trailing FWS around the element (inside any comments)
            $element = preg_replace("/^$FWS|$FWS\$/", '', $element);

            // What's left counts towards the maximum length for this part
            if ($partLength > 0) $partLength++;    // for the dot
            $partLength += strlen($element);

            // The DNS defines domain name syntax very generally -- a
            // string of labels each containing up to 63 8-bit octets,
            // separated by dots, and with a maximum total of 255
            // octets.
            //     (http://tools.ietf.org/html/rfc1123#section-6.1.3.5)
            if ($elementLength > 63) return false;    // Label must be 63 characters or less

            // Each dot-delimited component must be atext
            // A zero-length element implies a period at the beginning or end of the
            // local part, or two periods together. Either way it's not allowed.
            if ($elementLength === 0) return false;    // Dots in wrong place

            // Any ASCII graphic (printing) character other than the
            // at-sign ("@"), backslash, double quote, comma, or square brackets may
            // appear without quoting.  If any of that list of excluded characters
            // are to appear, they must be quoted
            //     (http://tools.ietf.org/html/rfc3696#section-3)
            //
            // If the hyphen is used, it is not permitted to appear at
            // either the beginning or end of a label.
            //     (http://tools.ietf.org/html/rfc3696#section-2)
            //
            // Any excluded characters? i.e. 0x00-0x20, (, ), <, >, [, ], :, ;, @, \, comma, period, "
            //if (preg_match('/[\\x00-\\x20\\(\\)<>\\[\\]:;@\\\\,\\."]|^-|-$/', $element) > 0) {
            if (preg_match('/[\\x00-\\x20\\(\\)<>\\[\\]:;@\\\\,\\."]$/', $element) > 0) {
                return false;
            }
        }

        if ($partLength > 255) return false;    // Local part must be 64 characters or less
        if (preg_match('/^[0-9]+$/', $element) > 0)    return false;    // TLD can't be all-numeric

        // Check DNS?
        if ($checkDNS && function_exists('checkdnsrr')) {
            if (!(checkdnsrr($domain, 'A') || checkdnsrr($domain, 'MX'))) {
                return false;    // Domain doesn't actually exist
            }
        }
    }

    // Eliminate all other factors, and the one which remains must be the truth.
    // (Sherlock Holmes, The Sign of Four)
    return true;
}



/**
* A convenience method to output the secure param tag that is used on all admin links
*
* @internal
* @access private
* @return string
* Rolf: only used in admin/imagefiles.php
*/
function get_secure_param()
{
  $urlext = '?';
  $str = strtolower(ini_get('session.use_cookies'));
  if( $str == '0' || $str == 'off' ) {
    $urlext .= htmlspecialchars(SID).'&';
  }
  $urlext .= CMS_SECURE_PARAM_NAME.'='.$_SESSION[CMS_USER_KEY];
  return $urlext;
}



/**
* Rolf: only used in lib/classes/contenttypes/Content.inc.php
*/
function cms_to_bool($str)
{
  if( is_numeric($str) ) return ((int)$str != 0)?TRUE:FALSE;
  $str = strtolower($str);
  if( $str == 'y' || $str == 'yes' || $str == 'true' || $str == 'on' || $str === '1' ) return TRUE;
  return FALSE;
}



/**
*
*/
function cms_get_jquery($exclude = '',$ssl = null,$cdn = false,$append = '',$custom_root='')
{
  $config = cms_config::get_instance();
  $scripts = array();
  $base_url = $config['root_url'];
  if( is_null($ssl) ) {
    $base_url = $config->smart_root_url();
  }
  else if( $ssl === true || $ssl === TRUE ) {
    $base_url = $config['ssl_url'];
  }
  $basePath=$custom_root!=''?trim($custom_root,'/'):$base_url;

  // Scripts to include
  $scripts['jquery.min.js'] = '<script type="text/javascript" src="'.($cdn?'https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js':$basePath.'/lib/jquery/js/jquery-1.11.0.min.js').'"></script>'."\n"
  . '<script type="text/javascript" src="' . $basePath .'/lib/jquery/js/jquery-migrate-1.2.1.min.js"></script>' . "\n";
  $scripts['jquery-ui.min.js'] = '<script type="text/javascript" src="'.($cdn?'https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.4/jquery-ui.min.js':$basePath.'/lib/jquery/js/jquery-ui-1.10.4.custom.min.js').'"></script>'."\n";
  $scripts['jquery.ui.nestedSortable.js'] = '<script type="text/javascript" src="'.$basePath.'/lib/jquery/js/jquery.ui.nestedSortable-1.3.4.js"></script>'."\n";
  $scripts['jquery.json.min.js'] = '<script type="text/javascript" src="'.$basePath.'/lib/jquery/js/jquery.json-2.3.min.js"></script>'."\n";

  // Check if we need exclude some script
  if(!empty($exclude)) {

    $exclude_list = explode(",", trim(str_replace(' ','',$exclude)));
    foreach($exclude_list as $one) {
      if ($one == 'jquery-1.6.2.min.js') {
          $one = 'jquery.min.js';
      }
      if ($one == 'jquery-ui-1.8.14.min.js') {
          $one = 'jquery-ui.min.js';
      }
      if ($one == 'jquery.json-2.2.js') {
          $one = 'jquery.json.min.js';
      }
      if ($one == 'jquery.ui.nestedSortable-1.3.4.js') {
          $one = 'jquery.ui.nestedSortable.js';
      }

      unset($scripts[$one]);
    }
  }
  // let them add scripts to the end ie: a jQuery plugin
  if(!empty($append)) {
    $append_list = explode(",", trim(str_replace(' ','',$append)));
    foreach($append_list as $key => $item) {
      $scripts['user_'+$key]='<script type="text/javascript" src="'.($item).'"></script>'."\n";;
    }
  }
  // Output

  $output = '';
  foreach($scripts as $script) {
    $output .= $script;
  }
  return $output;
}



/**
* Rolf: only used in lib/classes/class.CMSModule.php
*/
if(!function_exists('get_called_class')) {
  function get_called_class() {
    try {
      return cms_function_help::get_called_class();
    }
    catch( Exception $e ) {
      // ignore
    }
  }
  // this class must exist in this file until CMSMS 1.12 when we dont have to worry abut PHP 5.2
  // this file is loaded before the autoloader runs.
  class cms_function_help {

    public static function get_called_class($bt = false,$l = 1)
    {
      if (!$bt) $bt = debug_backtrace();
      if (!isset($bt[$l])) throw new Exception("Cannot find called class -> stack level too deep.");
      if (!isset($bt[$l]['type'])) {
        if( $l >= 2 ) {
      throw new Exception ('type not set');
        }
        else {
          return self::get_called_class($bt,$l+1);
        }
      }
      else switch ($bt[$l]['type']) {
      case '::':
    $lines = file($bt[$l]['file']);
    $i = 0;
    $callerLine = '';
    do {
      $i++;
      $callerLine = $lines[$bt[$l]['line']-$i] . $callerLine;
    } while (stripos($callerLine,$bt[$l]['function']) === false);
    preg_match('/([a-zA-Z0-9\_]+)::'.$bt[$l]['function'].'/',
           $callerLine,
           $matches);
    if (!isset($matches[1])) {

      // must be an edge case.
      throw new Exception ("Could not find caller class: originating method call is obscured.");
    }
    switch ($matches[1]) {
    case 'self':
    case 'parent':
      return self::get_called_class($bt,$l+1);
    default:
      return $matches[1];
    }
    // won't get here.
      case '->': switch ($bt[$l]['function']) {
    case '__get':
      // edge case -> get class of calling object
      if (!is_object($bt[$l]['object'])) throw new Exception ("Edge case fail. __get called on non object.");
      return get_class($bt[$l]['object']);
    default: return $bt[$l]['class'];
    }

      default: throw new Exception ("Unknown backtrace method type");
      }
    }
  }
}

# vim:ts=4 sw=4 noet
?>
#7
Quelle version PHP sur WAMP ?

>j'ai cette erreur des que je choisis la langue (fr_FR)
Donc c'est bien au départ de ta mise à jour

Quel fichier de mise à jour ? le cmsmadeesimple-1.12.1 ???
Il vient d'où ton fichier ?

NOTA sur hébergement
>phpversion: 5.2.9-1.illimite
ta version PHP est ancienne
Mise à jour fortement Recommandée PHP 5.4.3 mini car les modules CG sont en version PHP 5.4.3 mini
J-C Etiemble v 2.2.xx
#7
Quelle version PHP sur WAMP ?

>j'ai cette erreur des que je choisis la langue (fr_FR)
Donc c'est bien au départ de ta mise à jour

Quel fichier de mise à jour ? le cmsmadeesimple-1.12.1 ???
Il vient d'où ton fichier ?

NOTA sur hébergement
>phpversion: 5.2.9-1.illimite
ta version PHP est ancienne
Mise à jour fortement Recommandée PHP 5.4.3 mini car les modules CG sont en version PHP 5.4.3 mini
J-C Etiemble v 2.2.xx
#8
pourtant j'utilise

WampServer Version 2.5

Version de PHP: 5.5.12

le fichier de mise à jour est bien celui du cmsmadeesimple-1.12.1...
je test avec l'ancien
#8
pourtant j'utilise

WampServer Version 2.5

Version de PHP: 5.5.12

le fichier de mise à jour est bien celui du cmsmadeesimple-1.12.1...
je test avec l'ancien
#9
from scratch.... tjrs KO

Code :
( ! ) Fatal error: Class 'CmsApp' not found in C:\wamp\www\v2\lib\misc.functions.php on line 208
Call Stack
#    Time    Memory    Function    Location
1    0.0005    285016    {main}( )    ..\index.php:0
2    0.0074    1208464    require_once( 'C:\wamp\www\v2\include.php' )    ..\index.php:144
3    0.0077    1233176    debug_buffer( )    ..\include.php:67
4    0.0077    1233208    cmsms( )    ..\misc.functions.php:580
#9
from scratch.... tjrs KO

Code :
( ! ) Fatal error: Class 'CmsApp' not found in C:\wamp\www\v2\lib\misc.functions.php on line 208
Call Stack
#    Time    Memory    Function    Location
1    0.0005    285016    {main}( )    ..\index.php:0
2    0.0074    1208464    require_once( 'C:\wamp\www\v2\include.php' )    ..\index.php:144
3    0.0077    1233176    debug_buffer( )    ..\include.php:67
4    0.0077    1233208    cmsms( )    ..\misc.functions.php:580
#10
tu fais comment ta mise à jour ?
J-C Etiemble v 2.2.xx
#10
tu fais comment ta mise à jour ?
J-C Etiemble v 2.2.xx
#11
2 idées : vérifie que ton config.php ne comporte pas les lignes obsolètes, tu ne devrais avoir que
Code :
[== Indéfini ==]
<?php
# CMS Made Simple - Fichier de configuration
# Documentation : /doc/CMSMS_config_reference.pdf
#
$config['dbms'] = 'mysqli';
$config['db_hostname'] = 'localhost';
$config['db_username'] = 'root';
$config['db_password'] = '';
$config['db_name'] = 'V2';
$config['db_prefix'] = 'cms_';
$config['timezone'] = 'Europe/Brussels';
$config['url_rewriting'] = "mod_rewrite";
#$config['debug'] = true;
?>
Et assure-toi que tu as bien tous les fichiers, principalement lib/classes/class.CmsApp.php
#11
2 idées : vérifie que ton config.php ne comporte pas les lignes obsolètes, tu ne devrais avoir que
Code :
[== Indéfini ==]
<?php
# CMS Made Simple - Fichier de configuration
# Documentation : /doc/CMSMS_config_reference.pdf
#
$config['dbms'] = 'mysqli';
$config['db_hostname'] = 'localhost';
$config['db_username'] = 'root';
$config['db_password'] = '';
$config['db_name'] = 'V2';
$config['db_prefix'] = 'cms_';
$config['timezone'] = 'Europe/Brussels';
$config['url_rewriting'] = "mod_rewrite";
#$config['debug'] = true;
?>
Et assure-toi que tu as bien tous les fichiers, principalement lib/classes/class.CmsApp.php
#12
>vérifie que ton config.php ne comporte ..

pour moi je dirais
- quand tu fais une mise à jour depuis une ancienne version c'est le config ancienne version (ici 1.6.x) qu'il faut avoir et non le nouveau 1.1x.
- Ensuite et seulement ensuite après la mise à jour, tu modifies le config
J-C Etiemble v 2.2.xx
#12
>vérifie que ton config.php ne comporte ..

pour moi je dirais
- quand tu fais une mise à jour depuis une ancienne version c'est le config ancienne version (ici 1.6.x) qu'il faut avoir et non le nouveau 1.1x.
- Ensuite et seulement ensuite après la mise à jour, tu modifies le config
J-C Etiemble v 2.2.xx
#13
Salut Jean le chauve en faite j'ai déjà test cette conf mais je me suis retrouver avec des erreurs php type deprecicate sur plein de fichier...avec des obj = & new à changer en obj= new...donc retour cas depart...
Avec la methode de JCE en utilisant le conf d'origine 1.6 et l'install 1.6 (install/upgrade.php):

1 récupération de la bdd et de la racine du site / installation sur wamp (répertoire : v2)
2 récupération de la dernière version cmsms 1.12.1
3 fusion des répertoires admin-img-lib-modules-plugings etc..
4 .1 a ce moment la si j’affiche le site j’ai le message de maintenance
4. 2 je lancement de la mise a jours (v2/install/upgrade.php) et paf j’ai :
Code :
( ! ) Fatal error: Call to undefined function get_encoding() in C:\wamp\www\v2\include.php on line 219
Call Stack
#    Time    Memory    Function    Location
1    0.0009    289248    {main}( )    ..\upgrade.php:0
2    0.0017    357576    require_once( 'C:\wamp\www\v2\include.php' )    ..\upgrade.php:22
#13
Salut Jean le chauve en faite j'ai déjà test cette conf mais je me suis retrouver avec des erreurs php type deprecicate sur plein de fichier...avec des obj = & new à changer en obj= new...donc retour cas depart...
Avec la methode de JCE en utilisant le conf d'origine 1.6 et l'install 1.6 (install/upgrade.php):

1 récupération de la bdd et de la racine du site / installation sur wamp (répertoire : v2)
2 récupération de la dernière version cmsms 1.12.1
3 fusion des répertoires admin-img-lib-modules-plugings etc..
4 .1 a ce moment la si j’affiche le site j’ai le message de maintenance
4. 2 je lancement de la mise a jours (v2/install/upgrade.php) et paf j’ai :
Code :
( ! ) Fatal error: Call to undefined function get_encoding() in C:\wamp\www\v2\include.php on line 219
Call Stack
#    Time    Memory    Function    Location
1    0.0009    289248    {main}( )    ..\upgrade.php:0
2    0.0017    357576    require_once( 'C:\wamp\www\v2\include.php' )    ..\upgrade.php:22
#14
>... en utilisant le conf d'origine 1.6 et l'install 1.6 (install/upgrade.php):
Tu n'as pas à utiliser install/upgrade.php ICI

>1 récupération de la bdd et de la racine du site / installation sur wamp (répertoire : v2)
OK et TOUS tes fichiers de la 1.6 donc la ta version 1.6 fonctionne ??

>2 récupération de la dernière version cmsms 1.12.1
OK

>3 fusion des répertoires admin-img-lib-modules-plugings etc..
Houla pas conseillé pour éviter des problèmes
Vide ton répertoire V2 en ne laisant que config.php et /uploads et /temp (vide les fichiers temporaires)
extrait simplement tous les fichiers de la 1.12.1 dans ton répertoire v2
SAUF temp et uploads
- install/upgrade.php ICI
J-C Etiemble v 2.2.xx
#14
>... en utilisant le conf d'origine 1.6 et l'install 1.6 (install/upgrade.php):
Tu n'as pas à utiliser install/upgrade.php ICI

>1 récupération de la bdd et de la racine du site / installation sur wamp (répertoire : v2)
OK et TOUS tes fichiers de la 1.6 donc la ta version 1.6 fonctionne ??

>2 récupération de la dernière version cmsms 1.12.1
OK

>3 fusion des répertoires admin-img-lib-modules-plugings etc..
Houla pas conseillé pour éviter des problèmes
Vide ton répertoire V2 en ne laisant que config.php et /uploads et /temp (vide les fichiers temporaires)
extrait simplement tous les fichiers de la 1.12.1 dans ton répertoire v2
SAUF temp et uploads
- install/upgrade.php ICI
J-C Etiemble v 2.2.xx
#15
@ booky C'est résolu ?
J-C Etiemble v 2.2.xx
#15
@ booky C'est résolu ?
J-C Etiemble v 2.2.xx


Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)