Changeset 500


Ignore:
Timestamp:
Nov 15, 2014 9:34:39 PM (9 years ago)
Author:
anonymous
Message:

Many auth and crypto changes; various other bugfixes while working on pulso.

Files:
14 edited

Legend:

Unmodified
Added
Removed
  • tags/2.1.8/lib/Currency.inc.php

    r484 r500  
    44 * For details visit the project site: <http://trac.strangecode.com/codebase/>
    55 * Copyright 2001-2012 Strangecode, LLC
    6  * 
     6 *
    77 * This file is part of The Strangecode Codebase.
    88 *
     
    1111 * Free Software Foundation, either version 3 of the License, or (at your option)
    1212 * any later version.
    13  * 
     13 *
    1414 * The Strangecode Codebase is distributed in the hope that it will be useful, but
    1515 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1616 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
    1717 * details.
    18  * 
     18 *
    1919 * You should have received a copy of the GNU General Public License along with
    2020 * The Strangecode Codebase. If not, see <http://www.gnu.org/licenses/>.
     
    2828 * @author  Quinn Comendant <quinn@strangecode.com>
    2929 * @version 1.5
    30  * 
     30 *
    3131 * Example of use:
    3232---------------------------------------------------------------------
     
    3737---------------------------------------------------------------------
    3838 */
    39  
     39
    4040class Currency {
    4141
     
    4848        'api_key' => '', // Used only by xurrency API.
    4949    );
    50    
     50
    5151    /**
    5252     * Cart constructor.
     
    5858        // Set custom parameters.
    5959        $this->setParam($params);
    60        
     60
    6161        // Setup cache directory.
    6262        if ($this->getParam('cache_result')) {
     
    6666            }
    6767            if (!is_dir($this->getParam('cache_dir'))) {
    68                 $app->logMsg(sprintf('Creating cache_dir: %s', $this->getParam('cache_dir')), LOG_INFO, __FILE__, __LINE__);               
     68                $app->logMsg(sprintf('Creating cache_dir: %s', $this->getParam('cache_dir')), LOG_INFO, __FILE__, __LINE__);
    6969                if (!mkdir($this->getParam('cache_dir'))) {
    70                     $app->logMsg(sprintf('Could not create cache_dir: %s', $this->getParam('cache_dir')), LOG_WARNING, __FILE__, __LINE__);               
     70                    $app->logMsg(sprintf('Could not create cache_dir: %s', $this->getParam('cache_dir')), LOG_WARNING, __FILE__, __LINE__);
    7171                }
    7272            }
     
    9797    {
    9898        $app =& App::getInstance();
    99    
     99
    100100        if (array_key_exists($param, $this->_params)) {
    101101            return $this->_params[$param];
     
    105105        }
    106106    }
    107    
     107
    108108    /*
    109109    * Return the exchange value between the two given currencies for given amount.
     
    113113    * @param    string  $base   3-letter currency code to convert from.
    114114    * @param    string  $target 3-letter currency code to convert to.
    115     * @return   mixed   Float converted currency value, or false on error. 
     115    * @return   mixed   Float converted currency value, or false on error.
    116116    * @author   Quinn Comendant <quinn@strangecode.com>
    117117    * @version  1.0
     
    121121    {
    122122        if (false !== $rate = $this->getRate($base, $target)) {
    123             return abs($rate * $amount);           
     123            return abs($rate * $amount);
    124124        } else {
    125125            return false;
    126126        }
    127127    }
    128    
     128
    129129    /*
    130130    * Return the currency conversion rate as a ratio.
     
    133133    * @param    string  $base   3-letter currency code to convert from.
    134134    * @param    string  $target 3-letter currency code to convert to.
    135     * @return   mixed   Float exchange rate value, or false on error. 
     135    * @return   mixed   Float exchange rate value, or false on error.
    136136    * @author   Quinn Comendant <quinn@strangecode.com>
    137137    * @version  1.0
     
    173173        return trim($value);
    174174    }
    175    
     175
    176176    /**
    177177     * @param  string
     
    215215            $api_url = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
    216216            if (false === $sXML = file_get_contents($api_url)) {
    217                 $app->logMsg(sprintf('Failed to load ECB XML data from ', $api_url), LOG_WARNING, __FILE__, __LINE__);
     217                $app->logMsg(sprintf('Failed to load ECB XML data from: %s', $api_url), LOG_WARNING, __FILE__, __LINE__);
    218218                return false;
    219219            }
    220220            if (false === $oXML = simplexml_load_string($sXML)) {
    221                 $app->logMsg(sprintf('Failed to decode ECB XML data: ', truncate($sXML, 200, 'end')), LOG_WARNING, __FILE__, __LINE__);
     221                $app->logMsg(sprintf('Failed to decode ECB XML data: %s', truncate($sXML, 200, 'end')), LOG_WARNING, __FILE__, __LINE__);
    222222                return false;
    223223            }
  • trunk/bin/module_maker/_config.inc.php

    r468 r500  
    3535
    3636// Make sure necessary files exist.
    37 if (!file_exists(COMMON_BASE . '/global/db_auth.inc.php')) {
     37$db_auth_file = false;
     38$rii = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(COMMON_BASE));
     39$rii->setMaxDepth(2);
     40foreach ($rii as $filename => $file) {
     41    if (mb_strpos($filename, 'db_auth.inc.php') !== false) {
     42        $db_auth_file = $filename;
     43        break;
     44    }
     45}
     46
     47if (!$db_auth_file) {
    3848    die("Error: First argument directory must contain the global/db_auth.inc.php file with valid MySQL credentials.\n");
    3949}
     
    6373    'log_screen_priority' => LOG_DEBUG,
    6474));
    65 require_once 'global/db_auth.inc.php';
     75require_once $db_auth_file;
    6676
    6777// Start application-based functionality: database, session, environment, ini setup, etc.
  • trunk/bin/module_maker/module.cli.php

    r468 r500  
    55 * For details visit the project site: <http://trac.strangecode.com/codebase/>
    66 * Copyright 2001-2012 Strangecode, LLC
    7  * 
     7 *
    88 * This file is part of The Strangecode Codebase.
    99 *
     
    1212 * Free Software Foundation, either version 3 of the License, or (at your option)
    1313 * any later version.
    14  * 
     14 *
    1515 * The Strangecode Codebase is distributed in the hope that it will be useful, but
    1616 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1717 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
    1818 * details.
    19  * 
     19 *
    2020 * You should have received a copy of the GNU General Public License along with
    2121 * The Strangecode Codebase. If not, see <http://www.gnu.org/licenses/>.
     
    3939
    4040    " . basename($_SERVER['argv'][0]) . " site_directory name_singular name_plural [operation]
    41    
     41
    4242Valid operations include: " . join(', ', $valid_ops) . "
    4343
     
    149149    if (!is_dir("$public_tpl_dir")) {
    150150        die(basename($_SERVER['argv'][0]) . " Error: public_tpl_dir '$public_tpl_dir' directory not found.\n");
    151     }   
     151    }
    152152}
    153153
     
    196196        $type = preg_replace('/^(\w+).*$/', '\\1', $col[1]);
    197197        $default = $col[4];
    198        
     198
    199199        if (mb_strpos($default, '0000') !== false || '0' == $default) {
    200200            $default = '';
  • trunk/bin/module_maker/skel/admin.php

    r479 r500  
    408408    ";
    409409
    410     // Use a cash hash to determine if the result-set has changed.
     410    // Use a cache hash to determine if the result-set has changed.
    411411    // A unique key for this query, with the total_items in case db records
    412412    // were added since the last cache. This identifies a unique set of
  • trunk/css/admin2.inc.css

    r493 r500  
    392392    width: auto;
    393393}
     394
     395/* Hide foundation elements for sites still using old admin css. */
     396.sc-msg .close {
     397    display: none;
     398}
  • trunk/js/Msg.js

    r497 r500  
    4848    // Merge options with defaults
    4949    this.o = $.extend({
    50         container: '#sc-msg',
     50        container: '#sc-msg:last',
    5151        above_msg: '',
    5252        gotohash: true
     
    7474    if (!$(this.o.container).find(':contains("' + message + '")').length) {
    7575        $(this.o.container).append($('<div class="sc-js-msg ' + msg_class + '"></div>').text(message)).show();
     76        // $(this.o.container).append($('<div data-alert class="alert-box sc-js-msg ' + msg_class + '"></div>').hide().text(message).append('<a href="#" class="close">×</a>'));
     77        // $('.sc-js-msg').slideDown('fast');
    7678    }
    7779
  • trunk/js/Utilities.js

    r497 r500  
    4141        var args = arguments;
    4242        return this.replace(/{(\d+)}/g, function(match, number) {
    43             return typeof args[number] != 'undefined' ? args[number] : match;
     43            return typeof args[number-1] != 'undefined' ? args[number-1] : match;
    4444        });
    4545    };
  • trunk/lib/App.inc.php

    r499 r500  
    8080        'ssl_enabled' => false,
    8181
     82        // Use CSRF tokens.
     83        'csrf_token_enabled' => true,
     84        'csrf_token_name' => 'csrf_token',
     85        'csrf_token_timeout' => 86400, // In seconds. This causes form tokens to be unusable after this duration. This might only cause problems when opening forms in multiple tabs left open beyond the timeout duration. But usually their session will timeout first, and they'll receive new tokens when they load the form again..
     86
     87        // HMAC signing method
     88        'signing_method' => 'sha512+base64',
     89
    8290        // Character set for page output. Used in the Content-Type header and the HTML <meta content-type> tag.
    8391        'character_set' => 'utf-8',
     
    450458
    451459        if ('' == trim($message)) {
    452             $this->logMsg(sprintf('Raised message is an empty string.', __FUNCTION__), LOG_NOTICE, __FILE__, __LINE__);
     460            $this->logMsg(sprintf('Raised message is an empty string.', null), LOG_NOTICE, __FILE__, __LINE__);
    453461            return false;
    454462        }
     
    944952    }
    945953
    946     /*
    947     * Return a URL with a version number attached. This is useful for overriding network caches ("cache buster") for sourced media, e.g., /style.css?812763482
    948     *
    949     * @access   public
    950     * @param    string  $url    URL to media (e.g., /foo.js)
    951     * @return   string          URL with cache-busting version appended (/foo.js?v=1234567890)
    952     * @author   Quinn Comendant <quinn@strangecode.com>
    953     * @version  1.0
    954     * @since    03 Sep 2014 22:40:24
    955     */
    956     public function cacheBustURL($url)
    957     {
    958         // Get the first delimiter that is needed in the url.
    959         $delim = mb_strpos($url, '?') !== false ? ini_get('arg_separator.output') : '?';
    960         $v = crc32($this->getParam('codebase_version') . '|' . $this->getParam('site_version'));
    961         return sprintf('%s%sv=%s', $url, $delim, $v);
    962     }
    963 
    964954    /**
    965955     * Prints a hidden form element with the PHPSESSID when cookies are not used, as well
     
    971961     *                                      array('key1'=>'value', key2'='value')  <-- to set keys to default values if not present in form data.
    972962     *                                      false  <-- To not carry any queries. If URL already has queries those will be retained.
    973      */
    974     public function printHiddenSession($carry_args=null)
     963     * @param   bool    $include_csrf_token     Set to true to include the csrf_token in the form. Only use this for forms with action="post" to prevent the token from being revealed in the URL.
     964     */
     965    public function printHiddenSession($carry_args=null, $include_csrf_token=false)
    975966    {
    976967        if (!$this->running) {
     
    10231014            printf('<input type="hidden" name="%s" value="%s" />', session_name(), session_id());
    10241015        }
     1016
     1017        // Include the csrf_token in the form.
     1018        // This token can be validated upon form submission with $app->verifyCSRFToken() or $app->requireValidCSRFToken()
     1019        if ($this->getParam('csrf_token_enabled') && $include_csrf_token) {
     1020            printf('<input type="hidden" name="%s" value="%s" />', $this->getParam('csrf_token_name'), $this->recycleCSRFToken());
     1021        }
     1022    }
     1023
     1024    /*
     1025    * Return a URL with a version number attached. This is useful for overriding network caches ("cache buster") for sourced media, e.g., /style.css?812763482
     1026    *
     1027    * @access   public
     1028    * @param    string  $url    URL to media (e.g., /foo.js)
     1029    * @return   string          URL with cache-busting version appended (/foo.js?v=1234567890)
     1030    * @author   Quinn Comendant <quinn@strangecode.com>
     1031    * @version  1.0
     1032    * @since    03 Sep 2014 22:40:24
     1033    */
     1034    public function cacheBustURL($url)
     1035    {
     1036        // Get the first delimiter that is needed in the url.
     1037        $delim = mb_strpos($url, '?') !== false ? ini_get('arg_separator.output') : '?';
     1038        $v = crc32($this->getParam('codebase_version') . '|' . $this->getParam('site_version'));
     1039        return sprintf('%s%sv=%s', $url, $delim, $v);
     1040    }
     1041
     1042    /*
     1043    * Generate a csrf_token, saving it to the session and returning its value.
     1044    * https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#General_Recommendation:_Synchronizer_Token_Pattern
     1045    * @access   public
     1046    * @return   string  The new csrf_token.
     1047    * @author   Quinn Comendant <quinn@strangecode.com>
     1048    * @version  1.0
     1049    * @since    15 Nov 2014 17:53:51
     1050    */
     1051    public function generateCSRFToken()
     1052    {
     1053        return $_SESSION['_app'][$this->_ns]['csrf_tokens'][] = addSignature(time(), null, 64);
     1054    }
     1055
     1056    /*
     1057    * Update the csrf_token to a new value if it hasn't been set yet or has expired.
     1058    * Save the previous csrf_token in the session to ensure continuity of currently open sessions.
     1059    *
     1060    * @access   public
     1061    * @return   string The current csrf_token
     1062    * @author   Quinn Comendant <quinn@strangecode.com>
     1063    * @version  1.0
     1064    * @since    15 Nov 2014 17:57:17
     1065    */
     1066    public function recycleCSRFToken()
     1067    {
     1068        if (!isset($_SESSION['_app'][$this->_ns]['csrf_tokens'])) {
     1069            // No token yet; generate one and return it.
     1070            $_SESSION['_app'][$this->_ns]['csrf_tokens'] = array();
     1071            $return = $this->generateCSRFToken();
     1072        }
     1073        if (removeSignature(end($_SESSION['_app'][$this->_ns]['csrf_tokens'])) + $this->getParam('csrf_token_timeout') < time()) {
     1074            // Newest token is expired; prune array of tokens and generate new token.
     1075            // We'll save the 10-most-recent tokens. This allows the user to submit up to 5 forms saved in previously opened tabs with expired tokens (loading a form will prune one token, and submitting a form will prune one token, thus 10 = 5).
     1076            $_SESSION['_app'][$this->_ns]['csrf_tokens'] = array_slice($_SESSION['_app'][$this->_ns]['csrf_tokens'], -10, 10);
     1077            $return = $this->generateCSRFToken();
     1078        }
     1079        // Current token is not expired; return it.
     1080        $return = end($_SESSION['_app'][$this->_ns]['csrf_tokens']);
     1081        $app =& App::getInstance();
     1082        return $return;
     1083    }
     1084
     1085    /*
     1086    * Compares the given csrf_token with the current or previous one saved in the session.
     1087    *
     1088    * @access   public
     1089    * @param    string  $csrf_token     The token to compare with the session token.
     1090    * @return   bool    True if the tokens match, false otherwise.
     1091    * @author   Quinn Comendant <quinn@strangecode.com>
     1092    * @version  1.0
     1093    * @since    15 Nov 2014 18:06:55
     1094    */
     1095    public function verifyCSRFToken($csrf_token)
     1096    {
     1097        $app =& App::getInstance();
     1098
     1099        if (!$this->getParam('csrf_token_enabled')) {
     1100            $app->logMsg(sprintf('%s method called, but csrf_token_enabled=false', __FUNCTION__), LOG_ERR, __FILE__, __LINE__);
     1101            return false;
     1102        }
     1103        if ('' == trim($csrf_token)) {
     1104            $app->logMsg(sprintf('Empty string failed CSRF verification.', null), LOG_NOTICE, __FILE__, __LINE__);
     1105            return false;
     1106        }
     1107        if (!verifySignature($csrf_token, null, 64)) {
     1108            $app->logMsg(sprintf('Input failed CSRF verification (invalid signature in %s).', $csrf_token), LOG_WARNING, __FILE__, __LINE__);
     1109            return false;
     1110        }
     1111        $this->recycleCSRFToken();
     1112        if (!in_array($csrf_token, $_SESSION['_app'][$this->_ns]['csrf_tokens'])) {
     1113            $app->logMsg(sprintf('Input failed CSRF verification (%s not in %s).', $csrf_token, getDump($_SESSION['_app'][$this->_ns]['csrf_tokens'])), LOG_WARNING, __FILE__, __LINE__);
     1114            return false;
     1115        }
     1116        // $app->logMsg(sprintf('Verified token %s is in %s', $csrf_token, getDump($_SESSION['_app'][$this->_ns]['csrf_tokens'])), LOG_DEBUG, __FILE__, __LINE__);
     1117        return true;
     1118    }
     1119
     1120    /*
     1121    * Bounce user if they submit a token that doesn't match the one saved in the session.
     1122    * Because this function calls dieURL() it must be called before any other HTTP header output.
     1123    *
     1124    * @access   public
     1125    * @param    string  $csrf_token The token to compare with the session token.
     1126    * @param    string  $message    Optional message to display to the user (otherwise default message will display). Set to an empty string to display no message.
     1127    * @param    int    $type    The type of message: MSG_NOTICE,
     1128    *                           MSG_SUCCESS, MSG_WARNING, or MSG_ERR.
     1129    * @param    string $file    __FILE__.
     1130    * @param    string $line    __LINE__.
     1131    * @return   void
     1132    * @author   Quinn Comendant <quinn@strangecode.com>
     1133    * @version  1.0
     1134    * @since    15 Nov 2014 18:10:17
     1135    */
     1136    public function requireValidCSRFToken($csrf_token, $message=null, $type=MSG_NOTICE, $file=null, $line=null)
     1137    {
     1138        $app =& App::getInstance();
     1139
     1140        if (!$this->verifyCSRFToken($csrf_token)) {
     1141            $message = isset($message) ? $message : _("Something went wrong; please try again.");
     1142            $app->raiseMsg($message, $type, $file, $line);
     1143            $app->dieBoomerangURL();
     1144        }
    10251145    }
    10261146
  • trunk/lib/Auth_SQL.inc.php

    r497 r500  
    3939    const ENCRYPT_MD5 = 5;
    4040    const ENCRYPT_MD5_HARDENED = 6;
     41    const ENCRYPT_PASSWORD_BCRYPT = 7;
     42    const ENCRYPT_PASSWORD_DEFAULT = 8;
    4143
    4244    // Namespace of this auth object.
     
    174176                " . $this->getParam('db_username_column') . " varchar(255) NOT NULL default '',
    175177                userpass VARCHAR(255) NOT NULL DEFAULT '',
     178                userpass_hashtype TINYINT UNSIGNED NOT NULL DEFAULT '0',
    176179                first_name VARCHAR(255) NOT NULL DEFAULT '',
    177180                last_name VARCHAR(255) NOT NULL DEFAULT '',
     
    260263            $params['login_abuse_exempt_usernames'] = array_map('strtolower', $params['login_abuse_exempt_usernames']);
    261264        }
     265        if (isset($params['encryption_type']) && version_compare(PHP_VERSION, '5.5.0', '<') && in_array($params['encryption_type'], array(self::ENCRYPT_PASSWORD_BCRYPT, self::ENCRYPT_PASSWORD_DEFAULT))) {
     266            // These hash types require the password_* userland lib in PHP < 5.5.0
     267            $pw_compat_lib = 'vendor/ircmaxell/password-compat/lib/password.php';
     268            if (false !== stream_resolve_include_path($pw_compat_lib)) {
     269                include_once $pw_compat_lib;
     270            } else {
     271                $app =& App::getInstance();
     272                $app->logMsg(sprintf('Encryption type %s requires password-compat lib in PHP < 5.5.0; falling back to ENCRYPT_SHA1', $params['encryption_type']), LOG_ERR, __FILE__, __LINE__);
     273                $params['encryption_type'] = self::ENCRYPT_SHA1;
     274            }
     275        }
    262276        if (isset($params) && is_array($params)) {
    263277            // Merge new parameters with old overriding only those passed.
     
    353367
    354368    /**
    355      * Find out if a set of login credentials are valid.
     369     * Retrieve and verify the given username and password against a matching user record in the database.
    356370     *
    357371     * @access private
     
    367381        $this->initDB();
    368382
    369         switch ($this->_params['encryption_type']) {
    370         case self::ENCRYPT_CRYPT :
    371             // Query DB for user matching credentials. Compare cyphertext with salted-encrypted password.
    372             $qid = $db->query("
    373                 SELECT *, " . $this->_params['db_primary_key'] . " AS user_id
    374                 FROM " . $this->_params['db_table'] . "
    375                 WHERE " . $this->_params['db_username_column'] . " = '" . $db->escapeString($username) . "'
    376                 AND BINARY userpass = ENCRYPT('" . $db->escapeString($password) . "', LEFT(userpass, 2)))
    377             ");
    378             break;
    379         case self::ENCRYPT_PLAINTEXT :
    380         case self::ENCRYPT_MD5 :
    381         case self::ENCRYPT_SHA1 :
    382         default :
    383             // Query DB for user matching credentials. Directly compare cyphertext with result from encryptPassword().
    384             $qid = $db->query("
    385                 SELECT *, " . $this->_params['db_primary_key'] . " AS user_id
    386                 FROM " . $this->_params['db_table'] . "
    387                 WHERE " . $this->_params['db_username_column'] . " = '" . $db->escapeString($username) . "'
    388                 AND BINARY userpass = '" . $db->escapeString($this->encryptPassword($password)) . "'
    389             ");
    390             break;
    391         }
    392 
    393         // Return user data if found.
    394         if ($user_data = mysql_fetch_assoc($qid)) {
    395             // Don't return password value.
    396             unset($user_data['userpass']);
    397             $app->logMsg(sprintf('Authentication successful for user_id %s (%s)', $user_data['user_id'], $username), LOG_INFO, __FILE__, __LINE__);
     383        // Get user data for specified username.
     384        // Query DB for user matching credentials. Compare cyphertext with salted-encrypted password.
     385        $qid = $db->query("
     386            SELECT *, " . $this->_params['db_primary_key'] . " AS user_id
     387            FROM " . $this->_params['db_table'] . "
     388            WHERE " . $this->_params['db_username_column'] . " = '" . $db->escapeString($username) . "'
     389        ");
     390        if (!$user_data = mysql_fetch_assoc($qid)) {
     391            $app->logMsg(sprintf('Username %s not found for authentication', $username), LOG_NOTICE, __FILE__, __LINE__);
     392            return false;
     393        }
     394
     395        if ($this->verifyPassword($password, $user_data['userpass'])) {
     396            $app->logMsg(sprintf('Authentication successful for %s (user_id=%s)', $username, $user_data['user_id']), LOG_INFO, __FILE__, __LINE__);
     397            unset($user_data['userpass']); // Avoid revealing the encrypted password in the $user_data.
    398398            return $user_data;
    399         } else {
    400             $app->logMsg(sprintf('Authentication failed for username %s (encrypted attempted password: %s)', $username, $this->encryptPassword($password)), LOG_NOTICE, __FILE__, __LINE__);
    401             return false;
    402         }
     399        }
     400
     401        $app->logMsg(sprintf('Authentication failed for %s (user_id=%s)', $username, $user_data['user_id']), LOG_NOTICE, __FILE__, __LINE__);
     402        return false;
    403403    }
    404404
     
    553553                SELECT 1 FROM " . $this->_params['db_table'] . "
    554554                WHERE " . $this->_params['db_primary_key'] . " = '" . $db->escapeString($user_id) . "'
    555                 AND DATE_ADD(last_login_datetime, INTERVAL '" . $this->_params['login_timeout'] . "' SECOND) > NOW()
    556                 AND DATE_ADD(last_access_datetime, INTERVAL '" . $this->_params['idle_timeout'] . "' SECOND) > NOW()
     555                AND last_login_datetime > DATE_SUB(NOW(), INTERVAL '" . $this->_params['login_timeout'] . "' SECOND)
     556                AND last_access_datetime > DATE_SUB(NOW(), INTERVAL '" . $this->_params['idle_timeout'] . "' SECOND)
    557557            ");
    558558            $login_status = (mysql_num_rows($qid) > 0);
     
    809809    }
    810810
    811     /**
    812      * Returns a randomly generated password based on $pattern. The pattern is any
    813      * sequence of 'x', 'V', 'C', 'v', 'c', or 'd' and if it is something like 'cvccv' this
    814      * function will generate a pronounceable password. Recommend using more complex
    815      * patterns, at minimum the US State Department standard: cvcddcvc.
    816      *
    817      * - x    A random upper or lower character, digit, or punctuation.
    818      * - C    A random upper or lower consonant.
    819      * - V    A random upper or lower vowel.
    820      * - c    A random lowercase consonant.
    821      * - v    A random lowercase vowel.
    822      * - d    A random digit.
    823      *
    824      * @param  string $pattern  a sequence of character types, above.
    825      * @return string           a password
    826      */
    827     public function generatePassword($pattern='CvcdCvc')
    828     {
    829         $app =& App::getInstance();
    830         if (preg_match('/[^xCVcvd]/', $pattern)) {
    831             $app->logMsg(sprintf('Invalid pattern: %s', $pattern), LOG_WARNING, __FILE__, __LINE__);
    832             $pattern='CvcdCvc';
    833         }
    834         $str = '';
    835         for ($i=0; $i<mb_strlen($pattern); $i++) {
    836             $x = mb_substr('bcdfghjklmnprstvwxzBCDFGHJKLMNPRSTVWXZaeiouyAEIOUY0123456789!@#%&*-=+.?', (mt_rand() % 71), 1);
    837             $c = mb_substr('bcdfghjklmnprstvwxz', (mt_rand() % 19), 1);
    838             $C = mb_substr('bcdfghjklmnprstvwxzBCDFGHJKLMNPRSTVWXZ', (mt_rand() % 38), 1);
    839             $v = mb_substr('aeiouy', (mt_rand() % 6), 1);
    840             $V = mb_substr('aeiouyAEIOUY', (mt_rand() % 12), 1);
    841             $d = mb_substr('0123456789', (mt_rand() % 10), 1);
    842             $str .= $$pattern[$i];
    843         }
    844         return $str;
     811    /*
     812    * Generate a cryptographically secure, random password.
     813    *
     814    * @access   public
     815    * @param    int  $bytes     Length of password (in bytes)
     816    * @return   string          Random string of characters.
     817    * @author   Quinn Comendant <quinn@strangecode.com>
     818    * @version  1.0
     819    * @since    15 Nov 2014 20:30:27
     820    */
     821    public function generatePassword($bytes=10)
     822    {
     823        $app =& App::getInstance();
     824
     825        $bytes = is_numeric($bytes) ? $bytes : 10;
     826        $string = strtok(base64_encode(openssl_random_pseudo_bytes($bytes, $strong)), '=');
     827        if (!$strong) {
     828            $app->logMsg(sprintf('Password generated was not "cryptographically strong"; check your openssl.', null), LOG_NOTICE, __FILE__, __LINE__);
     829        }
     830
     831        return $string;
    845832    }
    846833
     
    851838    {
    852839        $app =& App::getInstance();
     840
     841        $password = (string)$password;
    853842
    854843        // Existing password hashes rely on the same key/salt being used to compare encryptions.
     
    858847        switch ($this->_params['encryption_type']) {
    859848        case self::ENCRYPT_PLAINTEXT :
    860             return $password;
     849            $encrypted_password = $password;
    861850            break;
    862851
    863852        case self::ENCRYPT_CRYPT :
    864             // If comparing plaintext password with a hash, provide first two chars of the hash as the salt.
    865             return isset($salt) ? crypt($password, mb_substr($salt, 0, 2)) : crypt($password);
     853            // If comparing password with an existing hashed password, provide the hashed password as the salt.
     854            $encrypted_password = isset($salt) ? crypt($password, $salt) : crypt($password);
    866855            break;
    867856
    868857        case self::ENCRYPT_SHA1 :
    869             return sha1($password);
     858            $encrypted_password = sha1($password);
    870859            break;
    871860
    872861        case self::ENCRYPT_SHA1_HARDENED :
    873             $hash = sha1($app->getParam('signing_key') . $password . $more_salt);
    874             // Increase key strength by 12 bits.
    875             for ($i=0; $i < 4096; $i++) {
    876                 $hash = sha1($hash);
    877             }
    878             return $hash;
     862            $encrypted_password = sha1($app->getParam('signing_key') . $password . $more_salt);
     863            for ($i=0; $i < pow(2, 20); $i++) {
     864                $encrypted_password = sha1($password . $encrypted_password);
     865            }
    879866            break;
    880867
    881868        case self::ENCRYPT_MD5 :
    882             return md5($password);
     869            $encrypted_password = md5($password);
    883870            break;
    884871
    885872        case self::ENCRYPT_MD5_HARDENED :
    886             // Include salt to improve hash
    887             $hash = md5($app->getParam('signing_key') . $password . $more_salt);
    888             // Increase key strength by 12 bits.
    889             for ($i=0; $i < 4096; $i++) {
    890                 $hash = md5($hash);
    891             }
    892             return $hash;
     873            $encrypted_password = md5($app->getParam('signing_key') . $password . $more_salt);
     874            for ($i=0; $i < pow(2, 20); $i++) {
     875                $encrypted_password = md5($password . $encrypted_password);
     876            }
     877            break;
     878
     879        case self::ENCRYPT_PASSWORD_BCRYPT :
     880            $encrypted_password = password_hash($password, PASSWORD_BCRYPT, array('cost' => 12));
     881            break;
     882
     883        case self::ENCRYPT_PASSWORD_DEFAULT :
     884            $encrypted_password = password_hash($password, PASSWORD_DEFAULT, array('cost' => 12));
    893885            break;
    894886
     
    897889            return false;
    898890            break;
     891        }
     892
     893        // In case our hashing function returns 'false' or another empty value, bail out.
     894        if ('' == trim((string)$encrypted_password)) {
     895            $app->logMsg(sprintf('Invalid password hash returned; check yo crypto!', null), LOG_ALERT, __FILE__, __LINE__);
     896            return false;
     897        }
     898
     899        return $encrypted_password;
     900    }
     901
     902    /*
     903    *
     904    *
     905    * @access   public
     906    * @param
     907    * @return
     908    * @author   Quinn Comendant <quinn@strangecode.com>
     909    * @version  1.0
     910    * @since    15 Nov 2014 21:37:28
     911    */
     912    public function verifyPassword($password, $encrypted_password)
     913    {
     914        switch ($this->_params['encryption_type']) {
     915        case self::ENCRYPT_CRYPT :
     916            return $this->encryptPassword($password, $encrypted_password) == $encrypted_password;
     917
     918        case self::ENCRYPT_PLAINTEXT :
     919        case self::ENCRYPT_MD5 :
     920        case self::ENCRYPT_MD5_HARDENED :
     921        case self::ENCRYPT_SHA1 :
     922        case self::ENCRYPT_SHA1_HARDENED :
     923        default :
     924            return $this->encryptPassword($password) == $encrypted_password;
     925
     926        case self::ENCRYPT_PASSWORD_BCRYPT :
     927        case self::ENCRYPT_PASSWORD_DEFAULT :
     928            return password_verify($password, $encrypted_password);
    899929        }
    900930    }
     
    920950        ");
    921951        if (!list($old_encrypted_password) = mysql_fetch_row($qid)) {
    922             $app->logMsg(sprintf('Cannot set password for nonexistent user_id %s', $user_id), LOG_NOTICE, __FILE__, __LINE__);
     952            $app->logMsg(sprintf('Cannot set password for nonexistent user_id %s', $user_id), LOG_WARNING, __FILE__, __LINE__);
    923953            return false;
    924954        }
    925955
    926956        // Compare old with new to ensure we're actually *changing* the password.
    927         $encrypted_password = $this->encryptPassword($password);
    928         if ($old_encrypted_password == $encrypted_password) {
     957        if ($this->verifyPassword($password, $old_encrypted_password)) {
    929958            $app->logMsg(sprintf('Not setting password: new is the same as old.', null), LOG_INFO, __FILE__, __LINE__);
    930             return false;
     959            return null;
     960        }
     961
     962        // Save the hash method used if a table exists for it.
     963        $userpass_hashtype = '';
     964        if ($db->columnExists($this->_params['db_table'], 'userpass_hashtype', false)) {
     965            $userpass_hashtype = ", userpass_hashtype = '" . $db->escapeString($this->getParam('encryption_type')) . "'";
    931966        }
    932967
     
    934969        $db->query("
    935970            UPDATE " . $this->_params['db_table'] . "
    936             SET userpass = '" . $db->escapeString($encrypted_password) . "'
     971            SET userpass = '" . $db->escapeString($this->encryptPassword($password)) . "'
     972            $userpass_hashtype
    937973            WHERE " . $this->_params['db_primary_key'] . " = '" . $db->escapeString($user_id) . "'
    938974        ");
     
    943979        }
    944980
     981        $app->logMsg(sprintf('Password change successful for user_id %s', $user_id), LOG_INFO, __FILE__, __LINE__);
    945982        return true;
    946983    }
     
    10081045    }
    10091046
    1010     /**
    1011      * If the current user has access to the specified $security_zone, return true.
    1012      * If the optional $user_type is supplied, test that against the zone.
    1013      *
    1014      * NOTE: "user_type" used to be called "priv" in some older implementations.
    1015      *
    1016      * @param  constant $security_zone   string of comma delimited privileges for the zone
    1017      * @param  string   $user_type       a privilege that might be found in a zone
    1018      * @return bool     true if user is a member of security zone, false otherwise
    1019      */
    1020     public function inClearanceZone($security_zone, $user_type='')
    1021     {
    1022         $zone_members = preg_split('/,\s*/', $security_zone);
    1023         $user_type = empty($user_type) ? $this->get('user_type') : $user_type;
    1024 
    1025         // If the current user's privilege level is NOT in that array or if the
    1026         // user has no privilege, return false. Otherwise the user is clear.
    1027         if (!in_array($user_type, $zone_members) || empty($user_type)) {
    1028             return false;
    1029         } else {
    1030             return true;
    1031         }
    1032     }
    1033 
    1034     /**
    1035      * This function tests a list of arguments $security_zone against the priv that the current user has.
    1036      * If the user doesn't have one of the supplied privs, die.
    1037      *
    1038      * NOTE: "user_type" used to be called "priv" in some older implementations.
    1039      *
    1040      * @param  constant $security_zone   string of comma delimited privileges for the zone
    1041      */
    1042     public function requireAccessClearance($security_zone, $message='')
    1043     {
    1044         $app =& App::getInstance();
    1045 
    1046         $zone_members = preg_split('/,\s*/', $security_zone);
    1047 
    1048         /* If the current user's privilege level is NOT in that array or if the
    1049          * user has no privilege, DIE with a message. */
    1050         if (!in_array($this->get('user_type'), $zone_members) || !$this->get('user_type')) {
    1051             $message = empty($message) ? _("You have insufficient privileges to view that page.") : $message;
    1052             $app->raiseMsg($message, MSG_NOTICE, __FILE__, __LINE__);
    1053             $app->dieBoomerangURL();
    1054         }
    1055     }
    1056 
    10571047} // end class
    1058 
    1059 // CIDR cheat-sheet
    1060 //
    1061 // Netmask              Netmask (binary)                 CIDR     Notes
    1062 // _____________________________________________________________________________
    1063 // 255.255.255.255  11111111.11111111.11111111.11111111  /32  Host (single addr)
    1064 // 255.255.255.254  11111111.11111111.11111111.11111110  /31  Unusable
    1065 // 255.255.255.252  11111111.11111111.11111111.11111100  /30    2  useable
    1066 // 255.255.255.248  11111111.11111111.11111111.11111000  /29    6  useable
    1067 // 255.255.255.240  11111111.11111111.11111111.11110000  /28   14  useable
    1068 // 255.255.255.224  11111111.11111111.11111111.11100000  /27   30  useable
    1069 // 255.255.255.192  11111111.11111111.11111111.11000000  /26   62  useable
    1070 // 255.255.255.128  11111111.11111111.11111111.10000000  /25  126  useable
    1071 // 255.255.255.0    11111111.11111111.11111111.00000000  /24 "Class C" 254 useable
    1072 //
    1073 // 255.255.254.0    11111111.11111111.11111110.00000000  /23    2  Class C's
    1074 // 255.255.252.0    11111111.11111111.11111100.00000000  /22    4  Class C's
    1075 // 255.255.248.0    11111111.11111111.11111000.00000000  /21    8  Class C's
    1076 // 255.255.240.0    11111111.11111111.11110000.00000000  /20   16  Class C's
    1077 // 255.255.224.0    11111111.11111111.11100000.00000000  /19   32  Class C's
    1078 // 255.255.192.0    11111111.11111111.11000000.00000000  /18   64  Class C's
    1079 // 255.255.128.0    11111111.11111111.10000000.00000000  /17  128  Class C's
    1080 // 255.255.0.0      11111111.11111111.00000000.00000000  /16  "Class B"
    1081 //
    1082 // 255.254.0.0      11111111.11111110.00000000.00000000  /15    2  Class B's
    1083 // 255.252.0.0      11111111.11111100.00000000.00000000  /14    4  Class B's
    1084 // 255.248.0.0      11111111.11111000.00000000.00000000  /13    8  Class B's
    1085 // 255.240.0.0      11111111.11110000.00000000.00000000  /12   16  Class B's
    1086 // 255.224.0.0      11111111.11100000.00000000.00000000  /11   32  Class B's
    1087 // 255.192.0.0      11111111.11000000.00000000.00000000  /10   64  Class B's
    1088 // 255.128.0.0      11111111.10000000.00000000.00000000  /9   128  Class B's
    1089 // 255.0.0.0        11111111.00000000.00000000.00000000  /8   "Class A"
    1090 //
    1091 // 254.0.0.0        11111110.00000000.00000000.00000000  /7
    1092 // 252.0.0.0        11111100.00000000.00000000.00000000  /6
    1093 // 248.0.0.0        11111000.00000000.00000000.00000000  /5
    1094 // 240.0.0.0        11110000.00000000.00000000.00000000  /4
    1095 // 224.0.0.0        11100000.00000000.00000000.00000000  /3
    1096 // 192.0.0.0        11000000.00000000.00000000.00000000  /2
    1097 // 128.0.0.0        10000000.00000000.00000000.00000000  /1
    1098 // 0.0.0.0          00000000.00000000.00000000.00000000  /0   IP space
  • trunk/lib/Currency.inc.php

    r484 r500  
    44 * For details visit the project site: <http://trac.strangecode.com/codebase/>
    55 * Copyright 2001-2012 Strangecode, LLC
    6  * 
     6 *
    77 * This file is part of The Strangecode Codebase.
    88 *
     
    1111 * Free Software Foundation, either version 3 of the License, or (at your option)
    1212 * any later version.
    13  * 
     13 *
    1414 * The Strangecode Codebase is distributed in the hope that it will be useful, but
    1515 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    1616 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
    1717 * details.
    18  * 
     18 *
    1919 * You should have received a copy of the GNU General Public License along with
    2020 * The Strangecode Codebase. If not, see <http://www.gnu.org/licenses/>.
     
    2828 * @author  Quinn Comendant <quinn@strangecode.com>
    2929 * @version 1.5
    30  * 
     30 *
    3131 * Example of use:
    3232---------------------------------------------------------------------
     
    3737---------------------------------------------------------------------
    3838 */
    39  
     39
    4040class Currency {
    4141
     
    4848        'api_key' => '', // Used only by xurrency API.
    4949    );
    50    
     50
    5151    /**
    5252     * Cart constructor.
     
    5858        // Set custom parameters.
    5959        $this->setParam($params);
    60        
     60
    6161        // Setup cache directory.
    6262        if ($this->getParam('cache_result')) {
     
    6666            }
    6767            if (!is_dir($this->getParam('cache_dir'))) {
    68                 $app->logMsg(sprintf('Creating cache_dir: %s', $this->getParam('cache_dir')), LOG_INFO, __FILE__, __LINE__);               
     68                $app->logMsg(sprintf('Creating cache_dir: %s', $this->getParam('cache_dir')), LOG_INFO, __FILE__, __LINE__);
    6969                if (!mkdir($this->getParam('cache_dir'))) {
    70                     $app->logMsg(sprintf('Could not create cache_dir: %s', $this->getParam('cache_dir')), LOG_WARNING, __FILE__, __LINE__);               
     70                    $app->logMsg(sprintf('Could not create cache_dir: %s', $this->getParam('cache_dir')), LOG_WARNING, __FILE__, __LINE__);
    7171                }
    7272            }
     
    9797    {
    9898        $app =& App::getInstance();
    99    
     99
    100100        if (array_key_exists($param, $this->_params)) {
    101101            return $this->_params[$param];
     
    105105        }
    106106    }
    107    
     107
    108108    /*
    109109    * Return the exchange value between the two given currencies for given amount.
     
    113113    * @param    string  $base   3-letter currency code to convert from.
    114114    * @param    string  $target 3-letter currency code to convert to.
    115     * @return   mixed   Float converted currency value, or false on error. 
     115    * @return   mixed   Float converted currency value, or false on error.
    116116    * @author   Quinn Comendant <quinn@strangecode.com>
    117117    * @version  1.0
     
    121121    {
    122122        if (false !== $rate = $this->getRate($base, $target)) {
    123             return abs($rate * $amount);           
     123            return abs($rate * $amount);
    124124        } else {
    125125            return false;
    126126        }
    127127    }
    128    
     128
    129129    /*
    130130    * Return the currency conversion rate as a ratio.
     
    133133    * @param    string  $base   3-letter currency code to convert from.
    134134    * @param    string  $target 3-letter currency code to convert to.
    135     * @return   mixed   Float exchange rate value, or false on error. 
     135    * @return   mixed   Float exchange rate value, or false on error.
    136136    * @author   Quinn Comendant <quinn@strangecode.com>
    137137    * @version  1.0
     
    173173        return trim($value);
    174174    }
    175    
     175
    176176    /**
    177177     * @param  string
     
    215215            $api_url = 'http://www.ecb.europa.eu/stats/eurofxref/eurofxref-daily.xml';
    216216            if (false === $sXML = file_get_contents($api_url)) {
    217                 $app->logMsg(sprintf('Failed to load ECB XML data from ', $api_url), LOG_WARNING, __FILE__, __LINE__);
     217                $app->logMsg(sprintf('Failed to load ECB XML data from: %s', $api_url), LOG_WARNING, __FILE__, __LINE__);
    218218                return false;
    219219            }
    220220            if (false === $oXML = simplexml_load_string($sXML)) {
    221                 $app->logMsg(sprintf('Failed to decode ECB XML data: ', truncate($sXML, 200, 'end')), LOG_WARNING, __FILE__, __LINE__);
     221                $app->logMsg(sprintf('Failed to decode ECB XML data: %s', truncate($sXML, 200, 'end')), LOG_WARNING, __FILE__, __LINE__);
    222222                return false;
    223223            }
  • trunk/lib/Email.inc.php

    r490 r500  
    314314        foreach ($headers as $key => $val) {
    315315            // Validate key and values.
    316             if (empty($key) || empty($val) || !is_string($key) || !is_string($val) || preg_match("/[\n\r]/", $key . $val) || preg_match('/[^\w-]/', $key)) {
    317                 $app->logMsg(sprintf('Broken headers provided: %s=%s', $key, $val), LOG_WARNING, __FILE__, __LINE__);
     316            if (empty($val)) {
     317                $app->logMsg(sprintf('Empty email header provided: %s', $key), LOG_DEBUG, __FILE__, __LINE__);
     318                continue;
     319            }
     320            if (empty($key) || !is_string($key) || !is_string($val) || preg_match("/[\n\r]/", $key . $val) || preg_match('/[^\w-]/', $key)) {
     321                $app->logMsg(sprintf('Broken email header provided: %s=%s', $key, $val), LOG_WARNING, __FILE__, __LINE__);
    318322                continue;
    319323            }
  • trunk/lib/HTML.inc.php

    r497 r500  
    3939
    4040class HTML {
     41
     42    // Browsers add names and ids of form controls as properties to the FORM. This results in the properties of the form being replaced.
     43    // Use this list to warn the programmer if he uses an unsafe name.
     44    // http://jibbering.com/faq/names/unsafe_names.html
     45    static $unsafe_form_control_names = array('accept','acceptCharset','action','addBehavior','addEventListener','addEventSource','addRepetitionBlock','addRepetitionBlockByIndex','all','appendChild','applyElement','ariaBusy','ariaChecked','ariaControls','ariaDescribability','ariaDisabled','ariaExpanded','ariaFlowto','ariaHaspopup','ariaHidden','ariaInvalid','ariaLabelledby','ariaLevel','ariaMultiselect','ariaOwns','ariaPosinset','ariaPressed','ariaReadonly','ariaRequired','ariaSecret','ariaSelected','ariaSetsize','ariaValuemax','ariaValuemin','ariaValuenow','attachEvent','attributes','ATTRIBUTE_NODE','autocomplete','baseURI','behaviorUrns','blockDiraction','blur','canHaveChildren','canHaveHTML','CDATA_SECTION_NODE','checkValidity','childElementCount','childNodes','children','className','clearAttributes','click','clientHeight','clientLeft','clientTop','clientWidth','cloneNode','COMMENT_NODE','compareDocumentPosition','componentFromPoint','constructor','contains','contentEditable','currentStyle','data','detachEvent','dir','dispatchEvent','dispatchFormChange','dispatchFormInput','document','DOCUMENT_FRAGMENT_NODE','DOCUMENT_NODE','DOCUMENT_POSITION_CONTAINED_BY','DOCUMENT_POSITION_CONTAINS','DOCUMENT_POSITION_DISCONNECTED','DOCUMENT_POSITION_FOLLOWING','DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC','DOCUMENT_POSITION_PRECEDING','DOCUMENT_TYPE_NODE','dragDrop','elements','ELEMENT_NODE','encoding','enctype','ENTITY_NODE','ENTITY_REFERENCE_NODE','fireEvent','firstChild','firstElementChild','focus','getAdjacentText','getAttribute','getAttributeNode','getAttributeNodeNS','getAttributeNS','getBoundingClientRect','getClientRects','getElementsByClassName','getElementsByTagName','getElementsByTagNameNS','getExpression','getFeature','getUserData','hasAttribute','hasAttributeNS','hasAttributes','hasChildNodes','hasOwnProperty','hideFocus','id','innerHTML','innerText','insertAdjacentElement','insertAdjacentHTML','insertAdjacentText','insertBefore','isContentEditable','isDefaultNamespace','isDefaultNamespaceURI','isDisabled','isEqualNode','isMultiLine','isPrototypeOf','isSameNode','isSupported','isTextEdit','item','lang','language','lastChild','lastElementChild','length','localName','lookupPrefix','mergeAttributes','method','moveRepetitionBlock','msBlockProgression','msBoxSizing','name','namedItem','namespaceURI','nextSibling','nodeName','nodeType','nodeValue','normalize','NOTATION_NODE','offsetHeight','offsetWidth','onabort','onactivate','onbeforeactivate','onbeforecopy','onbeforecut','onbeforedeactivate','onbeforeeditfocus','onbeforepaste','onblur','onchage','onclick','onclosecapture','oncontextmenu','oncopy','oncut','ondblclick','ondeactivate','ondrag','ondragend','ondragenter','ondragleave','ondragover','onerror','onfocus','onfocusin','onfocusout','onhelp','oninput','onkeydown','onkeypress','onkeyup','onmousedown','onmouseenter','onmouseleave','onmousemove','onmousemultiwheel','onmouseout','onmouseover','onmouseup','onmousewheel','onmove','onmoveend','onmovestart','onOffBehavior','onpaste','onpropertychange','onreadystatechange','onresize','onresizeend','onresizestart','onscroll','onsearch','onselect','onselectstart','ontimeerror','onunload','outerHTML','outerText','ownerDocument','parentNode','parentTextEdit','prefix','previousElementSibling','previousSibling','PROCESSING_INSTRUCTION_NODE','propertyIsEnumerable','querySelector','querySelectorAll','quotes','releaseCapture','removeAttribute','removeAttributeNode','removeAttributeNS','removeBehavior','removeChild','removeEventListener','removeEventSource','removeExpression','removeNode','removeRepetitionBlock','repeatMax','repeatMin','repeatStart','repetitionBlocks','repetitionIndex','repetitionTemplate','repetitionType','replace','replaceAdjacentText','replaceChild','replaceNode','reset','resetFromData','role','runtimeStyle','schemaTypeInfo','scopeName','scrollByLines','scrollByPages','scrollHeight','scrollIntoView','scrollLeft','scrollTop','scrollWidth','selectNodes','selectSingleNode','setActive','setAttributeNode','setAttributeNodeNS','setAttributeNS','setCapture','setExpression','setIdAttribute','setIdAttributeNode','setIdAttributeNS','setUserData','sourceIndex','spellcheck','style','submit','swapNode','tabIndex','tagName','tagUrn','target','templateElements','text','textContent','TEXT_NODE','title','toLocaleString','toString','uniqueID','unselectable','unwatch','urns','valueOf','watch','window');
    4146
    4247    /**
     
    5358    static public function printButtons($buttons=array(), $class='button-group')
    5459    {
     60        $app =& App::getInstance();
     61
    5562        if (!isset($buttons[0]) || !is_array($buttons[0])) {
    5663            $app =& App::getInstance();
     
    7380                echo '>' . oTxt($b['value']) . '</a></li>';
    7481            } else if (isset($b['name'])) {
     82                if (in_array($b['name'], self::$unsafe_form_control_names)) {
     83                    $app->logMsg(sprintf('Unsafe form control name: %s', $b['name']), LOG_NOTICE, __FILE__, __LINE__);
     84                }
    7585                $defaults['id'] = isset($b['id']) ? $b['id'] : sprintf('sc-%s-button', $b['name']);
    7686                echo '<li><input';
  • trunk/lib/Utilities.inc.php

    r497 r500  
    945945 * environment variable set in httpd.conf is a good place.
    946946 *
     947 * TODO: consider using more bits-per-character, such as done with:
     948 * http://www.php.net/manual/en/function.sha1.php#86239
     949 * http://blog.kevburnsjr.com/php-unique-hash
     950 *
    947951 * @access  public
    948952 * @param   string  $val    The string to sign.
     
    964968    }
    965969
    966     // TODO: consider using more bits-per-character, such as done with:
    967     // http://www.php.net/manual/en/function.sha1.php#86239
    968     // http://blog.kevburnsjr.com/php-unique-hash
    969     return $val . '-' . mb_strtolower(mb_substr(md5($salt . md5($val . $salt)), 0, $length));
     970    switch ($app->getParam('signing_method')) {
     971    case 'sha512+base64':
     972        return $val . '-' . mb_substr(preg_replace('/[^\w]/', '', base64_encode(hash('sha512', $val . $salt, true))), 0, $length);
     973
     974    case 'md5':
     975    default:
     976        return $val . '-' . mb_strtolower(mb_substr(md5($salt . md5($val . $salt)), 0, $length));
     977    }
    970978}
    971979
     
    986994
    987995/**
    988  * Verifies a signature appened to a value by addSignature().
     996 * Verifies a signature appended to a value by addSignature().
    989997 *
    990998 * @access  public
     
    9951003function verifySignature($signed_val, $salt=null, $length=18)
    9961004{
    997     // All comparisons are done using lower-case strings.
    998     $signed_val = mb_strtolower($signed_val);
    9991005    // Strip the value from the signed value.
    10001006    $val = removeSignature($signed_val);
     
    10041010        return true;
    10051011    } else {
     1012        $app =& App::getInstance();
     1013        $app->logMsg(sprintf('Failed signature (%s should be %s)', $signed_val, addSignature($val, $salt, $length)), LOG_DEBUG, __FILE__, __LINE__);
    10061014        return false;
    10071015    }
     
    12551263    }
    12561264}
    1257 
  • trunk/lib/Validator.inc.php

    r490 r500  
    162162    static public function stringLength($val, $min, $max)
    163163    {
    164         return mb_strlen(trim((string)$val)) >= $min && mb_strlen($val) <= $max;
     164        return mb_strlen((string)$val) >= $min && mb_strlen((string)$val) <= $max;
    165165    }
    166166
Note: See TracChangeset for help on using the changeset viewer.