Example #1
0
/**
 * Convert special chars (like german umlauts) to ASCII characters.
 *
 * @todo dh> IMHO this function should not be included in a file that gets used often/always.
 * @param string
 * @return string
 */
function replace_special_chars($str)
{
    global $evo_charset;
    if (can_convert_charsets('UTF-8', $evo_charset) && can_convert_charsets('UTF-8', 'ISO-8859-1')) {
        $str = convert_charset($str, 'UTF-8', $evo_charset);
        // TODO: add more...?!
        $search = array('Ä', 'ä', 'Ö', 'ö', 'Ü', 'ü', 'ß', 'à', 'ç', 'è', 'é', 'ì', 'ò', 'ô', 'ù');
        // iso-8859-1
        $replace = array('Ae', 'ae', 'Oe', 'oe', 'Ue', 'ue', 'ss', 'a', 'c', 'e', 'e', 'i', 'o', 'o', 'u');
        foreach ($search as $k => $v) {
            // convert $search to UTF-8
            $search[$k] = convert_charset($v, 'UTF-8', 'ISO-8859-1');
        }
        $str = str_replace($search, $replace, $str);
        // Replace HTML entities
        $str = htmlentities($str, ENT_NOQUOTES, 'UTF-8');
    } else {
        // Replace HTML entities only
        $str = htmlentities($str, ENT_NOQUOTES, $evo_charset);
    }
    // Keep only one char in entities!
    $str = preg_replace('/&(.).+?;/', '$1', $str);
    // Replace non acceptable chars
    $str = preg_replace('/[^A-Za-z0-9_]+/', '-', $str);
    // Remove '-' at start and end:
    $str = preg_replace('/^-+/', '', $str);
    $str = preg_replace('/-+$/', '', $str);
    return $str;
}
Example #2
0
 function set_euckr($str)
 {
     if (is_utf8($str)) {
         $str = convert_charset('utf-8', 'cp949', $str);
     }
     $str = trim($str);
     return $str;
 }
 /**
  * Ping the b2evonet RPC service.
  */
 function ItemSendPing(&$params)
 {
     global $evonetsrv_host, $evonetsrv_port, $evonetsrv_uri;
     global $debug, $baseurl, $instance_name, $evo_charset;
     /**
      * @var Blog
      */
     $item_Blog = $params['Item']->get_Blog();
     $client = new xmlrpc_client($evonetsrv_uri, $evonetsrv_host, $evonetsrv_port);
     $client->debug = $debug == 2;
     $message = new xmlrpcmsg('b2evo.ping', array(new xmlrpcval($item_Blog->ID), new xmlrpcval($baseurl), new xmlrpcval($instance_name), new xmlrpcval(convert_charset($item_Blog->get('name'), 'utf-8', $evo_charset)), new xmlrpcval(convert_charset($item_Blog->get('url'), 'utf-8', $evo_charset)), new xmlrpcval($item_Blog->locale), new xmlrpcval(convert_charset($params['Item']->get('title'), 'utf-8', $evo_charset))));
     $result = $client->send($message);
     $params['xmlrpcresp'] = $result;
     return true;
 }
Example #4
0
/**
 * Sets a parameter with values from the request or to provided default,
 * except if param is already set!
 *
 * Also removes magic quotes if they are set automatically by PHP.
 * Also forces type.
 * Priority order: POST, GET, COOKIE, DEFAULT.
 *
 * @param string Variable to set
 * @param string Force value type to one of:
 * - integer
 * - float, double
 * - string (strips (HTML-)Tags, trims whitespace)
 * - array	(TODO:  array/integer  , array/array/string )
 * - html (does nothing)
 * - '' (does nothing)
 * - '/^...$/' check regexp pattern match (string)
 * - boolean (will force type to boolean, but you can't use 'true' as a default since it has special meaning. There is no real reason to pass booleans on a URL though. Passing 0 and 1 as integers seems to be best practice).
 * Value type will be forced only if resulting value (probably from default then) is !== NULL
 * @param mixed Default value or TRUE if user input required
 * @param boolean Do we need to memorize this to regenerate the URL for this page?
 * @param boolean Override if variable already set
 * @param boolean Force setting of variable to default if no param is sent and var wasn't set before
 * @param mixed true will refuse illegal values,
 *              false will try to convert illegal to legal values,
 *              'allow_empty' will refuse illegal values but will always accept empty values (This helps blocking dirty spambots or borked index bots. Saves a lot of processor time by killing invalid requests)
 * @return mixed Final value of Variable, or false if we don't force setting and did not set
 */
function param($var, $type = '', $default = '', $memorize = false, $override = false, $use_default = true, $strict_typing = 'allow_empty')
{
    global $Debuglog, $debug, $evo_charset, $io_charset;
    // NOTE: we use $GLOBALS[$var] instead of $$var, because otherwise it would conflict with param names which are used as function params ("var", "type", "default", ..)!
    /*
     * STEP 1 : Set the variable
     *
     * Check if already set
     * WARNING: when PHP register globals is ON, COOKIES get priority over GET and POST with this!!!
     *   dh> I never understood that comment.. does it refer to "variables_order" php.ini setting?
     *		fp> I guess
     */
    if (!isset($GLOBALS[$var]) || $override) {
        if (isset($_POST[$var])) {
            $GLOBALS[$var] = remove_magic_quotes($_POST[$var]);
            // if( isset($Debuglog) ) $Debuglog->add( 'param(-): '.$var.'='.$GLOBALS[$var].' set by POST', 'params' );
        } elseif (isset($_GET[$var])) {
            $GLOBALS[$var] = remove_magic_quotes($_GET[$var]);
            // if( isset($Debuglog) ) $Debuglog->add( 'param(-): '.$var.'='.$GLOBALS[$var].' set by GET', 'params' );
        } elseif (isset($_COOKIE[$var])) {
            $GLOBALS[$var] = remove_magic_quotes($_COOKIE[$var]);
            // if( isset($Debuglog) ) $Debuglog->add( 'param(-): '.$var.'='.$GLOBALS[$var].' set by COOKIE', 'params' );
        } elseif ($default === true) {
            bad_request_die(sprintf(T_('Parameter «%s» is required!'), $var));
        } elseif ($use_default) {
            // We haven't set any value yet and we really want one: use default:
            $GLOBALS[$var] = $default;
            // echo '<br>param(-): '.$var.'='.$GLOBALS[$var].' set by default';
            // if( isset($Debuglog) ) $Debuglog->add( 'param(-): '.$var.'='.$GLOBALS[$var].' set by default', 'params' );
        } else {
            // param not found! don't set the variable.
            // Won't be memorized nor type-forced!
            return false;
        }
    } else {
        // Variable was already set but we need to remove the auto quotes
        $GLOBALS[$var] = remove_magic_quotes($GLOBALS[$var]);
        // if( isset($Debuglog) ) $Debuglog->add( 'param(-): '.$var.' already set to ['.var_export($GLOBALS[$var], true).']!', 'params' );
    }
    if (isset($io_charset) && !empty($evo_charset)) {
        $GLOBALS[$var] = convert_charset($GLOBALS[$var], $evo_charset, $io_charset);
    }
    /*
     * STEP 2: make sure the data fits the expected type
     *
     * type will be forced even if it was set before and not overriden
     */
    if (!empty($type) && $GLOBALS[$var] !== NULL) {
        // Force the type
        // echo "forcing type!";
        switch ($type) {
            case 'html':
                // do nothing
                if (isset($Debuglog)) {
                    $Debuglog->add('param(-): <strong>' . $var . '</strong> as RAW Unsecure HTML', 'params');
                }
                break;
            case 'string':
                // strip out any html:
                // echo $var, '=', $GLOBALS[$var], '<br />';
                if (!is_scalar($GLOBALS[$var])) {
                    // This happens if someone uses "foo[]=x" where "foo" is expected as string
                    // TODO: dh> debug_die() instead?
                    $GLOBALS[$var] = '';
                    $Debuglog->add('param(-): <strong>' . $var . '</strong> is not scalar!', 'params');
                } else {
                    $GLOBALS[$var] = trim(strip_tags($GLOBALS[$var]));
                    // Make sure the string is a single line
                    $GLOBALS[$var] = preg_replace('¤\\r|\\n¤', '', $GLOBALS[$var]);
                }
                $Debuglog->add('param(-): <strong>' . $var . '</strong> as string', 'params');
                break;
            default:
                if (substr($type, 0, 1) == '/') {
                    // We want to match against a REGEXP:
                    if (preg_match($type, $GLOBALS[$var])) {
                        // Okay, match
                        if (isset($Debuglog)) {
                            $Debuglog->add('param(-): <strong>' . $var . '</strong> matched against ' . $type, 'params');
                        }
                    } elseif ($strict_typing == 'allow_empty' && empty($GLOBALS[$var])) {
                        // No match but we accept empty value:
                        if (isset($Debuglog)) {
                            $Debuglog->add('param(-): <strong>' . $var . '</strong> is empty: ok', 'params');
                        }
                    } elseif ($strict_typing) {
                        // We cannot accept this MISMATCH:
                        bad_request_die(sprintf(T_('Illegal value received for parameter &laquo;%s&raquo;!'), $var));
                    } else {
                        // Fall back to default:
                        $GLOBALS[$var] = $default;
                        if (isset($Debuglog)) {
                            $Debuglog->add('param(-): <strong>' . $var . '</strong> DID NOT match ' . $type . ' set to default value=' . $GLOBALS[$var], 'params');
                        }
                    }
                    // From now on, consider this as a string: (we need this when memorizing)
                    $type = 'string';
                } elseif ($GLOBALS[$var] === '') {
                    // Special handling of empty values.
                    if ($strict_typing === false && $use_default) {
                        // ADDED BY FP 2006-07-06
                        // We want to consider empty values as invalid and fall back to the default value:
                        $GLOBALS[$var] = $default;
                    } else {
                        // We memorize the empty value as NULL:
                        // fplanque> note: there might be side effects to this, but we need
                        // this to distinguish between 0 and 'no input'
                        // Note: we do this after regexps because we may or may not want to allow empty strings in regexps
                        $GLOBALS[$var] = NULL;
                        if (isset($Debuglog)) {
                            $Debuglog->add('param(-): <strong>' . $var . '</strong> set to NULL', 'params');
                        }
                    }
                } elseif ($GLOBALS[$var] === array()) {
                    if ($strict_typing === false && $use_default) {
                        // ADDED BY FP 2006-09-07
                        // We want to consider empty values as invalid and fall back to the default value:
                        $GLOBALS[$var] = $default;
                    }
                } else {
                    if ($strict_typing) {
                        // We want to make sure the value is valid:
                        $regexp = '';
                        switch ($type) {
                            case 'boolean':
                                $regexp = '/^(0|1|false|true)$/i';
                                break;
                            case 'integer':
                                $regexp = '/^(\\+|-)?[0-9]+$/';
                                break;
                            case 'float':
                            case 'double':
                                $regexp = '/^(\\+|-)?[0-9]+(.[0-9]+)?$/';
                                break;
                                // Note: other types are not tested here.
                        }
                        if ($strict_typing == 'allow_empty' && empty($GLOBALS[$var])) {
                            // We have an empty value and we accept it
                            // ok..
                        } elseif (!empty($regexp) && (!is_scalar($GLOBALS[$var]) || !preg_match($regexp, $GLOBALS[$var]))) {
                            // Value does not match!
                            bad_request_die(sprintf(T_('Illegal value received for parameter &laquo;%s&raquo;!'), $var));
                        }
                    }
                    // Change the variable type:
                    settype($GLOBALS[$var], $type);
                    if (isset($Debuglog)) {
                        $Debuglog->add('param(-): <strong>' . $var . '</strong> typed to ' . $type . ', new value=' . $GLOBALS[$var], 'params');
                    }
                }
        }
    }
    /*
     * STEP 3: memorize the value for later url regeneration
     */
    if ($memorize) {
        // Memorize this parameter
        memorize_param($var, $type, $default);
    }
    // echo $var, '(', gettype($GLOBALS[$var]), ')=', $GLOBALS[$var], '<br />';
    return $GLOBALS[$var];
}
Example #5
0
/**
 * IDNA-Encode URL to Punycode.
 * @param string URL
 * @return string Encoded URL (ASCII)
 */
