Location: PHPKode > projects > Streber > std/common.inc.php
<?php if(!function_exists('startedIndexPhp')) { header("location:../index.php"); exit();}

/**
 * function different purposes relating to:
 * - filtering and accessing request vars
 * - getting passed ids with wildcards
 * - language-support
 *
 * included from:index.php, install.php
 *
 * @author Thomas Mann
 * @uses:
 * @usedby: everything
 *
 */


/**
* About using referred variables:
*
* - all referred variables are combined into one assoc. array (see index.php)
* -
*/
global $g_request_vars;
$g_request_vars=array();

global $g_tags_removed;
$g_tags_removed= 0;


/**
* clear possibily defined request-vars
*/
function clearRequestVars() {
    global $g_request_vars;
    $g_request_vars=array();
}



/**
* filter request vars given as assoc. array
* - we don't want to trust any extern data therefore
*   strip weird size & remove weird characters
*/
function addRequestVars(&$referred_vars)
{
    global $g_request_vars;
    global $g_tags_removed;

    if(!isset($g_request_vars)) {
        $g_request_vars= array();
    }

    if(!isset($referred_vars) ) {
        trigger_error('filter_vars() called without proper parameters', E_USER_NOTICE);
        return;
    }

    foreach(array_keys($referred_vars) as $key) {

        ### skip too long variable key (probably an hacking-attempt) ###
        if(strlen($key) > 256) {
            trigger_error('Skipping too long key: "'.$key.'"', E_USER_NOTICE);
            continue;
        }

        ### skip variables with invalid name ###
        if(preg_match("/[\\'<>\/\"]/",$key)) {
            trigger_error('Skipping maleformed key: "'.$key.'"', E_USER_NOTICE);
            continue;
        }

        $value= $referred_vars[$key];

        if(is_string($value)) {

            switch(confGet('CLEAN_REFERRED_VARS')) {

                case 'STRIP_TAGS':
                    while ($value != strip_tags($value)) {
                       $g_tags_removed++;
                       $value = strip_tags($value);
                    }

                case 'HTML_ENTITIES':
                    break;

                default:
                    trigger_error("unknown setting for CLEAN_REFERRED_VARS: '".confGet('CLEAN_REFERRED_VARS')."'",E_USER_WARNING);
            }
            
            ### remove slashes if magic quotes
            if(get_magic_quotes_gpc()) {
                $value= stripslashes($value);
            }

            ### strip length ###
            $value= substr( $value,0,confGet('STRING_SIZE_MAX'));
        }
        else if(! is_numeric($value) ) {
            $content = print_r($value, true);
            trigger_error("Skipping referred value for '$key' of unknown type: '". gettype($value)."' $content", E_USER_NOTICE);
            continue;
        }
        $g_request_vars[$key] = $value;
    }
}



/**
* access request vars
*
* returns optional 2nd parameter, if variable isn't set
*/
function get($key, $default_value= NULL) {
    global $g_request_vars;

    if(isset($g_request_vars[$key])) {
        $value=$g_request_vars[$key];
        /**
        * weird boolean conversion
        */
        if(gettype($value) == 'boolean') {

            $value="";
        }
        return $value;
    }

    ### use wildcards ###
    else if(isset($g_request_vars) && preg_match("/\*/",$key)) {
        $key= str_replace("*",".*",$key);


        $hash= array();
        foreach($g_request_vars as $ikey=>$ivalue) {
            if(preg_match("/" . $key . "/", $ikey)) {
                $hash[$ikey]=$ivalue;
            }
        }
        return($hash);
    }
    return $default_value;
}

function getServerVar($name, $as_html= false)
{
    if( isset($_SERVER[$name]) ){
        if( $as_html) {
            return asHtml($_SERVER[$name] );
        }
        return $_SERVER[$name];
    }
}
/**
* sometimes useful for debugging
* - note the print of a double % which will trigger a warning for debug out
*   in unit tests
*
*/
function printFormVars()
{
    global $g_request_vars;
    echo "%" . "%<pre>";
    print_r($g_request_vars);
    echo "</pre>";
}

