From 06316c07128f63e41f140a728570a7d2c525b59d Mon Sep 17 00:00:00 2001 From: tokul Date: Sat, 10 Sep 2005 08:46:15 +0000 Subject: [PATCH] adding database field size checks (#1233721) git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@10083 7612ce4b-ef26-0410-bec9-ea0150e637f0 --- config/conf.pl | 36 ++++++++++++++-- config/config_default.php | 30 ++++++++++++++ doc/db-backend.txt | 21 ++++++++++ functions/db_prefs.php | 69 +++++++++++++++++++++++++++++++ plugins/administrator/defines.php | 6 +++ 5 files changed, 158 insertions(+), 4 deletions(-) diff --git a/config/conf.pl b/config/conf.pl index 2236d04b..4f7a175a 100755 --- a/config/conf.pl +++ b/config/conf.pl @@ -360,6 +360,9 @@ $abook_global_file_listing = 'true' if ( !$abook_global_file_listing ); $encode_header_key = '' if ( !$encode_header_key ); $hide_auth_header = 'false' if ( !$hide_auth_header ); $time_zone_type = '0' if ( !$time_zone_type ); +$prefs_user_size = 128 if ( !$prefs_user_size ); +$prefs_key_size = 64 if ( !$prefs_key_size ); +$prefs_val_size = 65536 if ( !$prefs_val_size ); if ( $ARGV[0] eq '--install-plugin' ) { print "Activating plugin " . $ARGV[1] . "\n"; @@ -608,9 +611,9 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) { print "\n"; print "3. DSN for Preferences : $WHT$prefs_dsn$NRM\n"; print "4. Table for Preferences : $WHT$prefs_table$NRM\n"; - print "5. Field for username : $WHT$prefs_user_field$NRM\n"; - print "6. Field for prefs key : $WHT$prefs_key_field$NRM\n"; - print "7. Field for prefs value : $WHT$prefs_val_field$NRM\n"; + print "5. Field for username : $WHT$prefs_user_field$NRM ($prefs_user_size)\n"; + print "6. Field for prefs key : $WHT$prefs_key_field$NRM ($prefs_key_size)\n"; + print "7. Field for prefs value : $WHT$prefs_val_field$NRM ($prefs_val_size)\n"; print "\n"; print "8. DSN for Global Address Book : $WHT$addrbook_global_dsn$NRM\n"; print "9. Table for Global Address Book : $WHT$addrbook_global_table$NRM\n"; @@ -2964,6 +2967,7 @@ sub command95 { } else { $new_field =~ s/[\r\n]//g; } + $prefs_user_size = db_pref_size($prefs_user_size); return $new_field; } @@ -2978,6 +2982,7 @@ sub command96 { } else { $new_field =~ s/[\r\n]//g; } + $prefs_key_size = db_pref_size($prefs_key_size); return $new_field; } @@ -2992,9 +2997,26 @@ sub command97 { } else { $new_field =~ s/[\r\n]//g; } + $prefs_val_size = db_pref_size($prefs_val_size); return $new_field; } +# routine is used to set database field limits +# it needs one argument +sub db_pref_size() { + my ($size) = $_[0]; + print "\nDatabase fields have size limits.\n"; + print "\n"; + print "What limit is set for this field? [$WHT$size$NRM]: $WHT"; + $new_size = ; + if ( $new_size eq "\n" ) { + $new_size = $size; + } else { + $new_size =~ s/[\r\n]//g; + } + return $new_size; +} + sub command98 { print "If you want to store your global address book in a database then\n"; print "you need to set this DSN to a valid value. The format for this is:\n"; @@ -3583,10 +3605,16 @@ sub save_data { print CF "\$prefs_table = '$prefs_table';\n"; # string print CF "\$prefs_user_field = '$prefs_user_field';\n"; + # integer + print CF "\$prefs_user_size = $prefs_user_size;\n"; # string print CF "\$prefs_key_field = '$prefs_key_field';\n"; + # integer + print CF "\$prefs_key_size = $prefs_key_size;\n"; # string - print CF "\$prefs_val_field = '$prefs_val_field';\n\n"; + print CF "\$prefs_val_field = '$prefs_val_field';\n"; + # integer + print CF "\$prefs_val_size = $prefs_val_size;\n\n"; # string print CF "\$addrbook_global_dsn = '$addrbook_global_dsn';\n"; # string diff --git a/config/config_default.php b/config/config_default.php index 90e8ede0..cdeb9a36 100644 --- a/config/config_default.php +++ b/config/config_default.php @@ -845,9 +845,39 @@ $addrbook_table = 'address'; */ $prefs_dsn = ''; $prefs_table = 'userprefs'; +/** + * Preference key field + * @global string $prefs_key_field + */ $prefs_key_field = 'prefkey'; +/** + * Size of preference key field + * @global integer $prefs_key_size + * @since 1.5.1 + */ +$prefs_key_size = 64; +/** + * Preference owner field + * @global string $prefs_user_field + */ $prefs_user_field = 'user'; +/** + * Size of preference owner field + * @global integer $prefs_user_size + * @since 1.5.1 + */ +$prefs_user_size = 128; +/** + * Preference value field + * @global string $prefs_val_field + */ $prefs_val_field = 'prefval'; +/** + * Size of preference key field + * @global integer $prefs_val_size + * @since 1.5.1 + */ +$prefs_val_size = 65536; /*** Global sql database options ***/ /** diff --git a/doc/db-backend.txt b/doc/db-backend.txt index 33155437..3942b40c 100644 --- a/doc/db-backend.txt +++ b/doc/db-backend.txt @@ -118,3 +118,24 @@ database. Default preferences can be set by altering the $default array in db_prefs.php. + +Troubleshooting +--------------- +1. Oversized field values. Preferences are not/can't be saved + +Database fields have size limits. Preference table example sets 128 +character limit to owner field, 64 character limit to preference key +field and 64KB (database BLOB field size) limit to value field. + +If interface tries to insert data without checking field limits, it +can cause data loss or database errors. Table information functions +provided by Pear DB libraries are not accurate and some database +backends don't support them. Since 1.5.1 SquirrelMail provides +configuration options that set allowed field sizes. + +If you see oversized field errors in your error logs - check your +database structure. Issue can be solved by increasing database field +sizes. + +If you want to get more debugging information - check setKey() function +in dbPrefs class. Class is stored in functions/db_prefs.php diff --git a/functions/db_prefs.php b/functions/db_prefs.php index fe1d4253..63db4a26 100644 --- a/functions/db_prefs.php +++ b/functions/db_prefs.php @@ -142,6 +142,25 @@ class dbPrefs { var $default = Array('theme_default' => 0, 'show_html_default' => '0'); + /** + * Preference owner field size + * @var integer + * @since 1.5.1 + */ + var $user_size = 128; + /** + * Preference key field size + * @var integer + * @since 1.5.1 + */ + var $key_size = 64; + /** + * Preference value field size + * @var integer + * @since 1.5.1 + */ + var $val_size = 65536; + /** * initialize DB connection object * @return boolean true, if object is initialized @@ -149,6 +168,7 @@ class dbPrefs { function open() { global $prefs_dsn, $prefs_table; global $prefs_user_field, $prefs_key_field, $prefs_val_field; + global $prefs_user_size, $prefs_key_size, $prefs_val_size; if(isset($this->dbh)) { return true; @@ -172,6 +192,15 @@ class dbPrefs { if (!empty($prefs_val_field)) { $this->val_field = $prefs_val_field; } + if (!empty($prefs_user_size)) { + $this->user_size = (int) $prefs_user_size; + } + if (!empty($prefs_key_size)) { + $this->key_size = (int) $prefs_key_size; + } + if (!empty($prefs_val_size)) { + $this->val_size = (int) $prefs_val_size; + } $dbh = DB::connect($prefs_dsn, true); if(DB::isError($dbh)) { @@ -261,6 +290,46 @@ class dbPrefs { if (!$this->open()) { return false; } + + /** + * Check if username fits into db field + */ + if (strlen($user) > $this->user_size) { + $this->error = "Oversized username value." + ." User's preferences can't be saved. See doc/db-backend.txt troubleshooting documentation."; + + /** + * Debugging function. Can be used to log all issues that trigger + * oversized field errors. Function should be enabled in all three + * strlen checks. See http://www.php.net/error-log + */ + // error_log($user.'|'.$key.'|'.$value."\n",3,'/tmp/oversized_log'); + + // error is fatal + $this->failQuery(null); + } + /** + * Check if preference key fits into db field + */ + if (strlen($key) > $this->key_size) { + $err_msg = "Oversized user's preference key." + ." Some user preferences are not saved. See doc/db-backend.txt troubleshooting documentation."; + // error is not fatal. Only some preference is not saved. + trigger_error($err_msg,E_USER_WARNING); + return false; + } + /** + * Check if preference value fits into db field + */ + if (strlen($value) > $this->val_size) { + $err_msg = "Oversized user's preference value." + ." Some user preferences are not saved. See doc/db-backend.txt troubleshooting documentation."; + // error is not fatal. Only some preference is not saved. + trigger_error($err_msg,E_USER_WARNING); + return false; + } + + if ($this->db_type == SMDB_MYSQL) { $query = sprintf("REPLACE INTO %s (%s, %s, %s) ". "VALUES('%s','%s','%s')", diff --git a/plugins/administrator/defines.php b/plugins/administrator/defines.php index e5deb8be..c8b6018b 100644 --- a/plugins/administrator/defines.php +++ b/plugins/administrator/defines.php @@ -289,14 +289,20 @@ $defcfg = array( '$config_version' => array( 'name' => _("Config File Version"), 'type' => SMOPT_TYPE_STRING, 'size' => 40, 'default' => 'user' ), + '$prefs_user_size' => array( 'name' => _("Size of username field"), + 'type' => SMOPT_TYPE_INTEGER ), '$prefs_key_field' => array('name' => _("Preferences key field"), 'type' => SMOPT_TYPE_STRING, 'size' => 40, 'default' => 'prefkey' ), + '$prefs_key_size' => array( 'name' => _("Size of key field"), + 'type' => SMOPT_TYPE_INTEGER ), '$prefs_val_field' => array('name' => _("Preferences value field"), 'type' => SMOPT_TYPE_STRING, 'size' => 40, 'default' => 'prefval' ), + '$prefs_val_size' => array( 'name' => _("Size of value field"), + 'type' => SMOPT_TYPE_INTEGER ), '$addrbook_global_dsn' => array( 'name' => _("Global address book DSN"), 'type' => SMOPT_TYPE_STRING, 'size' => 40 ), -- 2.25.1