function idna_encode($url)
{
    global $evo_charset;
    $url_utf8 = convert_charset($url, 'utf-8', $evo_charset);
    if (version_compare(PHP_VERSION, '5', '>=')) {
        load_class('_ext/idna/_idna_convert.class.php', 'idna_convert');
        $IDNA = new idna_convert();
    } else {
        load_class('_ext/idna/_idna_convert.class.php4', 'Net_IDNA_php4');
        $IDNA = new Net_IDNA_php4();
    }
    //echo '['.$url_utf8.'] ';
    $url = $IDNA->encode($url_utf8);
    /* if( $idna_error = $IDNA->get_last_error() )
    	{
    		echo $idna_error;
    	} */
    // echo '['.$url.']<br>';
    return $url;
}
Example #6
0
 /**
  * @ignore
  */
 function T_($string, $req_locale = '')
 {
     /**
      * The translations keyed by locale. They get loaded through include() of _global.php
      * @var array
      * @static
      */
     static $trans = array();
     global $current_locale, $locales, $Debuglog, $locales_path, $evo_charset;
     if (empty($req_locale)) {
         // By default we use the current locale
         if (empty($current_locale)) {
             // don't translate if we have no locale
             return $string;
         }
         $req_locale = $current_locale;
     }
     if (!isset($locales[$req_locale]['messages'])) {
         $Debuglog->add('No messages file path for locale. $locales["' . $req_locale . '"] is ' . var_export(@$locales[$req_locale], true), 'locale');
         $locales[$req_locale]['messages'] = false;
     }
     $messages = $locales[$req_locale]['messages'];
     // replace special characters to msgid-equivalents
     $search = str_replace(array("\n", "\r", "\t"), array('\\n', '', '\\t'), $string);
     // echo "Translating ", $search, " to $messages<br />";
     if (!isset($trans[$messages])) {
         // Translations for current locale have not yet been loaded:
         // echo 'LOADING', dirname(__FILE__).'/../locales/'. $messages. '/_global.php';
         if (file_exists($locales_path . $messages . '/_global.php')) {
             include_once $locales_path . $messages . '/_global.php';
         }
         if (!isset($trans[$messages])) {
             // Still not loaded... file doesn't exist, memorize that no translations are available
             // echo 'file not found!';
             $trans[$messages] = array();
             /*
             				May be an english locale without translation.
             				TODO: when refactoring locales, assign a key for 'original english'.
             				$Debuglog->add( 'No messages found for locale ['.$req_locale.'],
             												message file [/locales/'.$messages.'/_global.php]', 'locale' );*/
         }
     }
     if (isset($trans[$messages][$search])) {
         // If the string has been translated:
         $r = $trans[$messages][$search];
         $messages_charset = $locales[$req_locale]['charset'];
     } else {
         // echo "Not found!";
         // Return the English string:
         $r = $string;
         $messages_charset = 'iso-8859-1';
         // our .php file encoding
     }
     if (!empty($evo_charset)) {
         $r = convert_charset($r, $evo_charset, $messages_charset);
     }
     return $r;
 }
Example #7
0
/**
 * A helper function to conditionally convert a string from current charset to UTF-8
 *
 * @param mixed
 * @return mixed
 */