function debugMessage($message)
{
    echo "<div class=debugMessage><pre>";
    print_r( $message );
    echo "</pre></div>";
}



/**
* for securing hidden form information do following
* - when building up forms hiddenfields should be added like...
*           $form->add(new Form_HiddenField('task_project','',$project->id));
* - when rendering, the form requests a from handle for those which is stored with an md5 at _tmp/xxx
*   It then adds the md5 as 'hidden_crc'
*
* - when submitting a form with hidden_values you should first call validateFormCrc() which
*   returns NULL if one of the hidden parameters is missing is changed.
*/
function validateFormCrc()
{
    if(!$handle= get('hidden_crc')) {
        return NULL;
    }
    global $PH;
    $params= $PH->getFromParams($handle);
    if(!$params) {
        log_message("Validing crc for hidden form value failed (from handle missing)", LOG_MESSAGE_HACKING_ALERT);
        return NULL;
    }

    $log_message='';
    $flag_failure= false;
    foreach($params as $key => $value) {
        if($key == 'go') {
            continue;
        }
        if(is_null(get($key)) || get($key) != $value) {
            $log_message.="'$key': '$value' -> '".get($key)."'  ";
            $flag_failure = true;
        }
    }

    if($flag_failure) {
        global $auth;
        log_message("HACK?? Failed hidden form CRC ($log_message) by ". $auth->cur_user->name, LOG_MESSAGE_HACKING_ALERT);
        return NULL;

    }
    return true;
}


/**
* Checks for two parameters:
* - $captcha_input and $captcha_key
*
* The captcha image is been created in misc.inc.php -> imageRenderCaptcha($captcha_key)
* It rendens an image with a key created by the following formula:
*
*  substr(md5( $key . $auth->cur_user->identifier ), 0, 5)
*
* Both form parameters are protected by CRC and stored as from
* handles in the _tmp/ directory. If captcha_key is not found, the
* function returns with true and does nothing.
*
* Returns true/false or aborts if $abort_on_failure is true.
*
* Note: For convience instead of aborting, you should revisit the editForm.
*/
function validateFormCaptcha($abort_on_failure = false)
{
    global $auth;
    if($key= get('captcha_key')) {
        $captcha_input= get('captcha_input');

        $should_be= substr(md5( $key . $auth->cur_user->identifier ), 0, 5);


        if($captcha_input == $should_be) {
            return true;
        }
        else {
            if($abort_on_failure) {
                global $PH;
                $PH->abortWarning(__("Sorry, but the entered number did not match"));
            }
            return false;
        }
    }
    return true;
}

/**
* parse a mysql-dump with multiple queries and sent it to mysql
*
* - adds table-prefix to all select and create-statements
* - This function is a hack to quickly set up the db-structure. Sooner
*   or later it will be replaces with a real table-creation-function.
*/
function parse_mysql_dump($url, $table_prefix, $sql_obj)
{
    $file_content = file($url);
    $query = "";

    foreach($file_content as $sql_line){
        if(trim($sql_line) != "" && strpos($sql_line, "--") === FALSE){
            $query .= $sql_line;
            ### query complete ###
            if(preg_match("/;\s*$/", $sql_line)){

                ### add table-prefixes ###
                $matches= array();
                if(preg_match("/(CREATE\s*TABLE\s[`'](.*)[`'])\s*\(/", $query, $matches)) {
                    $create_string_old= $matches[1];
                    $table_name_old= $matches[2];
                    $create_string_new= str_replace($table_name_old, $table_prefix.$table_name_old, $create_string_old);
                    $query= str_replace($create_string_old, $create_string_new, $query);
                }
                if(preg_match("/(DROP\s+TABLE\s+IF\s+EXISTS [`']*(.*)[`']*);/", $query, $matches)) {
                    $create_string_old= $matches[1];
                    $table_name_old= $matches[2];
                    $create_string_new= str_replace($table_name_old, $table_prefix.$table_name_old, $create_string_old);
                    $query= str_replace($create_string_old, $create_string_new, $query);
                }
                if(preg_match("/(INSERT INTO [`']*(.*)[`']*)\s+\(/", $query, $matches)) {
                    $create_string_old= $matches[1];
                    $table_name_old= $matches[2];
                    $create_string_new= str_replace($table_name_old, $table_prefix.$table_name_old, $create_string_old);
                    $query= str_replace($create_string_old, $create_string_new, $query);
                }

                ### print errors ###
                if(!$result = $sql_obj->execute($query)) {
                    trace($sql_obj);
                    return false;
                }
                $query = "";
            }
         }
    }
    return true;
}



/**
* Basic object for setting values and passing
* constructor-parameters as assoc. array
*
*/
class BaseObject
{

    public function __construct($args=NULL)
    {
        if($args) {
            foreach($args as $key=>$value) {
                is_null($this->$key);   # cause E_NOTICE if member not defined
                $this->$key=$value;
            }
        }
    }


    public function __set($name,$value)
    {
        if($this->$name) {
            $this->$name= $value;
        }
        else {
            trigger_error("setting undefined member '$name'  to '$value'  in Class '" hide@address.com($this). "' ",E_USER_WARNING);
            $this->$name= $value;
        }
    }


    #--- get --------------------------------------
    public function __get($nm)
    {
        if (isset($this->$nm)) {
           return $r;
        }
        else {
            trigger_error("reading undefined member '$nm'  in '" hide@address.com($this). "' ", E_USER_WARNING);
        }
    }
}





/**
* inserts a number if key=>values into the first list, but does not overwrite existing values
*
* $a= array('x'=>1, 'z'=>2);
* $b= array('x'=>5, 'y'=>2);
* fillMissingValues($a,$b)      # set $b to ['x'=>1, 'y'=>2, 'z'=>2]
*
* Does not return the list!!!
*/
function fillMissingValues(&$list, $settings)
{
    foreach($settings as $key => $value){
        if(!array_key_exists($key, $list)) {
            $list[$key]= $value;
        }
    }
}



/**
* convert a string int months
* NOTE: this check is very loose to also fit for german
*/
function string2month(&$string) {
    $mon=1;
    foreach(array('Jan','Feb','Ma?.r','Apr','Ma','Jun','Jul','Aug','Sep','O','Nov','Dec') as $m) {
        if(preg_match("/^$m/i",$string,$matches)) {
            return "$mon";      # TODO-printf-formated layout for 2 digits
        }
        ++$mon;
    }
    return false;
}


function mysqlDatetime2utc($datetime) {
    $out=array();
    if(preg_match("/\b(\d\d\d\d)[^\d](\d?\d)[^\d](\d?\d)\s+(\d\d)[^\d](\d\d)[^\d](\d\d)\b/",$datetime,$matches)) {
        if(count($matches)==7) {
            $out['year']=$matches[1];
            $out['mon']=$matches[2];
            $out['day']=$matches[3];
            $out['hour']=$matches[4];
            $out['min']=$matches[5];
            $out['sec']=$matches[6];
            return $out;
        }
    }
     return false;
}

/**
* get html-passed ids
*
* - used to pass the ids of elements we want apply functions to (like edit a task, or delete task(2)
* - to avoid accidentally applying functions to both, we will check for wildscards (selected rows in a list)
*   rathen than for a single name (the id of the object the function is called from)
*/
function getPassedIds($name=false,$wild=false)
{

    $ids=NULL;
    #--- first check use wildcards --
    if(!$wild) {
        $wild= strtolower($name)."s_*";     # eg: 'objectS_*'
    }
    $selected_items= get($wild);

    if($selected_items) {
        $keys= array_keys($selected_items);
        foreach($keys as $key) {
            if(preg_match("/_(\d+)_chk/",$key,$matches)) {
                $ids[]=$matches[1];
            }
        }
    }
    if(!$ids) {
        #--- try original id ---
        if($name) {
            $id=get($name);
            $ids=array();
            if(isset($id)) {
                $ids[]=$id;
            }
        }
    }
    return $ids;
}