function current_charset_to_utf8($a)
{
    global $current_charset;
    if (is_string($a) && $current_charset != '' && $current_charset != 'utf-8') {
        return convert_charset($a, 'utf-8', $current_charset);
    }
    return $a;
}
Example #8
0
 /**
  *  Get languages defined in the language directory
  */
 function get_fs_languages($target_charset = null)
 {
     if (empty($target_charset)) {
         $target_charset = get_pwg_charset();
     }
     $target_charset = strtolower($target_charset);
     $dir = opendir(PHPWG_ROOT_PATH . 'language');
     while ($file = readdir($dir)) {
         if ($file != '.' and $file != '..') {
             $path = PHPWG_ROOT_PATH . 'language/' . $file;
             if (is_dir($path) and !is_link($path) and preg_match('/^[a-zA-Z0-9-_]+$/', $file) and file_exists($path . '/common.lang.php')) {
                 $language = array('name' => $file, 'code' => $file, 'version' => '0', 'uri' => '', 'author' => '');
                 $plg_data = implode('', file($path . '/common.lang.php'));
                 if (preg_match("|Language Name:\\s*(.+)|", $plg_data, $val)) {
                     $language['name'] = trim($val[1]);
                     $language['name'] = convert_charset($language['name'], 'utf-8', $target_charset);
                 }
                 if (preg_match("|Version:\\s*([\\w.-]+)|", $plg_data, $val)) {
                     $language['version'] = trim($val[1]);
                 }
                 if (preg_match("|Language URI:\\s*(https?:\\/\\/.+)|", $plg_data, $val)) {
                     $language['uri'] = trim($val[1]);
                 }
                 if (preg_match("|Author:\\s*(.+)|", $plg_data, $val)) {
                     $language['author'] = trim($val[1]);
                 }
                 if (preg_match("|Author URI:\\s*(https?:\\/\\/.+)|", $plg_data, $val)) {
                     $language['author uri'] = trim($val[1]);
                 }
                 if (!empty($language['uri']) and strpos($language['uri'], 'extension_view.php?eid=')) {
                     list(, $extension) = explode('extension_view.php?eid=', $language['uri']);
                     if (is_numeric($extension)) {
                         $language['extension'] = $extension;
                     }
                 }
                 // IMPORTANT SECURITY !
                 $language = array_map('htmlspecialchars', $language);
                 $this->fs_languages[$file] = $language;
             }
         }
     }
     closedir($dir);
     @uasort($this->fs_languages, 'name_compare');
 }
    없으면 mb_convert_encoding 함수를 사용한다.
    둘다 없으면 사용할 수 없다.
    */
    function convert_charset($from_charset, $to_charset, $str)
    {
        if (function_exists('iconv')) {
            return iconv($from_charset, $to_charset, $str);
        } elseif (function_exists('mb_convert_encoding')) {
            return mb_convert_encoding($str, $to_charset, $from_charset);
        } else {
            die("Not found 'iconv' or 'mbstring' library in server.");
        }
    }
}
if (strtolower($g4[charset]) == 'euc-kr') {
    $reg_mb_nick = convert_charset('UTF-8', 'CP949', $reg_mb_nick);
}
// 별명은 한글, 영문, 숫자만 가능
if (!check_string($reg_mb_nick, _G4_HANGUL_ + _G4_ALPHABETIC_ + _G4_NUMERIC_)) {
    echo "110";
    // 별명은 공백없이 한글, 영문, 숫자만 입력 가능합니다.
} else {
    if (strlen($reg_mb_nick) < 4) {
        echo "120";
        // 4글자 이상 입력
    } else {
        $row = sql_fetch(" select count(*) as cnt from {$g4['member_table']} where mb_nick = '{$reg_mb_nick}' ");
        if ($row[cnt]) {
            echo "130";
            // 이미 존재하는 별명
        } else {
Example #10
0
/**
 * Returns the number of the words in a string, sans HTML
 *
 * @todo dh> Test if http://de3.php.net/manual/en/function.str-word-count.php#85579 works better/faster
 *           (only one preg_* call and no loop).
 *
 * @param string The string.
 * @return integer Number of words.
 *
 * @internal PHP's str_word_count() is not accurate. Inaccuracy reported
 *           by sam2kb: http://forums.b2evolution.net/viewtopic.php?t=16596
 */
function bpost_count_words($str)
{
    global $evo_charset;
    $str = trim(strip_tags($str));
    // Note: The \p escape sequence is available since PHP 4.4.0 and 5.1.0.
    if (@preg_match('|\\pL|u', 'foo') === false) {
        return str_word_count($str);
    }
    $count = 0;
    foreach (preg_split('#\\s+#', convert_charset($str, 'UTF-8', $evo_charset), -1, PREG_SPLIT_NO_EMPTY) as $word) {
        if (preg_match('#\\pL#u', $word)) {
            ++$count;
        }
    }
    return $count;
}
Example #11
0
/**
 * Sends a mail, wrapping PHP's mail() function.
 *
 * {@link $current_locale} will be used to set the charset.
 *
 * Note: we use a single \n as line ending, though it does not comply to
 * {@link http://www.faqs.org/rfcs/rfc2822 RFC2822}, but seems to be safer,
 * because some mail transfer agents replace \n by \r\n automatically.
 *
 * @todo Unit testing with "nice addresses" This gets broken over and over again.
 *
 * @param string Recipient, either email only or in "Name <*****@*****.**>" format (RFC2822).
 *               Can be multiple comma-separated addresses.
 * @param string Subject of the mail
 * @param string The message text
 * @param string From address, being added to headers (we'll prevent injections);
 *               see {@link http://securephp.damonkohler.com/index.php/Email_Injection}.
 *               Might be just an email address or of the same form as {@link $to}.
 *               {@link $notify_from} gets used as default (if NULL).
 * @param array Additional headers ( headername => value ). Take care of injection!
 * @return boolean True if mail could be sent (not necessarily delivered!), false if not - (return value of {@link mail()})
 */
function send_mail($to, $subject, $message, $from = NULL, $headers = array())
{
    global $debug, $app_name, $app_version, $current_locale, $current_charset, $evo_charset, $locales, $Debuglog, $notify_from;
    $NL = "\n";
    if (is_windows()) {
        // fplanque: Windows XP, Apache 1.3, PHP 4.4, MS SMTP : will not accept "nice" addresses.
        $to = preg_replace('/^.*?<(.+?)>$/', '$1', $to);
        $from = preg_replace('/^.*?<(.+?)>$/', '$1', $from);
    }
    // echo 'sending email to: ['.htmlspecialchars($to).'] from ['.htmlspecialchars($from).']';
    if (!is_array($headers)) {
        // Make sure $headers is an array
        $headers = array($headers);
    }
    // Specify charset and content-type of email
    $headers['Content-Type'] = 'text/plain; charset=' . $current_charset;
    $headers['X-Mailer'] = $app_name . ' ' . $app_version . ' - PHP/' . phpversion();
    $headers['X-Remote-Addr'] = implode(',', get_ip_list());
    // -- Build headers ----
    if (empty($from)) {
        $from = $notify_from;
    } else {
        $from = trim($from);
    }
    if (!empty($from)) {
        // From has to go into headers
        $from_save = preg_replace('~(\\r|\\n).*$~s', '', $from);
        // Prevent injection! (remove everything after (and including) \n or \r)
        if ($from != $from_save) {
            if (strpos($from_save, '<') !== false && !strpos($from_save, '>')) {
                // We have probably stripped the '>' at the end!
                $from_save .= '>';
            }
            // Add X-b2evo notification mail header about this
            $headers['X-b2evo'] = 'Fixed email header injection (From)';
            $Debuglog->add('Detected email injection! Fixed &laquo;' . htmlspecialchars($from) . '&raquo; to &laquo;' . htmlspecialchars($from_save) . '&raquo;.', 'security');
            $from = $from_save;
        }
        $headers['From'] = $from;
    }
    $headerstring = '';
    reset($headers);
    while (list($lKey, $lValue) = each($headers)) {
        // Add additional headers
        $headerstring .= $lKey . ': ' . $lValue . $NL;
    }
    if (function_exists('mb_encode_mimeheader')) {
        // encode subject
        $subject = mb_encode_mimeheader($subject, mb_internal_encoding(), 'B', $NL);
    }
    $message = str_replace(array("\r\n", "\r"), $NL, $message);
    // Convert encoding of message (from internal encoding to the one of the message):
    $message = convert_charset($message, $current_charset, $evo_charset);
    if ($debug > 1) {
        // We agree to die for debugging...
        if (!mail($to, $subject, $message, $headerstring)) {
            debug_die('Sending mail from &laquo;' . htmlspecialchars($from) . '&raquo; to &laquo;' . htmlspecialchars($to) . '&raquo;, Subject &laquo;' . htmlspecialchars($subject) . '&raquo; FAILED.');
        }
    } else {
        // Soft debugging only....
        if (!@mail($to, $subject, $message, $headerstring)) {
            $Debuglog->add('Sending mail from &laquo;' . htmlspecialchars($from) . '&raquo; to &laquo;' . htmlspecialchars($to) . '&raquo;, Subject &laquo;' . htmlspecialchars($subject) . '&raquo; FAILED.', 'error');
            return false;
        }
    }
    $Debuglog->add('Sent mail from &laquo;' . htmlspecialchars($from) . '&raquo; to &laquo;' . htmlspecialchars($to) . '&raquo;, Subject &laquo;' . htmlspecialchars($subject) . '&raquo;.');
    return true;
}
Example #12
0
/**
 * Check the validity of a given URL
 *
 * Checks allowed URI schemes and URL ban list.
 * URL can be empty.
 *
 * Note: We have a problem when trying to "antispam" a keyword which is already blacklisted
 * If that keyword appears in the URL... then the next page has a bad referer! :/
 *
 * {@internal This function gets tested in misc.funcs.simpletest.php.}}
 *
 * @param string Url to validate
 * @param string
 * @param boolean also do an antispam check on the url
 * @return mixed false (which means OK) or error message
 */
function validate_url($url, $context = 'posting', $antispam_check = true)
{
    global $Debuglog, $debug;
    if (empty($url)) {
        // Empty URL, no problem
        return false;
    }
    $verbose = $debug || $context != 'commenting';
    $allowed_uri_schemes = get_allowed_uri_schemes($context);
    // Validate URL structure
    if ($url[0] == '$') {
        // This is a 'special replace code' URL (used in footers)
        if (!preg_match('¤\\$([a-z_]+)\\$¤', $url)) {
            return T_('Invalid URL $code$ format');
        }
    } elseif (preg_match('~^\\w+:~', $url)) {
        // there's a scheme and therefor an absolute URL:
        if (substr($url, 0, 7) == 'mailto:') {
            // mailto:link
            if (!in_array('mailto', $allowed_uri_schemes)) {
                // Scheme not allowed
                $scheme = 'mailto:';
                $Debuglog->add('URI scheme &laquo;' . $scheme . '&raquo; not allowed!', 'error');
                return $verbose ? sprintf(T_('URI scheme "%s" not allowed.'), htmlspecialchars($scheme)) : T_('URI scheme not allowed.');
            }
            preg_match('~^(mailto):(.*?)(\\?.*)?$~', $url, $match);
            if (!$match) {
                return $verbose ? sprintf(T_('Invalid email link: %s.'), htmlspecialchars($url)) : T_('Invalid email link.');
            } elseif (!is_email($match[2])) {
                return $verbose ? sprintf(T_('Supplied email address (%s) is invalid.'), htmlspecialchars($match[2])) : T_('Invalid email address.');
            }
        } elseif (substr($url, 0, 6) == 'clsid:') {
            // clsid:link
            if (!in_array('clsid', $allowed_uri_schemes)) {
                // Scheme not allowed
                $scheme = 'clsid:';
                $Debuglog->add('URI scheme &laquo;' . $scheme . '&raquo; not allowed!', 'error');
                return $verbose ? sprintf(T_('URI scheme "%s" not allowed.'), htmlspecialchars($scheme)) : T_('URI scheme not allowed.');
            }
            if (!preg_match('¤^(clsid):([a-fA-F0-9\\-]+)$¤', $url, $match)) {
                return T_('Invalid class ID format');
            }
        } elseif (substr($url, 0, 11) == 'javascript:') {
            // javascript:
            // Basically there could be anything here
            if (!in_array('javascript', $allowed_uri_schemes)) {
                // Scheme not allowed
                $scheme = 'javascript:';
                $Debuglog->add('URI scheme &laquo;' . $scheme . '&raquo; not allowed!', 'error');
                return $verbose ? sprintf(T_('URI scheme "%s" not allowed.'), htmlspecialchars($scheme)) : T_('URI scheme not allowed.');
            }
            preg_match('¤^(javascript):¤', $url, $match);
        } else {
            // convert URL to IDN:
            load_funcs('_ext/idna/_idna_convert.class.php');
            $IDNA = new Net_IDNA_php4();
            global $evo_charset;
            $url = $IDNA->encode(convert_charset($url, 'utf-8', $evo_charset));
            if (!preg_match('~^           # start
				([a-z][a-z0-9+.\\-]*)             # scheme
				://                              # authorize absolute URLs only ( // not present in clsid: -- problem? ; mailto: handled above)
				(\\w+(:\\w+)?@)?                   # username or username and password (optional)
				( localhost |
						[a-z0-9]([a-z0-9\\-])*            # Don t allow anything too funky like entities
						\\.                               # require at least 1 dot
						[a-z0-9]([a-z0-9.\\-])+           # Don t allow anything too funky like entities
				)
				(:[0-9]+)?                       # optional port specification
				[^ ]*                            # allow no space
				$~ix', $url, $match)) {
                // Cannot validate URL structure
                $Debuglog->add('URL &laquo;' . $url . '&raquo; does not match url pattern!', 'error');
                return $verbose ? sprintf(T_('Invalid URL format (%s).'), htmlspecialchars($url)) : T_('Invalid URL format.');
            }
            $scheme = strtolower($match[1]);
            if (!in_array($scheme, $allowed_uri_schemes)) {
                // Scheme not allowed
                $Debuglog->add('URI scheme &laquo;' . $scheme . '&raquo; not allowed!', 'error');
                return $verbose ? sprintf(T_('URI scheme "%s" not allowed.'), htmlspecialchars($scheme)) : T_('URI scheme not allowed.');
            }
        }
    } else {
        // URL is relative..
        if ($context == 'commenting') {
            // We do not allow relative URLs in comments
            return $verbose ? sprintf(T_('URL "%s" must be absolute.'), htmlspecialchars($url)) : T_('URL must be absolute.');
        }
        $char = substr($url, 0, 1);
        if ($char != '/' && $char != '#') {
            // must start with a slash or hash (for HTML anchors to the same page)
            return $verbose ? sprintf(T_('URL "%s" must be a full path starting with "/" or an anchor starting with "#".'), htmlspecialchars($url)) : T_('URL must be a full path starting with "/" or an anchor starting with "#".');
        }
    }
    if ($antispam_check) {
        // Search for blocked keywords:
        if ($block = antispam_check($url)) {
            return $verbose ? sprintf(T_('URL "%s" not allowed: blacklisted word "%s".'), htmlspecialchars($url), $block) : T_('URL not allowed');
        }
    }
    return false;
    // OK
}
Example #13
0
/**
 * Sets a parameter with values from the request or to provided default,
 * except if param is already set!
 *
 * Also removes magic quotes if they are set automatically by PHP.
 * Also forces type.
 * Priority order: POST, GET, COOKIE, DEFAULT.
 *
 * @todo when bad_request_die() gets called, the GLOBAL should not be left set to the invalid value!
 * fp> Why? if the process dies anyway
 *
 * @param string Variable to set
 * @param string Force value type to one of:
 * - integer
 * - float, double
 * - string (strips (HTML-)Tags, trims whitespace)
 * - text like string but allows multiple lines
 * - array (it may contains arbitrary array elements) NOTE: If there is one way to avoid and use some other array type then it should not be used
 * - array:integer (elements of array must be integer)
 * - array:string (strips (HTML-)Tags, trims whitespace of array's elements)
 * - array:/regexp/ (elements of array must match to the given regular expression) e.g. 'array:/^[a-z]*$/'
 * - array:array:integer (two dimensional array and the elements must be integers)
 * - array:array:string (strips (HTML-)Tags, trims whitespace of the two dimensional array's elements)
 * - html (does nothing, for now)
 * - raw (does nothing)
 * - '' (does nothing) -- DEPRECATED, use "raw" instead
 * - '/^...$/' check regexp pattern match (string)
 * - boolean (will force type to boolean, but you can't use 'true' as a default since it has special meaning. There is no real reason to pass booleans on a URL though. Passing 0 and 1 as integers seems to be best practice).
 * - url (like string but dies on illegal urls)
 * Value type will be forced only if resulting value (probably from default then) is !== NULL
 * @param mixed Default value or TRUE if user input required
 * @param boolean Do we need to memorize this to regenerate the URL for this page?
 * @param boolean Override if variable already set
 * @param boolean Force setting of variable to default if no param is sent and var wasn't set before
 * @param mixed true will refuse illegal values,
 *              false will try to convert illegal to legal values,
 *              'allow_empty' will refuse illegal values but will always accept empty values (This helps blocking dirty spambots or borked index bots. Saves a lot of processor time by killing invalid requests)
 * @return mixed Final value of Variable, or false if we don't force setting and did not set
 */
function param($var, $type = 'raw', $default = '', $memorize = false, $override = false, $use_default = true, $strict_typing = 'allow_empty')
{
    global $Debuglog, $debug, $evo_charset, $io_charset;
    // NOTE: we use $GLOBALS[$var] instead of $$var, because otherwise it would conflict with param names which are used as function params ("var", "type", "default", ..)!
    /*
     * STEP 1 : Set the variable
     *
     * Check if already set
     * WARNING: when PHP register globals is ON, COOKIES get priority over GET and POST with this!!!
     *   dh> I never understood that comment.. does it refer to "variables_order" php.ini setting?
     *		fp> I guess
     */
    if (!isset($GLOBALS[$var]) || $override) {
        if (isset($_POST[$var])) {
            $GLOBALS[$var] = remove_magic_quotes($_POST[$var]);
            // if( isset($Debuglog) ) $Debuglog->add( 'param(-): '.$var.'='.$GLOBALS[$var].' set by POST', 'params' );
        } elseif (isset($_GET[$var])) {
            $GLOBALS[$var] = remove_magic_quotes($_GET[$var]);
            // if( isset($Debuglog) ) $Debuglog->add( 'param(-): '.$var.'='.$GLOBALS[$var].' set by GET', 'params' );
        } elseif (isset($_COOKIE[$var])) {
            $GLOBALS[$var] = remove_magic_quotes($_COOKIE[$var]);
            // if( isset($Debuglog) ) $Debuglog->add( 'param(-): '.$var.'='.$GLOBALS[$var].' set by COOKIE', 'params' );
        } elseif ($default === true) {
            bad_request_die(sprintf(T_('Parameter &laquo;%s&raquo; is required!'), $var));
        } elseif ($use_default) {
            // We haven't set any value yet and we really want one: use default:
            if (in_array($type, array('array', 'array:integer', 'array:string', 'array:array:integer', 'array:array:string')) && $default === '') {
                // Change default '' into array() (otherwise there would be a notice with settype() below)
                $default = array();
            }
            $GLOBALS[$var] = $default;
            // echo '<br>param(-): '.$var.'='.$GLOBALS[$var].' set by default';
            // if( isset($Debuglog) ) $Debuglog->add( 'param(-): '.$var.'='.$GLOBALS[$var].' set by default', 'params' );
        } else {
            // param not found! don't set the variable.
            // Won't be memorized nor type-forced!
            return false;
        }
    } else {
        // Variable was already set but we need to remove the auto quotes
        $GLOBALS[$var] = remove_magic_quotes($GLOBALS[$var]);
        // if( isset($Debuglog) ) $Debuglog->add( 'param(-): '.$var.' already set to ['.var_export($GLOBALS[$var], true).']!', 'params' );
    }
    if (isset($io_charset) && !empty($evo_charset)) {
        $GLOBALS[$var] = convert_charset($GLOBALS[$var], $evo_charset, $io_charset);
    }
    // Check if the type is the special array or regexp
    if (substr($type, 0, 7) == 'array:/') {
        // It is an array type param which may contains elements mathcing to the given regular expression
        $elements_regexp = substr($type, 6);
        $elements_type = 'string';
        $type = 'array:regexp';
    }
    /*
     * STEP 2: make sure the data fits the expected type
     *
     * type will be forced even if it was set before and not overriden
     */
    if (!empty($type) && $GLOBALS[$var] !== NULL) {
        // Force the type
        // echo "forcing type!";
        switch ($type) {
            case 'html':
                // Technically does the same as "raw", but may do more in the future.
            // Technically does the same as "raw", but may do more in the future.
            case 'raw':
                if (!is_scalar($GLOBALS[$var])) {
                    // This happens if someone uses "foo[]=x" where "foo" is expected as string
                    debug_die('param(-): <strong>' . $var . '</strong> is not scalar!');
                }
                // Clean utf8:
                $GLOBALS[$var] = utf8_clean($GLOBALS[$var]);
                // do nothing
                if (isset($Debuglog)) {
                    $Debuglog->add('param(-): <strong>' . $var . '</strong> as RAW Unsecure HTML', 'params');
                }
                break;
            case 'htmlspecialchars':
                if (!is_scalar($GLOBALS[$var])) {
                    // This happens if someone uses "foo[]=x" where "foo" is expected as string
                    debug_die('param(-): <strong>' . $var . '</strong> is not scalar!');
                }
                // convert all html to special characters:
                $GLOBALS[$var] = utf8_trim(htmlspecialchars($GLOBALS[$var], ENT_COMPAT, $evo_charset));
                // cross-platform newlines:
                $GLOBALS[$var] = preg_replace("~(\r\n|\r)~", "\n", $GLOBALS[$var]);
                $Debuglog->add('param(-): <strong>' . $var . '</strong> as text with html special chars', 'params');
                break;
            case 'text':
                if (!is_scalar($GLOBALS[$var])) {
                    // This happens if someone uses "foo[]=x" where "foo" is expected as string
                    debug_die('param(-): <strong>' . $var . '</strong> is not scalar!');
                }
                // strip out any html:
                $GLOBALS[$var] = utf8_trim(utf8_strip_tags($GLOBALS[$var]));
                // cross-platform newlines:
                $GLOBALS[$var] = preg_replace("~(\r\n|\r)~", "\n", $GLOBALS[$var]);
                $Debuglog->add('param(-): <strong>' . $var . '</strong> as text', 'params');
                break;
            case 'string':
                if (!is_scalar($GLOBALS[$var])) {
                    // This happens if someone uses "foo[]=x" where "foo" is expected as string
                    debug_die('param(-): <strong>' . $var . '</strong> is not scalar!');
                }
                // echo $var, '=', $GLOBALS[$var], '<br />';
                // Make sure the string is a single line
                $GLOBALS[$var] = preg_replace('~\\r|\\n~', '', $GLOBALS[$var]);
                // strip out any html:
                $GLOBALS[$var] = utf8_strip_tags($GLOBALS[$var]);
                // echo "param $var=".$GLOBALS[$var]."<br />\n";
                $GLOBALS[$var] = utf8_trim($GLOBALS[$var]);
                // echo "param $var=".$GLOBALS[$var]."<br />\n";
                $Debuglog->add('param(-): <strong>' . $var . '</strong> as string', 'params');
                break;
            case 'url':
                if (!is_scalar($GLOBALS[$var])) {
                    // This happens if someone uses "foo[]=x" where "foo" is expected as string
                    debug_die('param(-): <strong>' . $var . '</strong> is not scalar!');
                }
                // Decode url:
                $GLOBALS[$var] = urldecode($GLOBALS[$var]);
                // strip out any html:
                $GLOBALS[$var] = utf8_trim(utf8_strip_tags($GLOBALS[$var]));
                // Remove new line chars and double quote from url
                $GLOBALS[$var] = preg_replace('~\\r|\\n|"~', '', $GLOBALS[$var]);
                if (!empty($GLOBALS[$var]) && !preg_match('#^(/|\\?|https?://)#i', $GLOBALS[$var])) {
                    // We cannot accept this MISMATCH:
                    bad_request_die(sprintf(T_('Illegal value received for parameter &laquo;%s&raquo;!'), $var));
                }
                $Debuglog->add('param(-): <strong>' . $var . '</strong> as url', 'params');
                break;
            case 'array:integer':
            case 'array:array:integer':
                // Set elements type to integer, and set the corresponding regular expression
                $elements_type = 'integer';
                $elements_regexp = '/^(\\+|-)?[0-9]+$/';
            case 'array':
            case 'array:string':
            case 'array:regexp':
            case 'array:array:string':
                if (!is_array($GLOBALS[$var])) {
                    // This param must be array
                    debug_die('param(-): <strong>' . $var . '</strong> is not array!');
                }
                // Store current array in temp var for checking and preparing
                $globals_var = $GLOBALS[$var];
                // Check if the given array type is one dimensional array
                $one_dimensional = $type == 'array' || $type == 'array:integer' || $type == 'array:string' || $type == 'array:regexp';
                // Check if the given array type should contains string elements
                $contains_strings = $type == 'array:string' || $type == 'array:array:string';
                if ($one_dimensional) {
                    // Convert to a two dimensional array to handle one and two dimensional arrays the same way
                    $globals_var = array($globals_var);
                }
                foreach ($globals_var as $i => $var_array) {
                    if (!is_array($var_array)) {
                        // This param must be array
                        // Note: In case of one dimensional array params this will never happen
                        debug_die('param(-): <strong>' . $var . '[' . $i . ']</strong> is not array!');
                    }
                    if ($type == 'array') {
                        // This param may contain any kind of elements we need to check and validate it recursively
                        $globals_var[$i] = param_check_general_array($var_array);
                        break;
                    }
                    foreach ($var_array as $j => $var_value) {
                        if (!is_scalar($var_value)) {
                            // This happens if someone uses "foo[][]=x" where "foo[]" is expected as string
                            debug_die('param(-): element of array <strong>' . $var . '</strong> is not scalar!');
                        }
                        if ($contains_strings) {
                            // Prepare string elements of array
                            // Make sure the string is a single line
                            $var_value = preg_replace('~\\r|\\n~', '', $var_value);
                            // strip out any html:
                            $globals_var[$i][$j] = utf8_trim(utf8_strip_tags($var_value));
                            continue;
                        }
                        if (isset($elements_regexp)) {
                            // Array contains elements which must match to the given regular expression
                            if (preg_match($elements_regexp, $var_value)) {
                                // OK match, set the corresponding type
                                settype($globals_var[$i][$j], $elements_type);
                            } else {
                                // No match, cannot accept this MISMATCH
                                // Note: In case of array:integer or array:regexp we always use strict typing for the array elements
                                bad_request_die(sprintf(T_('Illegal value received for parameter &laquo;%s&raquo;!'), $var));
                            }
                        }
                    }
                }
                if ($one_dimensional) {
                    // Extract real array from temp array
                    $globals_var = $globals_var[0];
                }
                // Restore current array with prepared data
                $GLOBALS[$var] = $globals_var;
                $Debuglog->add('param(-): <strong>' . $var . '</strong> as ' . $type, 'params');
                if ($GLOBALS[$var] === array() && $strict_typing === false && $use_default) {
                    // We want to consider empty values as invalid and fall back to the default value:
                    $GLOBALS[$var] = $default;
                }
                break;
            default:
                if (utf8_substr($type, 0, 1) == '/') {
                    // We want to match against a REGEXP:
                    if (!is_scalar($GLOBALS[$var])) {
                        // This happens if someone uses "foo[]=x" where "foo" is expected as string
                        debug_die('param(-): <strong>' . $var . '</strong> is not scalar!');
                    } elseif (preg_match($type, $GLOBALS[$var])) {
                        // Okay, match
                        if (isset($Debuglog)) {
                            $Debuglog->add('param(-): <strong>' . $var . '</strong> matched against ' . $type, 'params');
                        }
                    } elseif ($strict_typing == 'allow_empty' && empty($GLOBALS[$var])) {
                        // No match but we accept empty value:
                        if (isset($Debuglog)) {
                            $Debuglog->add('param(-): <strong>' . $var . '</strong> is empty: ok', 'params');
                        }
                    } elseif ($strict_typing) {
                        // We cannot accept this MISMATCH:
                        bad_request_die(sprintf(T_('Illegal value received for parameter &laquo;%s&raquo;!'), $var));
                    } else {
                        // Fall back to default:
                        $GLOBALS[$var] = $default;
                        if (isset($Debuglog)) {
                            $Debuglog->add('param(-): <strong>' . $var . '</strong> DID NOT match ' . $type . ' set to default value=' . $GLOBALS[$var], 'params');
                        }
                    }
                    // From now on, consider this as a string: (we need this when memorizing)
                    $type = 'string';
                } elseif ($GLOBALS[$var] === '') {
                    // Special handling of empty values.
                    if ($strict_typing === false && $use_default) {
                        // ADDED BY FP 2006-07-06
                        // We want to consider empty values as invalid and fall back to the default value:
                        $GLOBALS[$var] = $default;
                    } else {
                        // We memorize the empty value as NULL:
                        // fplanque> note: there might be side effects to this, but we need
                        // this to distinguish between 0 and 'no input'
                        // Note: we do this after regexps because we may or may not want to allow empty strings in regexps
                        $GLOBALS[$var] = NULL;
                        if (isset($Debuglog)) {
                            $Debuglog->add('param(-): <strong>' . $var . '</strong> set to NULL', 'params');
                        }
                    }
                } else {
                    if ($strict_typing) {
                        // We want to make sure the value is valid:
                        $regexp = '';
                        switch ($type) {
                            case 'boolean':
                                $regexp = '/^(0|1|false|true)$/i';
                                break;
                            case 'integer':
                                $regexp = '/^(\\+|-)?[0-9]+$/';
                                break;
                            case 'float':
                            case 'double':
                                $regexp = '/^(\\+|-)?[0-9]+(.[0-9]+)?$/';
                                break;
                            default:
                                // Note: other types are not tested and they are not allowed without testing.
                                debug_die('Invalid parameter type!');
                        }
                        if ($strict_typing == 'allow_empty' && empty($GLOBALS[$var])) {
                            // We have an empty value and we accept it
                            // ok..
                        } elseif (!empty($regexp)) {
                            if ($type == 'boolean' && strtolower($GLOBALS[$var]) == 'false') {
                                // 'false' string must be interpreted as boolean false value
                                $GLOBALS[$var] = false;
                            } elseif (!is_scalar($GLOBALS[$var]) || !preg_match($regexp, $GLOBALS[$var])) {
                                // Value of scalar var does not match!
                                bad_request_die(sprintf(T_('Illegal value received for parameter &laquo;%s&raquo;!'), $var));
                            }
                        }
                    }
                    // Change the variable type:
                    settype($GLOBALS[$var], $type);
                    if (isset($Debuglog)) {
                        $Debuglog->add('param(-): <strong>' . var_export($var, true) . '</strong> typed to ' . $type . ', new value=' . var_export($GLOBALS[$var], true), 'params');
                    }
                }
        }
    }
    /*
     * STEP 3: memorize the value for later url regeneration
     */
    if ($memorize) {
        // Memorize this parameter
        memorize_param($var, $type, $default);
    }
    // echo $var, '(', gettype($GLOBALS[$var]), ')=', $GLOBALS[$var], '<br />';
    return $GLOBALS[$var];
}
Example #14
0
/**
 * A helper function to conditionally convert a string from current charset to UTF-8
 *
 * @param string
 * @return string
 */
function current_charset_to_utf8(&$a)
{
    global $current_charset;
    if (is_string($a) && $current_charset != '' && $current_charset != 'utf-8') {
        // Convert string to utf-8 if it has another charset
        $a = convert_charset($a, 'utf-8', $current_charset);
    }
    return $a;
}
Example #15
0
for ($i=0; $i<count($filter); $i++)
{
	$str = $filter[$i];

	// 제목 필터링 (찾으면 중지)
	$subj = "";
	$pos = strpos($subject, $str);
	if ($pos !== false)
	{
		if (strtolower($g4[charset]) == 'euc-kr')
		$subj = convert_charset('utf-8', 'cp949', $str);//cp949 로 변환해서 반환
		else
		$subj = $str;
		break;
	}

	// 내용 필터링 (찾으면 중지)
	$cont = "";
	$pos = strpos($content, $str);
	if ($pos !== false)
	{
		if (strtolower($g4[charset]) == 'euc-kr')
		$cont = convert_charset('utf-8', 'cp949', $str);//cp949 로 변환해서 반환
		else
		$cont = $str;
		break;
	}
}

die("{\"subject\":\"$subj\",\"content\":\"$cont\"}");
?>
Example #16
0
/**
 * Convert special chars (like german umlauts) to ASCII characters.
 *
 * @param string Input string to operate on
 * @param NULL|string The post locale or NULL if there is no specific locale.
 *                    Gets passed to evo_iconv_transliterate().
 * @return string The input string with replaced chars.
 */
function replace_special_chars($str, $post_locale = NULL)
{
    global $evo_charset, $default_locale, $current_locale, $locales;
    // Decode entities to be able to transliterate the associated chars:
    // Tblue> TODO: Check if this could have side effects.
    $str = html_entity_decode($str, ENT_NOQUOTES, $evo_charset);
    $our_locale = $post_locale;
    if ($our_locale === NULL) {
        // post locale is not set, try to guess current locale
        if (!empty($default_locale)) {
            $our_locale = $default_locale;
        }
        if (!empty($current_locale)) {
            // Override with current locale if available
            $our_locale = $current_locale;
        }
    }
    if ($our_locale !== NULL && isset($locales[$our_locale]) && !empty($locales[$our_locale]['transliteration_map'])) {
        // Use locale 'transliteration_map' if present
        if (!array_key_exists('', $locales[$our_locale]['transliteration_map'])) {
            // Make sure there's no empty string key, otherwise strtr() returns false
            if ($tmp_str = strtr($str, $locales[$our_locale]['transliteration_map'])) {
            }
            // Use newly transliterated string
            $str = $tmp_str;
        }
    }
    if (($newstr = evo_iconv_transliterate($str, $post_locale)) !== false) {
        // iconv allows us to get nice URL titles by transliterating non-ASCII chars.
        // Tblue> htmlentities() does not know anything about ASCII?! ISO-8859-1 will work too, though.
        $newstr_charset = 'ISO-8859-1';
    } else {
        if (can_convert_charsets('UTF-8', $evo_charset) && can_convert_charsets('UTF-8', 'ISO-8859-1')) {
            // Fallback to the limited old method: Transliterate only a few known chars.
            $newstr = convert_charset($str, 'UTF-8', $evo_charset);
            $newstr_charset = 'UTF-8';
            $search = array('Ä', 'ä', 'Ö', 'ö', 'Ü', 'ü', 'ß', 'à', 'ç', 'è', 'é', 'ì', 'ò', 'ô', 'ù');
            // iso-8859-1
            $replace = array('Ae', 'ae', 'Oe', 'oe', 'Ue', 'ue', 'ss', 'a', 'c', 'e', 'e', 'i', 'o', 'o', 'u');
            foreach ($search as $k => $v) {
                // convert $search to UTF-8
                $search[$k] = convert_charset($v, 'UTF-8', 'ISO-8859-1');
            }
            $newstr = str_replace($search, $replace, $newstr);
        } else {
            // Replace HTML entities only.
            $newstr = $str;
            $newstr_charset = $evo_charset;
        }
    }
    // Replace HTML entities
    $newstr = htmlentities($newstr, ENT_NOQUOTES, $newstr_charset);
    // Handle special entities (e.g., use "-" instead of "a" for "&"):
    $newstr = str_replace(array('&amp;', '&laquo;', '&raquo;'), '-', $newstr);
    // Keep only one char in entities!
    $newstr = preg_replace('/&(.).+?;/', '$1', $newstr);
    // Replace non acceptable chars
    $newstr = preg_replace('/[^A-Za-z0-9_]+/', '-', $newstr);
    // Remove '-' at start and end:
    $newstr = preg_replace('/^-+/', '', $newstr);
    $newstr = preg_replace('/-+$/', '', $newstr);
    //pre_dump( $str, $newstr );
    return $newstr;
}
Example #17
0
 /**
  * Event handler: called when a user attemps to login.
  *
  * This function will check if the user exists in the LDAP directory and create it locally if it does not.
  *
  * @param array 'login', 'pass' and 'pass_md5'
  */
 function LoginAttempt(&$params)
 {
     global $localtimenow;
     global $Settings, $Hit, $evo_charset;
     // Check if LDAP is available:
     if (!function_exists('ldap_connect')) {
         $this->debug_log('This PHP installation does not support LDAP functions.');
         return false;
         // Login failed!
     }
     // Get ready to go through ALL LDAP Servers configured in the plugin:
     $search_sets = $this->Settings->get('search_sets');
     if (empty($search_sets)) {
         $this->debug_log('No LDAP servers have been configured in the LDAP plugin settings.');
         return false;
         // Login failed!
     }
     // Detect if we already have a local user with the same login:
     $UserCache =& get_Cache('UserCache');
     if ($local_User =& $UserCache->get_by_login($params['login'])) {
         $this->debug_log('User <b>' . $params['login'] . '</b> already exists locally. We will UPDATE it with the latest LDAP attibutes.');
         $update_mode = true;
         // Try to find a number of a search set which was used on successful logging previous time by current user:
         $user_search_set_num = intval($this->UserSettings->get('search_set_num', $local_User->ID));
         if ($user_search_set_num > 0 && isset($search_sets[$user_search_set_num])) {
             // We have found this, Reorder the array to use the successful set firstly:
             $success_search_set = $search_sets[$user_search_set_num];
             unset($search_sets[$user_search_set_num]);
             $search_sets = array($user_search_set_num => $success_search_set) + $search_sets;
         }
     } else {
         $update_mode = false;
     }
     $this->debug_log(sprintf('LDAP plugin will attempt to login with login=<b>%s</b> / pass=<b>%s</b> / MD5 pass=<b>%s</b>', $params['login'], $params['pass'], $params['pass_md5']));
     // ------ Loop through list of configured LDAP Servers: ------
     foreach ($search_sets as $l_id => $l_set) {
         $this->debug_log('Step 1 : STARTING LDAP AUTH WITH SERVER #' . $l_id);
         // --- CONNECT TO SERVER ---
         $server_port = explode(':', $l_set['server']);
         $server = $server_port[0];
         $port = isset($server_port[1]) ? $server_port[1] : 389;
         if (!empty($l_set['disabled'])) {
             $this->debug_log('Skipping disabled LDAP server &laquo;' . $server . ':' . $port . '&raquo;!');
             continue;
         }
         if (!($ldap_conn = @ldap_connect($server, $port))) {
             $this->debug_log('Could not connect to LDAP server &laquo;' . $server . ':' . $port . '&raquo;!');
             continue;
         }
         $this->debug_log('Connected to server &laquo;' . $server . ':' . $port . '&raquo;..');
         $ldap_rdn = str_replace('%s', $params['login'], $l_set['rdn']);
         $this->debug_log('Using RDN &laquo;' . $ldap_rdn . '&raquo; for binding...');
         // --- SET PROTOCOL VERSION ---
         // Get protocol version to use:
         if (!ldap_get_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, $initial_protocol_version)) {
             $this->debug_log('Failed to get LDAP_OPT_PROTOCOL_VERSION.');
             $initial_protocol_version = null;
         }
         $protocol_version = isset($l_set['protocol_version']) ? $l_set['protocol_version'] : 'auto';
         // new setting in 2.01
         if ($protocol_version[0] == 'v') {
             // transform "vX" => "X"
             $try_versions = array(substr($protocol_version, 1));
         } else {
             // "auto"
             $try_versions = array(3, 2);
             if (isset($initial_protocol_version)) {
                 array_unshift($try_versions, $initial_protocol_version);
             }
             $try_versions = array_unique($try_versions);
         }
         $this->debug_log('We will try protocol versions: ' . implode(', ', $try_versions));
         // --- VERIFY USER CREDENTIALS BY BINDING TO SERVER ---
         // you might use this for testing with Apache DS: if( !@ldap_bind($ldap_conn, 'uid=admin,ou=system', 'secret') )
         // Bind:
         $bound = false;
         $bind_errors = array();
         foreach ($try_versions as $try_version) {
             $this->debug_log(sprintf('Trying to connect with protocol version: %s / RDN: %s / pass: %s', $try_version, $ldap_rdn, $params['pass']));
             ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, $try_version);
             if (@ldap_bind($ldap_conn, $ldap_rdn, $params['pass'])) {
                 // Success
                 $this->debug_log('Binding worked.');
                 $bound = true;
                 break;
             } else {
                 $this->debug_log('Binding failed. Errno: ' . ldap_errno($ldap_conn) . ' Error: ' . ldap_error($ldap_conn));
             }
         }
         if (!$bound) {
             if (isset($initial_protocol_version)) {
                 // Reset this for the next search set:
                 ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, $initial_protocol_version);
             }
             continue;
         }
         $this->debug_log('User successfully bound to server.');
         // --- STEP 2 : TRY TO OBTAIN MORE INFO ABOUT USER ---
         // Search user info
         $filter = str_replace('%s', $params['login'], $l_set['search_filter']);
         $this->debug_log(sprintf('Step 2 : Now querying for additional user info. base_dn: <b>%s</b>, filter: <b>%s</b>', $l_set['base_dn'], $filter));
         $search_result = @ldap_search($ldap_conn, $l_set['base_dn'], $filter);
         if (!$search_result) {
             // this may happen with an empty base_dn
             $this->debug_log('Invalid ldap_search result. Skipping to next search set. Errno: ' . ldap_errno($ldap_conn) . ' Error: ' . ldap_error($ldap_conn));
             continue;
         }
         $search_info = ldap_get_entries($ldap_conn, $search_result);
         //$this->debug_log( 'Results returned by LDAP Server: <pre>'.var_export( $search_info, true ).'</pre>' );
         if ($search_info['count'] != 1) {
             // We have found 0 or more than 1 users, which is a problem...
             $this->debug_log('# of entries found with search: ' . $search_info['count'] . ' - Skipping...');
             /*
             for ($i=0; $i<$search_info["count"]; $i++) {
             	echo "dn: ". $search_info[$i]["dn"] ."<br>";
             	echo "first cn entry: ". $search_info[$i]["cn"][0] ."<br>";
             	echo "first email entry: ". $search_info[$i]["mail"][0] ."<p>";
             }
             */
             continue;
         }
         $this->debug_log('User info has been found.');
         // --- CREATE OR UPDATE USER ACCOUNT IN B2EVO ---
         if ($update_mode == false) {
             $this->debug_log('Step 3 : Creating a local user in b2evolution...');
             $local_User = new User();
             $local_User->set('login', $params['login']);
             $local_User->set('locale', locale_from_httpaccept());
             // use the browser's locale
             $local_User->set_datecreated($localtimenow);
             // $local_User->set( 'level', 1 );
         } else {
             // User exists already exists
             $this->debug_log('Step 3 : Updating the existing local user.');
         }
         $this->debug_log('Randomize password in b2evolution DB and autoactivate user.');
         // Generate a random password (we never want LDAP users to be able to login without a prior LDAP check) (also on update, just in case...
         $local_User->set_password(generate_random_passwd(32));
         // $params['pass'] );
         $local_User->set('status', 'autoactivated');
         // Activate the user automatically (no email activation necessary)
         // Convert each input string to current server encoding:
         $exclude_encoding_fields = array('uid', 'mail', 'jpegphoto');
         if (isset($search_info[0]) && is_array($search_info[0])) {
             foreach ($search_info[0] as $search_info_key => $search_info_data) {
                 if (isset($search_info_data[0]) && is_string($search_info_data[0]) && !in_array($search_info_key, $exclude_encoding_fields)) {
                     // Convert string from LDAP server encoding to current server encoding:
                     $search_info[0][$search_info_key][0] = convert_charset($search_info_data[0], $l_set['encoding'], $evo_charset);
                 }
             }
         }
         // Make some updates:
         // mail -> email:
         if (isset($search_info[0]['mail'][0])) {
             $local_User->set_email($search_info[0]['mail'][0]);
         }
         // uid -> nickname
         if (isset($search_info[0]['uid'][0])) {
             $this->debug_log('UID: <b>' . $search_info[0]['uid'][0] . '</b>');
             $local_User->set('nickname', $search_info[0]['uid'][0]);
         } else {
             // if not found, use login.
             $local_User->set('nickname', $params['login']);
         }
         // givenname -> Firstname:
         if (isset($search_info[0]['givenname'][0])) {
             $this->debug_log('First name (givenname): <b>' . $search_info[0]['givenname'][0] . '</b>');
             $local_User->set('firstname', $search_info[0]['givenname'][0]);
         }
         // sn -> Lastname:
         if (isset($search_info[0]['sn'][0])) {
             $this->debug_log('Last name (sn): <b>' . $search_info[0]['sn'][0] . '</b>');
             $local_User->set('lastname', $search_info[0]['sn'][0]);
         }
         // roomnumber -> user field "roomnumber" (if not found, autocreate it in group "Address")
         if (isset($search_info[0]['roomnumber'][0])) {
             $this->debug_log('Room number: <b>' . $search_info[0]['roomnumber'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'roomnumber', $search_info[0]['roomnumber'][0], 'Address', 'Room Number', 'word');
         }
         // businesscategory -> user field "businesscategory" (if not found, autocreate it in group "About me")
         if (isset($search_info[0]['businesscategory'][0])) {
             $this->debug_log('Business Category: <b>' . $search_info[0]['businesscategory'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'businesscategory', $search_info[0]['businesscategory'][0], 'About me', 'Business Category', 'text');
         }
         // telephonenumber -> user field "officephone" (if not found, autocreate it in group "Phone")
         if (isset($search_info[0]['telephonenumber'][0])) {
             $this->debug_log('Office phone: <b>' . $search_info[0]['telephonenumber'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'officephone', $search_info[0]['telephonenumber'][0], 'Phone', 'Office phone', 'phone');
         }
         // mobile -> user field "cellphone" (if not found, autocreate it in group "Phone")
         if (isset($search_info[0]['mobile'][0])) {
             $this->debug_log('Cell phone: <b>' . $search_info[0]['mobile'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'cellphone', $search_info[0]['mobile'][0], 'Phone', 'Cell phone', 'phone');
         }
         // employeenumber -> user field "employeenumber" (if not found, autocreate it in group "About me")
         if (isset($search_info[0]['employeenumber'][0])) {
             $this->debug_log('Employee number: <b>' . $search_info[0]['employeenumber'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'employeenumber', $search_info[0]['employeenumber'][0], 'About me', 'Employee number', 'word');
         }
         // title -> user field "title" (if not found, autocreate it in group "About me")
         if (isset($search_info[0]['title'][0])) {
             $this->debug_log('Title: <b>' . $search_info[0]['title'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'title', $search_info[0]['title'][0], 'About me', 'Title', 'word');
             $userfield_title = $search_info[0]['title'][0];
             // Use this as role for all organizations below
         } else {
             $userfield_title = '';
         }
         // departmentnumber -> join Organization with the same name (create if doesn't exist)
         if (isset($search_info[0]['departmentnumber'][0])) {
             $this->debug_log('Department Number: <b>' . $search_info[0]['departmentnumber'][0] . '</b>');
             $this->userorg_update_by_name($local_User, $search_info[0]['departmentnumber'][0], $userfield_title);
         }
         // o -> join Organization with the same name (create if doesn't exist)
         if (isset($search_info[0]['o'][0])) {
             $this->debug_log('Organization: <b>' . $search_info[0]['o'][0] . '</b>');
             $this->userorg_update_by_name($local_User, $search_info[0]['o'][0], $userfield_title);
         }
         // telexnumber -> user field "officefax" (if not found, autocreate it in group "Phone")
         if (isset($search_info[0]['telexnumber'][0])) {
             $this->debug_log('Office FAX: <b>' . $search_info[0]['telexnumber'][0] . '</b>');
             $this->userfield_update_by_code($local_User, 'officefax', $search_info[0]['telexnumber'][0], 'Phone', 'Office FAX', 'phone');
         }
         // ---- GROUP STUFF ----
         if ($update_mode == true) {
             // Updating existing user
             $this->debug_log('Updating existing user: we do NOT touch the primary group.');
             $local_User->dbupdate();
             $this->debug_log('OK -- User has been updated.');
         } else {
             // Try to assign prilary group from the search results:
             $assigned_group = false;
             if (!empty($l_set['assign_user_to_group_by'])) {
                 $this->debug_log('Plugin is configured to assign the Primary Group by the ' . $l_set['assign_user_to_group_by'] . ' key...');
                 if (isset($search_info[0][$l_set['assign_user_to_group_by']]) && isset($search_info[0][$l_set['assign_user_to_group_by']][0])) {
                     // There is info we want to assign by
                     $assign_by_value = $search_info[0][$l_set['assign_user_to_group_by']][0];
                     $this->debug_log('User info says has ' . $l_set['assign_user_to_group_by'] . ' = "<b>' . $assign_by_value . '</b>"');
                     $GroupCache =& get_Cache('GroupCache');
                     if ($users_Group =& $GroupCache->get_by_name($assign_by_value, false)) {
                         // A group with the users value returned exists.
                         $local_User->set_Group($users_Group);
                         $assigned_group = true;
                         $this->debug_log('Assigning User to existing Primary Group.');
                     } else {
                         $this->debug_log('Group with that name does not exist...');
                         if ($new_Group =& $this->usergroup_create($l_set['tpl_new_grp_ID'], $assign_by_value)) {
                             // Link the user to new created group:
                             $local_User->set_Group($new_Group);
                             $assigned_group = true;
                             $this->debug_log('Assigned User to new Primary Group.');
                         }
                     }
                 }
             }
             if (!$assigned_group) {
                 // Default group:
                 $this->debug_log('Falling back to default primary group...');
                 $users_Group = NULL;
                 $fallback_grp_ID = $this->Settings->get('fallback_grp_ID');
                 if (empty($fallback_grp_ID)) {
                     $this->debug_log('No default/fallback primary group configured.');
                     $this->debug_log('User NOT created, try next LDAP server...');
                     //Continue to next LDAP server:
                     continue;
                 } else {
                     $GroupCache =& get_Cache('GroupCache');
                     $users_Group =& $GroupCache->get_by_ID($fallback_grp_ID);
                     if ($users_Group) {
                         // either $this->default_group_name is not given or wrong
                         $local_User->set_Group($users_Group);
                         $assigned_group = true;
                         $this->debug_log('Using default/fallback primary group: <b>' . $users_Group->get('name') . '</b>');
                     } else {
                         $this->debug_log('Default/fallback primary group does not exist (' . $fallback_grp_ID . ').');
                         $this->debug_log('User NOT created, try next LDAP server...');
                         //Continue to next LDAP server:
                         continue;
                     }
                 }
             }
             $local_User->dbinsert();
             $UserCache->add($local_User);
             $this->debug_log('OK -- User has been created.');
         }
         // Remember this settings number in order use this first in next logging time by current user:
         $this->UserSettings->set('search_set_num', $l_id, $local_User->ID);
         $this->UserSettings->dbupdate();
         // Assign user to organizations:
         $this->userorg_assign_to_user($local_User);
         // jpegphoto -> Save as profile pictue "ldap.jpeg" and associate with user
         if (isset($search_info[0]['jpegphoto'][0])) {
             $this->debug_log('Photo: <img src="data:image/jpeg;base64,' . base64_encode($search_info[0]['jpegphoto'][0]) . '" />');
             // Save to disk and attach to user:
             $this->userimg_attach_photo($local_User, $search_info[0]['jpegphoto'][0], !empty($l_set['expand_pics']));
         }
         // --- EXTRA GROUPS ---
         if (!empty($l_set['secondary_grp_search_filter'])) {
             global $app_version;
             if (evo_version_compare($app_version, '6.7.0-alpha') < 0) {
                 // The plugin is used on b2evo 6.6
                 $this->debug_log('Secondary groups not handled. This feature requires b2evolution v6.7.0-alpha or newer.');
             } elseif (empty($l_set['secondary_grp_name_attribute'])) {
                 $this->debug_log('Missing name attribute for secondary groups');
             } else {
                 $filter = str_replace('%s', $params['login'], $l_set['secondary_grp_search_filter']);
                 $grp_name_attribute = $l_set['secondary_grp_name_attribute'];
                 $this->debug_log(sprintf('Step 4 : Now querying for secondary groups. base_dn: <b>%s</b>, filter: <b>%s</b>, name attribue=<b>%s</b>', $l_set['secondary_grp_base_dn'], $filter, $grp_name_attribute));
                 $search_result = @ldap_search($ldap_conn, $l_set['secondary_grp_base_dn'], $filter, array($grp_name_attribute));
                 if (!$search_result) {
                     // this may happen with an empty base_dn
                     $this->debug_log('Invalid ldap_search result. No secondary groups will be assigned. Errno: ' . ldap_errno($ldap_conn) . ' Error: ' . ldap_error($ldap_conn));
                 } else {
                     $search_info = ldap_get_entries($ldap_conn, $search_result);
                     // $this->debug_log( 'Results returned by LDAP Server: <pre>'.var_export( $search_info, true ).'</pre>' );
                     $secondary_groups = array();
                     // $this->debug_log( 'Secondary groups name prefix: <pre>'.var_export( $l_set['secondary_grp_name_prefix'], true ).'</pre>' );
                     // Walk through results:
                     foreach ($search_info as $group_candidate) {
                         if (is_array($group_candidate) && isset($group_candidate[$grp_name_attribute][0])) {
                             $group_candidate_cn = $group_candidate[$grp_name_attribute][0];
                             if (empty($l_set['secondary_grp_name_prefix']) || strpos($group_candidate_cn, $l_set['secondary_grp_name_prefix']) === 0) {
                                 // prefix is ok
                                 $this->debug_log('Accepted Secondary Group: ' . $group_candidate_cn);
                                 $secondary_groups[] = $group_candidate_cn;
                             } else {
                                 // prefix is NOT ok
                                 $this->debug_log('REJECTED Secondary Group: ' . $group_candidate_cn);
                             }
                         }
                     }
                     // Hardcode two secondary groups:
                     // $secondary_groups = array( 'Blog B members', 'Blog D Members' );
                     $this->debug_log('Secondary groups to be assigned: <pre>' . var_export($secondary_groups, true) . '</pre>');
                     // Update secondary groups for the User:
                     $this->usersecgroup_update($local_User, $secondary_groups, $l_set['tpl_new_secondary_grp_ID']);
                 }
             }
         }
         if (isset($initial_protocol_version)) {
             ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, $initial_protocol_version);
         }
         // --- CONSIDER THE LOGIN ATTEMPT TO BE SUCCESSFUL AND WE ACCEPT IT ---
         // Update this value which has been passed by REFERENCE:
         $params['pass_ok'] = true;
         return true;
         // Login was a success (but return "true" does not trigger anything special in b2evolution)
     }
     if (isset($initial_protocol_version)) {
         ldap_set_option($ldap_conn, LDAP_OPT_PROTOCOL_VERSION, $initial_protocol_version);
     }
     return false;
     // Login failed!
 }
Example #18
0
    $config['cf_filter'] = convert_charset('cp949', 'utf-8', $config['cf_filter']);
}
//$filter = explode(",", strtolower(trim($config['cf_filter'])));
// strtolower 에 의한 한글 변형으로 아래 코드로 대체 (곱슬최씨님이 알려 주셨습니다.)
$filter = explode(",", trim($config['cf_filter']));
for ($i = 0; $i < count($filter); $i++) {
    $str = $filter[$i];
    // 제목 필터링 (찾으면 중지)
    $subj = "";
    $pos = strpos($subject, $str);
    if ($pos !== false) {
        if (strtolower($g4[charset]) == 'euc-kr') {
            $subj = convert_charset('utf-8', 'cp949', $str);
        } else {
            $subj = $str;
        }
        break;
    }
    // 내용 필터링 (찾으면 중지)
    $cont = "";
    $pos = strpos($content, $str);
    if ($pos !== false) {
        if (strtolower($g4[charset]) == 'euc-kr') {
            $cont = convert_charset('utf-8', 'cp949', $str);
        } else {
            $cont = $str;
        }
        break;
    }
}
die("{\"subject\":\"{$subj}\",\"content\":\"{$cont}\"}");
Example #19
0
 /**
  * Translate a given string, in the Plugin's context.
  *
  * This means, that the translation is obtained from the Plugin's "locales" folder.
  * @link http://manual.b2evolution.net/Localization#Plugins
  *
  * It uses the global/regular {@link T_()} function as fallback.
  *
  * {@internal This is mainly a copy of {@link T_()}, for the $use_l10n==2 case.}}
  *
  * @param string The string (english), that should be translated
  * @param string Requested locale ({@link $current_locale} gets used by default)
  * @return string
  */
 function T_($string, $req_locale = '')
 {
     global $current_locale, $locales, $Debuglog, $plugins_path, $evo_charset;
     $trans =& $this->_trans;
     if (empty($req_locale)) {
         // By default we use the current locale
         if (empty($current_locale)) {
             // don't translate if we have no locale
             return $string;
         }
         $req_locale = $current_locale;
     }
     if (!isset($locales[$req_locale]['messages'])) {
         $this->debug_log('No messages file dirname for locale. $locales["' . $req_locale . '"] is ' . var_export(@$locales[$req_locale], true), 'locale');
         $locales[$req_locale]['messages'] = false;
     }
     $messages = $locales[$req_locale]['messages'];
     // replace special characters to msgid-equivalents
     $search = str_replace(array("\n", "\r", "\t"), array('\\n', '', '\\t'), $string);
     // echo "Translating ", $search, " to $messages<br />";
     if (!isset($trans[$messages])) {
         // Translations for current locale have not yet been loaded:
         if (!isset($this->classfile_path)) {
             // ->T_() called through the plugin's constructor, which is deprecated!
             $this->debug_log('T_() method called through plugin constructor!');
             return $string;
         }
         $locales_dir = dirname($this->classfile_path) . '/';
         if ($locales_dir == $plugins_path) {
             $locales_dir .= $this->classname . '/';
         }
         $locales_dir .= 'locales/';
         // First load the global messages file, if existing:
         if (!$this->_trans_loaded_global) {
             $this->_trans_loaded_global = true;
             $file_path = $locales_dir . '_global.php';
             if (file_exists($file_path)) {
                 if (is_readable($file_path)) {
                     // echo 'LOADING GLOBAL '.$file_path;
                     include $file_path;
                 } else {
                     $this->debug_log('Global messages file ' . $file_path . ' is not readable!', 'locale');
                 }
             }
         }
         // Then load locale specific files:
         $file_path = $locales_dir . $messages . '/_global.php';
         if (file_exists($file_path)) {
             if (is_readable($file_path)) {
                 // echo 'LOADING '.$file_path;
                 include $file_path;
             } else {
                 $this->debug_log('Messages file ' . $file_path . ' for locale ' . $req_locale . ' is not readable!', 'locale');
             }
         }
         if (!isset($trans[$messages])) {
             // Still not loaded... file doesn't exist, memorize that no translations are available
             // echo 'file not found!';
             $trans[$messages] = array();
             /*
             				May be an english locale without translation.
             				TODO: when refactoring locales, assign a key for 'original english'.
             				$Debuglog->add( 'No messages found for locale ['.$req_locale.'],
             												message file [/locales/'.$messages.'/_global.php]', 'locale' );*/
         }
         // Remember the charset:
         if (isset($trans[$messages][''])) {
             if (($pos = strpos($trans[$messages][''], 'Content-Type:')) !== false) {
                 if (preg_match('~^Content-Type:.*charset=([\\w\\d-]+)~', substr($trans[$messages][''], $pos), $match)) {
                     $this->_trans_charsets[$messages] = $match[1];
                     $this->debug_log('Charset of messages for ' . $messages . ' is ' . $match[1]);
                 }
             }
         }
         if (!isset($this->_trans_charsets[$messages])) {
             // not provided, use the one of the main locale files:
             $this->_trans_charsets[$messages] = $locales[$req_locale]['charset'];
         }
     }
     if (isset($trans[$messages][$search])) {
         // If the string has been translated:
         $r = $trans[$messages][$search];
     } else {
         // Fallback to global T_() function:
         return T_($string, $req_locale);
     }
     if (!empty($evo_charset)) {
         $r = convert_charset($r, $evo_charset, $this->_trans_charsets[$messages]);
     }
     return $r;
 }
Example #20
0
 /**
  * TRANSLATE!
  *
  * Translate a text to the desired locale or to the current locale.
  *
  * @param string String to translate, '' to get language file info (as in gettext spec)
  * @param string locale to translate to, '' to use current locale
  * @param array Array containing the following keys (all optional):
  *              - 'ext_transarray': A reference to an alternate array
  *                                  to use for the caching of the
  *                                  translated strings or NULL to use
  *                                  the internal array.
  *              - 'alt_basedir': Alternate base directory to search
  *                               for translations, e. g. a plugin or
  *                               skin directory.
  *              - 'for_helper': (boolean) Is the translation for the b2evoHelper object?
  * @return string The translated string or the original string on error.
  *
  * @internal The last parameter/its 'alt_basedir' key is used by
  *           Plugin::T_() and Skin::T_().
  */
 function T_($string, $req_locale = '', $params = array())
 {
     /**
      * The translations keyed by locale.
      *
      * This array is only used if $params['ext_transarray'] === NULL.
      *
      * @var array
      * @static
      */
     static $_trans = array();
     global $current_locale, $locales, $locales_path, $plugins_path;
     global $evo_charset, $Debuglog;
     $params = array_merge(array('ext_transarray' => NULL, 'alt_basedir' => '', 'for_helper' => false), $params);
     if (empty($req_locale)) {
         // By default we use the current locale
         if (empty($current_locale)) {
             // don't translate if we have no locale
             return $string;
         }
         $req_locale = $current_locale;
     }
     if (!isset($locales[$req_locale]['messages'])) {
         $Debuglog->add('No messages file path for locale. $locales["' . $req_locale . '"] is ' . var_export(@$locales[$req_locale], true), 'locale');
         if (!empty($evo_charset)) {
             $string = convert_charset($string, $evo_charset, 'iso-8859-1');
         }
         return $string;
     }
     $messages = $locales[$req_locale]['messages'];
     if (is_null($params['ext_transarray'])) {
         // use our array
         //$Debuglog->add( 'Using internal array', 'locale' );
         $trans =& $_trans;
     } else {
         // use external array:
         //$Debuglog->add( 'Using external array', 'locale' );
         $trans =& $params['ext_transarray'];
     }
     if (!isset($trans[$messages])) {
         // Translations for current locale have not yet been loaded:
         $Debuglog->add('We need to load a new translation file to translate: "' . $string . '"', 'locale');
         if ($params['alt_basedir'] != '') {
             // Load the translation file from the alternative base dir:
             //$Debuglog->add( 'Using alternative basedir ['.$params['alt_basedir'].']', 'locale' );
             $path = $params['alt_basedir'] . '/locales/' . $messages . '/_global.php';
         } else {
             // Load our global translation file.
             $path = $locales_path . $messages . '/_global.php';
         }
         if (file_exists($path) && is_readable($path)) {
             $Debuglog->add('T_: Loading file: ' . $path, 'locale');
             include_once $path;
         } else {
             $Debuglog->add('T_: Messages file does not exist or is not readable: ' . $path, 'locale');
         }
         if (!isset($trans[$messages])) {
             // Still not loaded... file doesn't exist, memorize that no translations are available
             // echo 'file not found!';
             $trans[$messages] = array();
         } else {
             if (!isset($trans[$messages]['__meta__'])) {
                 // Unknown/old messages format (< version 1):
                 $Debuglog->add('Found deprecated messages format (no __meta__ info).', 'locale');
                 // Translate keys (e.g. 'foo\nbar') to real strings ("foo\nbar")
                 // Doing this here for all strings, is actually faster than doing it on key lookup (like it has been done before always)
                 foreach ($trans[$messages] as $k => $v) {
                     if (($pos = strpos($k, '\\')) === false) {
                         // fast-path-skip
                         continue;
                     }
                     // Replace string as done in the good old days:
                     $new_k = str_replace(array('\\n', '\\r', '\\t'), array("\n", "\r", "\t"), $k);
                     if ($new_k != $k) {
                         $trans[$messages][$new_k] = $v;
                         unset($trans[$messages][$k]);
                     }
                 }
             }
         }
     }
     // sam2kb> b2evolution creates _global.php files with "\n" line breaks, and we must normalize newlines
     // in supplied string before trying to translate it. Otherwise strings won't match.
     // fp> TODO: this is not really satisfying in the long term. We need our own
     // parser that will extract T_() TS_() NT_() etc string and create a normalized potfile.
     // Actually it sgould create several potfiles. One for general use, one for admin, one for install, etc.
     // That way translators can concentrate on the most essential stuff first.
     $search_string = str_replace(array("\r\n", "\r"), "\n", $string);
     if (isset($trans[$messages][$search_string])) {
         // If the string has been translated:
         //$Debuglog->add( 'String ['.$string.'] found', 'locale' );
         $r = $trans[$messages][$search_string];
         if (isset($trans[$messages]['__meta__']['charset'])) {
             // new format: charset in meta data:
             $messages_charset = $trans[$messages]['__meta__']['charset'];
         } else {
             // old format.. extract charset from content type or fall back to setting from global locale definition:
             $meta = $trans[$messages][''];
             if (preg_match('~^Content-Type: text/plain; charset=(.*);?$~m', $meta, $match)) {
                 $messages_charset = $match[1];
             } else {
                 $messages_charset = $locales[$req_locale]['charset'];
             }
             // Set it accordingly to new format.
             $trans[$messages]['__meta__']['charset'] = $messages_charset;
         }
     } else {
         //$Debuglog->add( 'String ['.$string.'] not found', 'locale' );
         // Return the English string:
         $r = $string;
         // $messages_charset = 'iso-8859-1'; // our .php file encoding
         // fp> I am changing the above for the User custom field group labels (in theroy the php files are plain ASCII anyways!!)
         $messages_charset = $evo_charset;
     }
     if (!empty($evo_charset)) {
         $r = convert_charset($r, $evo_charset, $messages_charset);
     } else {
         $Debuglog->add(sprintf('Warning: evo_charset not set to translate "%s"', htmlspecialchars($string)), 'locale');
     }
     if ($params['for_helper']) {
         // translation is for the b2evoHelper object
         add_js_translation($string, $r);
     }
     //$Debuglog->add( 'Result: ['.$r.']', 'locale' );
     return $r;
 }
 /**
  * Tests {@link test_convert_charset()}.
  */
 function test_convert_charset()
 {
     $this->assertEqual(convert_charset('йкил', 'utf-8', 'latin1'), 'éêèë');
     $this->assertEqual(convert_charset('éêèë', 'latin1', 'utf-8'), 'йкил');
     $this->assertEqual(convert_charset('éêèë', 'Latin1', 'UTF-8'), 'йкил');
     $this->assertEqual(convert_charset('éêèë', 'Latin1', 'Utf8'), 'йкил');
     // THIS ONE will produce NO conversion because 'latin-1' is not a valid charset name for this func
     $this->assertEqual(convert_charset('йкил', 'utf-8', 'latin-1'), 'йкил');
 }
/**
 * return a cleaned IPTC value.
 *
 * @param string $value
 * @return string
 */
function clean_iptc_value($value)
{
    // strip leading zeros (weird Kodak Scanner software)
    while (isset($value[0]) and $value[0] == chr(0)) {
        $value = substr($value, 1);
    }
    // remove binary nulls
    $value = str_replace(chr(0x0), ' ', $value);
    if (preg_match('/[\\x80-\\xff]/', $value)) {
        // apparently mac uses some MacRoman crap encoding. I don't know
        // how to detect it so a plugin should do the trick.
        $value = trigger_change('clean_iptc_value', $value);
        if (($qual = qualify_utf8($value)) != 0) {
            // has non ascii chars
            if ($qual > 0) {
                $input_encoding = 'utf-8';
            } else {
                $input_encoding = 'iso-8859-1';
                if (function_exists('iconv') or function_exists('mb_convert_encoding')) {
                    // using windows-1252 because it supports additional characters
                    // such as "oe" in a single character (ligature). About the
                    // difference between Windows-1252 and ISO-8859-1: the characters
                    // 0x80-0x9F will not convert correctly. But these are control
                    // characters which are almost never used.
                    $input_encoding = 'windows-1252';
                }
            }
            $value = convert_charset($value, $input_encoding, get_pwg_charset());
        }
    }
    return $value;
}
 /**
  * Check the content of a given URL (referer), if the requested URI (with different hostname variations)
  * is present.
  *
  * @todo Use DB cache to avoid checking the same page again and again! (Plugin DB table)
  *
  * @param string
  * @param string URI to append to matching pattern for hostnames
  * @return boolean
  */
 function is_referer_linking_us($referer, $uri)
 {
     global $misc_inc_path, $lib_subdir, $ReqHost;
     if (empty($referer)) {
         return false;
     }
     // Load page content (max. 500kb), using fsockopen:
     $url_parsed = @parse_url($referer);
     if (!$url_parsed) {
         return false;
     }
     if (empty($url_parsed['scheme'])) {
         $url_parsed = parse_url('http://' . $referer);
     }
     $host = $url_parsed['host'];
     $port = empty($url_parsed['port']) ? 80 : $url_parsed['port'];
     $path = empty($url_parsed['path']) ? '/' : $url_parsed['path'];
     if (!empty($url_parsed['query'])) {
         $path .= '?' . $url_parsed['query'];
     }
     $fp = @fsockopen($host, $port, $errno, $errstr, 30);
     if (!$fp) {
         // could not access referring page
         $this->debug_log('is_referer_linking_us(): could not access &laquo;' . $referer . '&raquo; (host: ' . $host . '): ' . $errstr . ' (#' . $errno . ')');
         return false;
     }
     // Set timeout for data:
     if (function_exists('stream_set_timeout')) {
         stream_set_timeout($fp, 20);
     } else {
         socket_set_timeout($fp, 20);
     }
     // PHP 4
     // Send request:
     $out = "GET {$path} HTTP/1.0\r\n";
     $out .= "Host: {$host}:{$port}\r\n";
     $out .= "Connection: Close\r\n\r\n";
     fwrite($fp, $out);
     // Skip headers:
     $i = 0;
     $source_charset = 'iso-8859-1';
     // default
     while (($s = fgets($fp, 4096)) !== false) {
         $i++;
         if ($s == "\r\n" || $i > 100) {
             break;
         }
         if (preg_match('~^Content-Type:.*?charset=([\\w-]+)~i', $s, $match)) {
             $source_charset = $match[1];
         }
     }
     // Get the refering page's content
     $content_ref_page = '';
     $bytes_read = 0;
     while (($s = fgets($fp, 4096)) !== false) {
         $content_ref_page .= $s;
         $bytes_read += strlen($s);
         if ($bytes_read > 512000) {
             // do not pull more than 500kb of data!
             break;
         }
     }
     fclose($fp);
     if (!strlen($content_ref_page)) {
         $this->debug_log('is_referer_linking_us(): empty $content_ref_page (' . bytesreadable($bytes_read) . ' read)');
         return false;
     }
     $have_idn_name = false;
     // Build the search pattern:
     // We match for basically for 'href="[SERVER][URI]', where [SERVER] is a list of possible hosts (especially IDNA)
     $search_pattern = '~\\shref=["\']?https?://(';
     $possible_hosts = array($_SERVER['HTTP_HOST']);
     if ($_SERVER['SERVER_NAME'] != $_SERVER['HTTP_HOST']) {
         $possible_hosts[] = $_SERVER['SERVER_NAME'];
     }
     $search_pattern_hosts = array();
     foreach ($possible_hosts as $l_host) {
         if (preg_match('~^([^.]+\\.)(.*?)([^.]+\\.[^.]+)$~', $l_host, $match)) {
             // we have subdomains in this hostname
             if (stristr($match[1], 'www')) {
                 // search also for hostname without 'www.'
                 $search_pattern_hosts[] = $match[2] . $match[3];
             }
         }
         $search_pattern_hosts[] = $l_host;
     }
     $search_pattern_hosts = array_unique($search_pattern_hosts);
     foreach ($search_pattern_hosts as $l_host) {
         // add IDN, because this could be linked:
         $l_idn_host = idna_decode($l_host);
         // the decoded puny-code ("xn--..") name (utf8)
         if ($l_idn_host != $l_host) {
             $have_idn_name = true;
             $search_pattern_hosts[] = $l_idn_host;
         }
     }
     // add hosts to pattern, preg_quoted
     for ($i = 0, $n = count($search_pattern_hosts); $i < $n; $i++) {
         $search_pattern_hosts[$i] = preg_quote($search_pattern_hosts[$i], '~');
     }
     $search_pattern .= implode('|', $search_pattern_hosts) . ')';
     if (empty($uri)) {
         // host(s) should end with "/", "'", '"', "?" or whitespace
         $search_pattern .= '[/"\'\\s?]';
     } else {
         $search_pattern .= preg_quote($uri, '~');
         // URI should end with "'", '"' or whitespace
         $search_pattern .= '["\'\\s]';
     }
     $search_pattern .= '~i';
     if ($have_idn_name) {
         // Convert charset to UTF-8, because the decoded domain name is UTF-8, too:
         if (can_convert_charsets('utf-8', $source_charset)) {
             $content_ref_page = convert_charset($content_ref_page, 'utf-8', $source_charset);
         } else {
             $this->debug_log('is_referer_linking_us(): warning: cannot convert charset of referring page');
         }
     }
     if (preg_match($search_pattern, $content_ref_page)) {
         $this->debug_log('is_referer_linking_us(): found current URL in page (' . bytesreadable($bytes_read) . ' read)');
         return true;
     } else {
         if (strpos($referer, $ReqHost) === 0 && !empty($uri)) {
             // Referer is the same host.. just search for $uri
             if (strpos($content_ref_page, $uri) !== false) {
                 $this->debug_log('is_referer_linking_us(): found current URI in page (' . bytesreadable($bytes_read) . ' read)');
                 return true;
             }
         }
         $this->debug_log('is_referer_linking_us(): ' . sprintf('did not find &laquo;%s&raquo; in &laquo;%s&raquo; (%s bytes read).', $search_pattern, $referer, bytesreadable($bytes_read)));
         return false;
     }
 }
Example #24
0
 /**
  * Extracts a keyword from a raw not encoded URL.
  * Will only extract keyword if a known search engine has been detected.
  * Returns the keyword:
  * - in UTF8: automatically converted from other charsets when applicable
  * - strtolowered: "QUErY test!" will return "query test!"
  * - trimmed: extra spaces before and after are removed
  *
  * A list of supported search engines can be found in /inc/sessions/model/_search_engines.php
  * The function returns false when a keyword couldn't be found.
  * 	 eg. if the url is "http://www.google.com/partners.html" this will return false,
  *       as the google keyword parameter couldn't be found.
  *
  * @param string URL referer
  * @return array|false false if a keyword couldn't be extracted,
  * 						or array(
  * 							'engine_name' => 'Google',
  * 							'keywords' => 'my searched keywords',
  *							'serprank' => 4)
  */
 function extract_params_from_referer($ref)
 {
     global $Debuglog, $search_engine_params, $evo_charset, $current_charset;
     // Make sure we don't try params extraction twice
     $this->_search_params_tried = true;
     @(list($ref_host, $ref_path, $query, $fragment) = $this->is_search_referer($ref, true));
     if (empty($ref_host)) {
         // Not a search referer
         return false;
     }
     $search_engine_name = $search_engine_params[$ref_host][0];
     $keyword_param = NULL;
     if (!empty($search_engine_params[$ref_host][1])) {
         $keyword_param = $search_engine_params[$ref_host][1];
     }
     if (is_null($keyword_param)) {
         // Get settings from first item in group
         $search_engine_names = $this->get_search_engine_names();
         $url = $search_engine_names[$search_engine_name];
         $keyword_param = $search_engine_params[$url][1];
     }
     if (!is_array($keyword_param)) {
         $keyword_param = array($keyword_param);
     }
     if ($search_engine_name == 'Google Images' || $search_engine_name == 'Google' && strpos($ref, '/imgres') !== false) {
         // Google image search
         $search_engine_name = 'Google Images';
         $query = urldecode(trim($this->get_param_from_string($query, 'prev')));
         $query = str_replace('&', '&amp;', strstr($query, '?'));
     } elseif ($search_engine_name == 'Google' && (strpos($query, '&as_') !== false || strpos($query, 'as_') === 0)) {
         // Google with "as_" param
         $keys = array();
         if ($key = $this->get_param_from_string($query, 'as_q')) {
             array_push($keys, $key);
         }
         if ($key = $this->get_param_from_string($query, 'as_oq')) {
             array_push($keys, str_replace('+', ' OR ', $key));
         }
         if ($key = $this->get_param_from_string($query, 'as_epq')) {
             array_push($keys, "\"{$key}\"");
         }
         if ($key = $this->get_param_from_string($query, 'as_eq')) {
             array_push($keys, "-{$key}");
         }
         $key = trim(urldecode(implode(' ', $keys)));
     }
     if (empty($key)) {
         // we haven't extracted a search key with the special cases above...
         foreach ($keyword_param as $param) {
             if ($param[0] == '/') {
                 // regular expression match
                 if (@preg_match($param, $ref, $matches)) {
                     $key = trim(urldecode($matches[1]));
                     break;
                 }
             } else {
                 // search for keywords now &vname=keyword
                 if ($key = $this->get_param_from_string($query, $param)) {
                     $key = trim(urldecode($key));
                     if (!empty($key)) {
                         break;
                     }
                 }
             }
         }
     }
     $key_param_in_query = false;
     if (empty($key) && !empty($keyword_param)) {
         // Check if empty key param exists in query, e.g. "/search?q=&other_param=text"
         foreach ($keyword_param as $k_param) {
             if (strpos($query, '&' . $k_param . '=') !== false || strpos($query, $k_param . '=') === 0) {
                 // Key param with empty value exists in query, We can decide this referer url as from search engine
                 $key_param_in_query = true;
             }
         }
     }
     if (empty($key) && !$key_param_in_query) {
         // Not a search referer
         if ($this->referer_type == 'search') {
             // If the referer was detected as 'search' we need to change it to 'special'
             // to keep search stats clean.
             $this->referer_type = 'special';
             $Debuglog->add('Hit: extract_params_from_referer() overrides referer type set by detect_referer(): "search" -> "special"', 'request');
         }
         return false;
     }
     // Convert encoding
     if (!empty($search_engine_params[$ref_host][3])) {
         $ie = $search_engine_params[$ref_host][3];
     } elseif (isset($url) && !empty($search_engine_params[$url][3])) {
         $ie = $search_engine_params[$url][3];
     } else {
         // Fallback to default encoding
         $ie = array('utf-8', 'iso-8859-15');
     }
     if (is_array($ie)) {
         if (can_check_encoding()) {
             foreach ($ie as $test_encoding) {
                 if (check_encoding($key, $test_encoding)) {
                     $ie = $test_encoding;
                     break;
                 }
             }
         } else {
             $ie = $ie[0];
         }
     }
     $key = convert_charset($key, $evo_charset, $ie);
     // convert to lower string but keep in evo_charset
     $saved_charset = $current_charset;
     $current_charset = $evo_charset;
     $key = utf8_strtolower($key);
     $current_charset = $saved_charset;
     // Extract the "serp rank"
     // Typically http://google.com?s=keyphraz&start=18 returns 18
     if (!empty($search_engine_params[$ref_host][4])) {
         $serp_param = $search_engine_params[$ref_host][4];
     } elseif (isset($url) && !empty($search_engine_params[$url][4])) {
         $serp_param = $search_engine_params[$url][4];
     } else {
         // Fallback to default params
         $serp_param = array('offset', 'page', 'start');
     }
     if (!is_array($serp_param)) {
         $serp_param = array($serp_param);
     }
     if (strpos($search_engine_name, 'Google') !== false) {
         // Append fragment which Google uses in instant search
         $query .= '&' . $fragment;
     }
     foreach ($serp_param as $param) {
         if ($var = $this->get_param_from_string($query, $param)) {
             if (ctype_digit($var)) {
                 $serprank = $var;
                 break;
             }
         }
     }
     $this->_search_engine = $search_engine_name;
     $this->_keyphrase = $key;
     $this->_serprank = isset($serprank) ? $serprank : NULL;
     return array('engine_name' => $this->_search_engine, 'keyphrase' => $this->_keyphrase, 'serprank' => $this->_serprank);
 }
 /**
  * Test {@link bpost_count_words()}.
  */
 function test_bpost_count_words()
 {
     global $evo_charset;
     if (!can_convert_charsets('ISO-8859-1', 'UTF-8')) {
         echo 'Skipping tests (cannot convert charsets)...<br />', "\n";
         return;
     }
     $old_evo_charset = $evo_charset;
     $evo_charset = 'ISO-8859-1';
     $this->assertEqual(bpost_count_words(convert_charset('eine gleichung wie 1 + 2 = 9 /', 'ISO-8859-1', 'UTF-8')), 3);
     $this->assertEqual(bpost_count_words(convert_charset('mixed with the 3 ümläuts: äää ööö üüü ÄÄÄ ÖÖÖ	ÜÜÜ', 'ISO-8859-1', 'UTF-8')), 10);
     $evo_charset = 'UTF-8';
     $this->assertEqual(bpost_count_words('möre (again 3) ümläüts... öö üü ää ÄÄ ÖÖ ÜÜ'), 9);
     $this->assertEqual(bpost_count_words('russian: Расширенные возможности - это удобный'), 5);
     $this->assertEqual(bpost_count_words('A versão foi apelidade de Tilqi, porque era aniversário dele. numbers: 42'), 11);
     $this->assertEqual(bpost_count_words('HTML tags -> <a href="http://b2evolution.net" target="_blank">visit b2evo!</a>. Some other chars: "\' \' " <<< < >>> > ``` -- versão удобный überladen'), 10);
     $evo_charset = $old_evo_charset;
 }