/**
* get exactly one html-passed id
* -  set PH->message if multiple selected
*/
function getOnePassedId($name=false,$wild=false, $abort_on_failure=true,$message=NULL)
{
    global $PH;

    if(!$message) {
        $message=__("No element selected? (could not find id)","Message if a function started without items selected");
    }
    $ids= getPassedIds($name,$wild);
    if(!$ids) {
        if($abort_on_failure) {
            $PH->abortWarning($message,ERROR_NOTE);
            exit("aborting");
        }
        return;
    }
    else if(count($ids)>1) {
        $message= __('only one item expected.');
        if($abort_on_failure) {
            $PH->abortWarning($message,ERROR_NOTE);
        }
        else {
            $PH->messages[]= $message;
            return;
        }
    }
    return $ids[0];
}




/**
* translate string into another language
*
* - translation is done over assoc. arrays
* - each string that should be translated hase to be writte like ("word","used in this context")
* - in english, or if not translated, only "word" will be written
* - the "context"-string is used to clarify the current meaning like...
*   - ("work for","some company") should be translated different than ("work for","new effort for a person")
* -
*/
global $g_lang;
$g_lang="en";
function __ ( $str, $context=NULL ) {
    global $g_lang;

    if (!isset($g_lang) or $g_lang == "en") {
        return $str;
    }

    global $g_lang_table;

    ### first try clarified phrase ###
    if($context && isset($g_lang_table[$str."|".$context]) && $g_lang_table[$str."|".$context]!="" ) {
        return preg_replace('/\|.*/','',$g_lang_table[$str."|".$context]);
    }

    ### then try general phrase ###
    if(isset($g_lang_table[$str]) && $g_lang_table[$str] != "") {
        return preg_replace('/\|.*/','',$g_lang_table[$str]);
    }

    ### not found -> keep in not-found-list for later output ###
    global $g_lang_new;
    if(!isset($g_lang_new)) {
        $g_lang_new=array();
    }
    $g_lang_new[$str."|".$context]="?";

    return $str;
}


/**
* set language
*
* This will include a big assoc. array as translation-table.
*
* Setting setLanguage twice might work, since the language-file
* is NOT "require(d)_once"
*/
function setLang($lang) {
    global $g_lang;
    if($lang == $g_lang) {
        return;
    }
    if($lang == 'en') {
        $g_lang= 'en';
    }
    else {
        $filepath= "lang/{$lang}.inc.php";
        if(file_exists($filepath)) {
            require($filepath);
            $g_lang= $lang;
        }
        else {
            trigger_error("Undefined language '$lang'", E_USER_NOTICE);
            return;
        }
    }

    /*
    * reset time format
    */
    clearCachedTimeFormats();

    $locale = confGet('DEFAULT_LOCALE');

    if($locale != 'C') {
        // setlocale() is used to set the proper locale for date formatting
        // As locale identifiers are platform dependent, PHP allows to specify more than one,
        // they are tried in order until a supported one is found. Most *nix-based platforms
        // use "xx_XX.encoding", while Windows platforms use three letter forms. The more
        // locales are listed, the more compatible the code will be.
        // Please refer to documentation of function setlocale() for details.
        // TODO: should we set the locale also for LC_CTYPE and/or LC_COLLATE?

        if( $locale == 'USE_TRANSLATION') {
            $locale = __('en_US.utf8,en_US,enu', 'list of locales');
        }

        $res = setlocale(LC_TIME, explode(',', $locale));

        # this warning might be annoying, but we need a way to detect that setlocale failed
        # eventually the list of locales will be long enough to include all supported platforms
        # 
        # pixtur: changed from warning to log_message that will only be displayed when
        # 
        
        if($res === FALSE) {
            log_message("Could not set locale to '$locale'", E_USER_WARNING);
        }
    }
}





/**
* readfile for very large files
* by from hide@address.com
*/
function readfile_chunked($filename, $retbytes=true) {
    $chunksize = 1*(1024*1024); // how many bytes per chunk
    $buffer = '';
    $cnt =0;
    // $handle = fopen($filename, 'rb');
    $handle = fopen($filename, 'rb');
    if ($handle === false) {
        return false;
    }
    while (!feof($handle)) {
        $buffer = fread($handle, $chunksize);
        echo $buffer;
        if(ob_get_length()) {
            ob_flush();
        }
        flush();
        if ($retbytes) {
           $cnt += strlen($buffer);
        }
    }
    $status = fclose($handle);

    if ($retbytes && $status) {
       return $cnt; // return num. bytes delivered like readfile() does.
    }
    return $status;

}


function createRandomString() {
    return  md5( time().microtime() . rand(12312,time()) . rand(234423,123213));
}



/**
* removes all non-alpha numeric characters
* - all user-data from user-input that a used to build up sql-queries
*   should be filtered by this
*
*/
function asAlphaNumeric($str) {
    return preg_replace("/[^0-9A-Z_]/i",'',$str);
}


function asSearchQuery($str) {
    return preg_replace("/[\[\]<>;$\t \/(),\*+:\"'.=]/"," ",$str);
}

function asMatchString($str) {
    #return preg_replace("/[^0-9A-Z_]/i",' ', $str); 
    return preg_replace("/[\/\<\>\`_%&?\"\'()\[\]]/",' ', $str); 
}

function asIdentifier($str) {
    return strtolower( preg_replace("/[^0-9A-Z_]/i",'_', $str) ); 
}

function asCleanString($str)
{
    return preg_replace("/[\\\<\>\`\ยด\"]/",'',$str);
}


function asSecureString($str)
{
    global $sql_obj;
    if(!is_object($sql_obj)) {
        trigger_error("sql_obj not defined", E_USER_ERROR);
    }
    return $sql_obj->secure($str);

}


function getOrderByString($f_order_str=NULL, $default='')
{
    if($tmp= asCleanString($f_order_str)) {
        return 'ORDER BY '. $tmp;
    }
    else if($tmp= asCleanString($default)) {
        return 'ORDER BY '. $tmp;
    }
    return '';
}


/**
* to prevent code injection all user-entered text should be printed asHtml()
*/
function asHtml($str) {

    #$str= str_replace("\\\"", '"',$str);

    return htmlSpecialChars($str, ENT_QUOTES,'UTF-8' );
}

/**
* removes all non alphanumerics
*/
function asKey($str) {
    return preg_replace("/[^0-9a-z_]/",'',strtolower($str));
}







/**
* note: the strToTime-function is useful for converting SQL-Timestrings like 2005-05-02 23:23:32
* into seconds. But this conversion is always into local time -- not GMT. This functions adds the user's
* time-shift to adjust this behavior.
*/
function strToGMTime($str)
{
    return (strToTime($str. " GMT") );
}


/**
* converts a time string like 2005-05-02 23:23:32 from the client's timezone to database GMT-String
*/
function clientTimeStrToGMTString($str)
{
    global $auth;
    $time_offset= 0;
    if(isset($auth->cur_user)) {
        $time_offset= $auth->cur_user->time_offset;
    }
    return getGMTString( strToGMTime($str) - $time_offset  -  confGet('SERVER_TIME_OFFSET'));
}


/**
* converts a time in seconds from the client's timezone to database GMT-String
*/
function clientTimeToGMTString($time)
{
    global $auth;
    $time_offset= 0;
    if(isset($auth->cur_user)) {
        $time_offset= $auth->cur_user->time_offset;
    }
    return getGMTString( $time - $time_offset -  confGet('SERVER_TIME_OFFSET'));
}



/**
* returns GMT-date formated as Y-m-d H:i:s
* - if no argument given, Now is used.
*/
function getGMTString($time=NULL)
{
    if(is_null($time)) {
        $time = time();
    }
    return gmdate("Y-m-d H:i:s", $time);
}


/**
* converts GMT time string (e.g. from database) to client time in seconds
*/
function strToClientTime($str)
{
    if($str == '0000-00-00 00:00:00' || $str == '0000-00-00') {
        return 0;
    }
    global $auth;
    $time_offset= 0;
    if(isset($auth->cur_user)) {
        $time_offset= $auth->cur_user->time_offset;
    }
    return strToTime($str . " GMT")  + $time_offset +  confGet('SERVER_TIME_OFFSET');
}


/**
* converts GMT (in seconds) to Client time (in seconds)
*/
function GMTToClientTime($time)
{
    global $auth;
    $time_offset= 0;
    if(isset($auth->cur_user)) {
        $time_offset= $auth->cur_user->time_offset;
    }
    return $time + $time_offset + confGet('SERVER_TIME_OFFSET');
}






/**
* Rollout a tree structure in a list
*
* - This function is used for comments, but it is object independant, as long as:
*   Objects have children and level attributes
*
* @params:
* - $obj_with_children - reference to object (e.g. of type Comment)
* - $list - reference to resulting, flat list of objects
* - $level recursion depth
*/
function sortObjectsRecursively(&$obj_with_children, &$list, $level=0)
{

    $obj_with_children->level= $level;
    $list[]= $obj_with_children;

    foreach($obj_with_children->children as $id => $child) {
        if($child->id) {
            sortObjectsRecursively(&$child, &$list, $level+1);
        }
    }
    return $list;
}

/**
* returns spam probability as float from 0 .. 1 (or higher for very likely)
*
* - uses confGet('SPAM_WORDS')
* - see conf.inc.php for settings
*/
function isSpam($str) {
    $cleaned= preg_replace("/[^a-z]/",'', strtolower($str));
    $count= 0;
    $count_matched_words=0;
    foreach(confGet('SPAM_WORDS') as $word => $value) {

        if($tmp= substr_count($cleaned, $word)) {
            $count_matched_words += $value;
            $count+= $tmp * $value;
        }
    }
    if(str_word_count($str)) {
        $rate= $count * $count_matched_words/ str_word_count($str) / count(confGet('SPAM_WORDS'));
    }
    else {
        $rate= 0;
    }
    return $rate;
}


/**
* helper function to clear global variables used in render_misc time rendering.
*/
function clearCachedTimeFormats() 
{
    global $g_userFormatTimestamp;
    $g_userFormatTimestamp = NULL;

    global $g_userFormatTime;
    $g_userFormatDate = NULL;

    global $g_userFormatDate;
    $g_userFormatDate = NULL;
}

/**
* Map firephp trace function for easy disabling
*/
function trace($message, $options= '')
{
    if (confGet('USE_FIREPHP')) {
        global $g_firephp;
        if (!isset($g_firephp)) {
            require_once('lib/firephp/FirePHP.class.php');
            #require_once('lib/firephp/fb.php');
            $g_firephp = FirePHP::getInstance(true);
            $options = array('maxObjectDepth' => 1,
                 'maxArrayDepth' => 1,
                 'useNativeJsonEncode' => true,
                 'includeLineNumbers' => true
                 );
 
             $g_firephp->setOptions($options);
        }
        $g_firephp->trace($message, $options);
    }
    else {
        debugMessage($message);
    }
}

?>
Return current item: Streber