increment year in copyright notices
[squirrelmail.git] / config / conf.pl
index e4391c47aa5935042f96cbe05d0cdc5463bbdbcb..5af0a43c8e9d8349af4e24705e79240fad220539 100755 (executable)
@@ -1,14 +1,14 @@
 #!/usr/bin/env perl
 # conf.pl
 #
 #!/usr/bin/env perl
 # conf.pl
 #
-# Copyright (c) 1999-2005 The SquirrelMail Project Team
+# Copyright (c) 1999-2007 The SquirrelMail Project Team
 # Licensed under the GNU GPL. For full terms see COPYING.
 #
 # A simple configure script to configure SquirrelMail
 #
 # $Id$
 ############################################################
 # Licensed under the GNU GPL. For full terms see COPYING.
 #
 # A simple configure script to configure SquirrelMail
 #
 # $Id$
 ############################################################
-$conf_pl_version = "1.4.0";
+$conf_pl_version = "1.5.0";
 
 ############################################################
 # Check what directory we're supposed to be running in, and
 
 ############################################################
 # Check what directory we're supposed to be running in, and
@@ -46,6 +46,17 @@ $dir = cwd();
 # First, lets read in the data already in there...
 ############################################################
 if ( -e "config.php" ) {
 # First, lets read in the data already in there...
 ############################################################
 if ( -e "config.php" ) {
+    # Make sure that file is readable
+    if (! -r "config.php") {
+        clear_screen();
+        print "WARNING:\n";
+        print "The file \"config/config.php\" was found, but you don't\n";
+        print "have rights to read it.\n";
+        print "\n";
+        print "Press enter to continue";
+        $ctu = <STDIN>;
+        exit;
+    }
     open( FILE, "config.php" );
     while ( $line = <FILE> ) {
         $line =~ s/^\s+//;
     open( FILE, "config.php" );
     while ( $line = <FILE> ) {
         $line =~ s/^\s+//;
@@ -70,7 +81,7 @@ if ( -e "config.php" ) {
 
     if ( $config_version ne $conf_pl_version ) {
         clear_screen();
 
     if ( $config_version ne $conf_pl_version ) {
         clear_screen();
-        print $WHT. "WARNING:\n" . $NRM;
+        print "WARNING:\n";
         print "  The file \"config/config.php\" was found, but it is for\n";
         print "  an older version of SquirrelMail. It is possible to still\n";
         print "  read the defaults from this file but be warned that many\n";
         print "  The file \"config/config.php\" was found, but it is for\n";
         print "  an older version of SquirrelMail. It is possible to still\n";
         print "  read the defaults from this file but be warned that many\n";
@@ -123,7 +134,7 @@ if ( -e "config.php" ) {
 
     if ( $config_version ne $conf_pl_version ) {
         clear_screen();
 
     if ( $config_version ne $conf_pl_version ) {
         clear_screen();
-        print $WHT. "WARNING:\n" . $NRM;
+        print "WARNING:\n";
         print "  You are trying to use a 'config_default.php' from an older\n";
         print "  version of SquirrelMail. This is HIGHLY unrecommended. You\n";
         print "  should get the 'config_default.php' that matches the version\n";
         print "  You are trying to use a 'config_default.php' from an older\n";
         print "  version of SquirrelMail. This is HIGHLY unrecommended. You\n";
         print "  should get the 'config_default.php' that matches the version\n";
@@ -175,19 +186,57 @@ while ( $line = <FILE> ) {
         $options[1] =~ s/\\'/'/g;
         $options[1] =~ s/\\\\/\\/g;
 
         $options[1] =~ s/\\'/'/g;
         $options[1] =~ s/\\\\/\\/g;
 
-        if ( $options[0] =~ /^theme\[[0-9]+\]\[['"]PATH['"]\]/ ) {
+        if ( $options[0] =~ /^user_themes\[[0-9]+\]\[['"]PATH['"]\]/ ) {
+            $sub = $options[0];
+            $sub =~ s/\]\[['"]PATH['"]\]//;
+            $sub =~ s/.*\[//;
+            if ( -e "../css/" ) {
+                $options[1] =~ s/^\.\.\/config/\.\.\/css/;
+            }
+            $user_theme_path[$sub] = &change_to_rel_path($options[1]);
+        } elsif ( $options[0] =~ /^user_themes\[[0-9]+\]\[['"]NAME['"]\]/ ) {
+            $sub = $options[0];
+            $sub =~ s/\]\[['"]NAME['"]\]//;
+            $sub =~ s/.*\[//;
+            $user_theme_name[$sub] = $options[1];
+        } elsif ( $options[0] =~ /^icon_themes\[[0-9]+\]\[['"]PATH['"]\]/ ) {
             $sub = $options[0];
             $sub =~ s/\]\[['"]PATH['"]\]//;
             $sub =~ s/.*\[//;
             $sub = $options[0];
             $sub =~ s/\]\[['"]PATH['"]\]//;
             $sub =~ s/.*\[//;
-            if ( -e "../themes" ) {
-                $options[1] =~ s/^\.\.\/config/\.\.\/themes/;
+            if ( -e "../images/" ) {
+                $options[1] =~ s/^\.\.\/config/\.\.\/images/;
+            }
+            $icon_theme_path[$sub] = &change_to_rel_path($options[1]);
+        } elsif ( $options[0] =~ /^icon_themes\[[0-9]+\]\[['"]NAME['"]\]/ ) {
+            $sub = $options[0];
+            $sub =~ s/\]\[['"]NAME['"]\]//;
+            $sub =~ s/.*\[//;
+            $icon_theme_name[$sub] = $options[1];
+        } elsif ( $options[0] =~ /^aTemplateSet\[[0-9]+\]\[['"]ID['"]\]/ ) {
+            $sub = $options[0];
+            $sub =~ s/\]\[['"]ID['"]\]//;
+            $sub =~ s/.*\[//;
+            if ( -e "../templates" ) {
+                $options[1] =~ s/^\.\.\/config/\.\.\/templates/;
             }
             }
-            $theme_path[$sub] = &change_to_rel_path($options[1]);
-        } elsif ( $options[0] =~ /^theme\[[0-9]+\]\[['"]NAME['"]\]/ ) {
+            $templateset_id[$sub] = $options[1];
+##### FIXME: This section BELOW here so old prefs files don't blow up when running conf.pl
+#####        Remove after a month or two 
+} elsif ( $options[0] =~ /^aTemplateSet\[[0-9]+\]\[['"]PATH['"]\]/ ) {
+    $sub = $options[0];
+    $sub =~ s/\]\[['"]PATH['"]\]//;
+    $sub =~ s/.*\[//;
+    if ( -e "../templates" ) {
+        $options[1] =~ s/^\.\.\/config/\.\.\/templates/;
+    }
+    $templateset_id[$sub] = $options[1];
+##### FIXME: This section ABOVE here so old prefs files don't blow up when running conf.pl
+#####        Remove after a month or two 
+        } elsif ( $options[0] =~ /^aTemplateSet\[[0-9]+\]\[['"]NAME['"]\]/ ) {
             $sub = $options[0];
             $sub =~ s/\]\[['"]NAME['"]\]//;
             $sub =~ s/.*\[//;
             $sub = $options[0];
             $sub =~ s/\]\[['"]NAME['"]\]//;
             $sub =~ s/.*\[//;
-            $theme_name[$sub] = $options[1];
+            $templateset_name[$sub] = $options[1];
         } elsif ( $options[0] =~ /^plugins\[[0-9]*\]/ ) {
             $sub = $options[0];
             $sub =~ s/\]//;
         } elsif ( $options[0] =~ /^plugins\[[0-9]*\]/ ) {
             $sub = $options[0];
             $sub =~ s/\]//;
@@ -197,6 +246,17 @@ while ( $line = <FILE> ) {
             } else {
                $plugins[$sub] = $options[1];
             }
             } else {
                $plugins[$sub] = $options[1];
             }
+        } elsif ($options[0] =~ /^fontsets\[\'[a-z]*\'\]/) {
+            # parse associative $fontsets array
+            $sub = $options[0];
+            $sub =~ s/\'\]//;
+            $sub =~ s/^fontsets\[\'//;
+            $fontsets{$sub} = $options[1];
+        } elsif ( $options[0] =~ /^theme\[[0-9]+\]\[['"]PATH|NAME['"]\]/ ) {
+            ##
+            ## $color themes are no longer supported.  Please leave this
+            ## so conf.pl doesn't barf if it encounters a $theme.
+            ##
         } elsif ( $options[0] =~ /^ldap_server\[[0-9]+\]/ ) {
             $sub = $options[0];
             $sub =~ s/\]//;
         } elsif ( $options[0] =~ /^ldap_server\[[0-9]+\]/ ) {
             $sub = $options[0];
             $sub =~ s/\]//;
@@ -267,6 +327,11 @@ while ( $line = <FILE> ) {
                     $tmp =~ s/[\'\"]?,?\s*$//;
                     $tmp =~ s/[\'\"]?\);\s*$//;
                     $listing = $tmp;
                     $tmp =~ s/[\'\"]?,?\s*$//;
                     $tmp =~ s/[\'\"]?\);\s*$//;
                     $listing = $tmp;
+                } elsif ( $tmp =~ /^\s*[\'\"]writeable[\'\"]/i ) {
+                    $tmp =~ s/^\s*[\'\"]writeable[\'\"]\s*=>\s*[\'\"]?//i;
+                    $tmp =~ s/[\'\"]?,?\s*$//;
+                    $tmp =~ s/[\'\"]?\);\s*$//;
+                    $writeable = $tmp;
                 } elsif ( $tmp =~ /^\s*[\'\"]search_tree[\'\"]/i ) {
                     $tmp =~ s/^\s*[\'\"]search_tree[\'\"]\s*=>\s*[\'\"]?//i;
                     $tmp =~ s/[\'\"]?,?\s*$//;
                 } elsif ( $tmp =~ /^\s*[\'\"]search_tree[\'\"]/i ) {
                     $tmp =~ s/^\s*[\'\"]search_tree[\'\"]\s*=>\s*[\'\"]?//i;
                     $tmp =~ s/[\'\"]?,?\s*$//;
@@ -291,9 +356,10 @@ while ( $line = <FILE> ) {
             $ldap_protocol[$sub] = $protocol;
             $ldap_limit_scope[$sub] = $limit_scope;
             $ldap_listing[$sub] = $listing;
             $ldap_protocol[$sub] = $protocol;
             $ldap_limit_scope[$sub] = $limit_scope;
             $ldap_listing[$sub] = $listing;
+            $ldap_writeable[$sub] = $writeable;
             $ldap_search_tree[$sub] = $search_tree;
             $ldap_starttls[$sub] = $starttls;
             $ldap_search_tree[$sub] = $search_tree;
             $ldap_starttls[$sub] = $starttls;
-        } elsif ( $options[0] =~ /^(data_dir|attachment_dir|theme_css|org_logo|signout_page)$/ ) {
+        } elsif ( $options[0] =~ /^(data_dir|attachment_dir|org_logo|signout_page|icon_theme_def)$/ ) {
             ${ $options[0] } = &change_to_rel_path($options[1]);
         } else {
             ${ $options[0] } = $options[1];
             ${ $options[0] } = &change_to_rel_path($options[1]);
         } else {
             ${ $options[0] } = $options[1];
@@ -302,6 +368,7 @@ while ( $line = <FILE> ) {
 }
 close FILE;
 
 }
 close FILE;
 
+# FIXME: unknown introduction date
 $useSendmail = 'false'                  if ( lc($useSendmail) ne 'true' );
 $sendmail_path = "/usr/sbin/sendmail"   if ( !$sendmail_path );
 $pop_before_smtp = 'false'              if ( !$pop_before_smtp );
 $useSendmail = 'false'                  if ( lc($useSendmail) ne 'true' );
 $sendmail_path = "/usr/sbin/sendmail"   if ( !$sendmail_path );
 $pop_before_smtp = 'false'              if ( !$pop_before_smtp );
@@ -313,39 +380,45 @@ $force_username_lowercase = 'false'     if ( !$force_username_lowercase );
 $optional_delimiter = "detect"          if ( !$optional_delimiter );
 $auto_create_special = 'false'          if ( !$auto_create_special );
 $default_use_priority = 'true'          if ( !$default_use_priority );
 $optional_delimiter = "detect"          if ( !$optional_delimiter );
 $auto_create_special = 'false'          if ( !$auto_create_special );
 $default_use_priority = 'true'          if ( !$default_use_priority );
-$hide_sm_attributions = 'false'         if ( !$hide_sm_attributions );
 $default_use_mdn = 'true'               if ( !$default_use_mdn );
 $delete_folder = 'false'                if ( !$delete_folder );
 $noselect_fix_enable = 'false'          if ( !$noselect_fix_enable );
 $frame_top = "_top"                     if ( !$frame_top );
 $provider_uri = ''                      if ( !$provider_uri );
 $provider_name = ''                     if ( !$provider_name );
 $default_use_mdn = 'true'               if ( !$default_use_mdn );
 $delete_folder = 'false'                if ( !$delete_folder );
 $noselect_fix_enable = 'false'          if ( !$noselect_fix_enable );
 $frame_top = "_top"                     if ( !$frame_top );
 $provider_uri = ''                      if ( !$provider_uri );
 $provider_name = ''                     if ( !$provider_name );
-$edit_identity = 'true'                 if ( !$edit_identity );
-$edit_name = 'true'                     if ( !$edit_name );
-$allow_thread_sort = 'false'            if ( !$allow_thread_sort );
-$allow_server_sort = 'false'            if ( !$allow_server_sort );
 $no_list_for_subscribe = 'false'        if ( !$no_list_for_subscribe );
 $allow_charset_search = 'true'          if ( !$allow_charset_search );
 $allow_advanced_search = 0              if ( !$allow_advanced_search) ;
 $prefs_user_field = 'user'              if ( !$prefs_user_field );
 $prefs_key_field = 'prefkey'            if ( !$prefs_key_field );
 $prefs_val_field = 'prefval'            if ( !$prefs_val_field );
 $no_list_for_subscribe = 'false'        if ( !$no_list_for_subscribe );
 $allow_charset_search = 'true'          if ( !$allow_charset_search );
 $allow_advanced_search = 0              if ( !$allow_advanced_search) ;
 $prefs_user_field = 'user'              if ( !$prefs_user_field );
 $prefs_key_field = 'prefkey'            if ( !$prefs_key_field );
 $prefs_val_field = 'prefval'            if ( !$prefs_val_field );
+$session_name = 'SQMSESSID'             if ( !$session_name );
+$skip_SM_header = 'false'               if ( !$skip_SM_header );
+$default_use_javascript_addr_book = 'false' if (! $default_use_javascript_addr_book);
+
+# since 1.2.0
+$hide_sm_attributions = 'false'         if ( !$hide_sm_attributions );
+# since 1.2.5
+$edit_identity = 'true'                 if ( !$edit_identity );
+$edit_name = 'true'                     if ( !$edit_name );
+
+# since 1.4.0
 $use_smtp_tls= 'false'                  if ( !$use_smtp_tls);
 $smtp_auth_mech = 'none'                if ( !$smtp_auth_mech );
 $use_imap_tls = 'false'                 if ( !$use_imap_tls );
 $imap_auth_mech = 'login'               if ( !$imap_auth_mech );
 $use_smtp_tls= 'false'                  if ( !$use_smtp_tls);
 $smtp_auth_mech = 'none'                if ( !$smtp_auth_mech );
 $use_imap_tls = 'false'                 if ( !$use_imap_tls );
 $imap_auth_mech = 'login'               if ( !$imap_auth_mech );
-$session_name = 'SQMSESSID'             if ( !$session_name );
-$skip_SM_header = 'false'               if ( !$skip_SM_header );
-$default_use_javascript_addr_book = 'false' if (! $default_use_javascript_addr_book);
+
 # since 1.5.0
 $show_alternative_names = 'false'       if ( !$show_alternative_names );
 # $available_languages option available only in 1.5.0. removed due to $languages
 # implementation changes. options are provided by limit_languages plugin
 # $available_languages = 'all'            if ( !$available_languages );
 $aggressive_decoding = 'false'          if ( !$aggressive_decoding );
 # since 1.5.0
 $show_alternative_names = 'false'       if ( !$show_alternative_names );
 # $available_languages option available only in 1.5.0. removed due to $languages
 # implementation changes. options are provided by limit_languages plugin
 # $available_languages = 'all'            if ( !$available_languages );
 $aggressive_decoding = 'false'          if ( !$aggressive_decoding );
-$advanced_tree = 'false'                if ( !$advanced_tree );
+# available only in 1.5.0 and 1.5.1
+# $advanced_tree = 'false'                if ( !$advanced_tree );
 $use_php_recode = 'false'               if ( !$use_php_recode );
 $use_php_iconv = 'false'                if ( !$use_php_iconv );
 $use_php_recode = 'false'               if ( !$use_php_recode );
 $use_php_iconv = 'false'                if ( !$use_php_iconv );
+
 # since 1.5.1
 $use_icons = 'false'                    if ( !$use_icons );
 $use_iframe = 'false'                   if ( !$use_iframe );
 # since 1.5.1
 $use_icons = 'false'                    if ( !$use_icons );
 $use_iframe = 'false'                   if ( !$use_iframe );
@@ -363,13 +436,42 @@ $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 );
 $prefs_user_size = 128                  if ( !$prefs_user_size );
 $prefs_key_size = 64                    if ( !$prefs_key_size );
 $prefs_val_size = 65536                 if ( !$prefs_val_size );
+
 # add qmail-inject test here for backwards compatibility
 # add qmail-inject test here for backwards compatibility
-if ( !$sendmail_args && $sendmail_path =~ /qmail-inject/ ) { 
+if ( !$sendmail_args && $sendmail_path =~ /qmail-inject/ ) {
     $sendmail_args = '';
 } elsif ( !$sendmail_args ) {
     $sendmail_args = '-i -t';
 }
 
     $sendmail_args = '';
 } elsif ( !$sendmail_args ) {
     $sendmail_args = '-i -t';
 }
 
+$default_fontsize = ''                  if ( !$default_fontsize);
+$default_fontset = ''                   if ( !$default_fontset);
+if ( !%fontsets) {
+    %fontsets = ('serif',     'serif',
+                 'sans',      'helvetica,arial,sans-serif',
+                 'comicsans', 'comic sans ms,sans-serif',
+                 'tahoma',    'tahoma,sans-serif',
+                 'verasans',  'bitstream vera sans,verdana,sans-serif');
+}
+
+# $use_imap_tls and $use_smtp_tls are switched to integer since 1.5.1
+$use_imap_tls = 0                      if ( $use_imap_tls eq 'false');
+$use_imap_tls = 1                      if ( $use_imap_tls eq 'true');
+$use_smtp_tls = 0                      if ( $use_smtp_tls eq 'false');
+$use_smtp_tls = 1                      if ( $use_smtp_tls eq 'true');
+# sorting options changed names and reversed values in 1.5.1
+$disable_thread_sort = 'false'         if ( !$disable_thread_sort );
+$disable_server_sort = 'false'         if ( !$disable_server_sort );
+
+# since 1.5.2
+$abook_file_line_length = 2048         if ( !$abook_file_line_length );
+$config_location_base = ''             if ( !$config_location_base );
+$smtp_sitewide_user = ''               if ( !$smtp_sitewide_user );
+$smtp_sitewide_pass = ''               if ( !$smtp_sitewide_pass );
+$icon_theme_def = ''                   if ( !$icon_theme_def );
+$disable_plugins = 'false'             if ( !$disable_plugins );
+$disable_plugins_user = ''             if ( !$disable_plugins_user );
+
 if ( $ARGV[0] eq '--install-plugin' ) {
     print "Activating plugin " . $ARGV[1] . "\n";
     push @plugins, $ARGV[1];
 if ( $ARGV[0] eq '--install-plugin' ) {
     print "Activating plugin " . $ARGV[1] . "\n";
     push @plugins, $ARGV[1];
@@ -385,8 +487,38 @@ if ( $ARGV[0] eq '--install-plugin' ) {
     @plugins = @newplugins;
     save_data();
     exit(0);
     @plugins = @newplugins;
     save_data();
     exit(0);
+} elsif ( $ARGV[0] eq '--update-plugins' or $ARGV[0] eq '-u') {
+    build_plugin_hook_array();
+    exit(0);
+} elsif ( $ARGV[0] eq '--help' or $ARGV[0] eq '-h') {
+    print "SquirrelMail Configuration Script\n";
+    print "Usage:\n";
+    print " * No arguments: initiates the configuration dialog\n";
+    print " * --install-plugin <plugin> : activates the specified plugin\n";
+    print " * --remove-plugin <plugin>  : deactivates the specified plugin\n";
+    print " * --update-plugins , -u     : rebuilds plugin_hooks.php according\n";
+    print "                               to plugins activated in config.php\n";
+    print " * --help , -h               : Displays this help\n";
+    print "\n";
+    exit(0);
 }
 
 }
 
+
+
+####################################################################################
+
+# used in multiple places, define once
+$list_supported_imap_servers = 
+    "    bincimap    = Binc IMAP server\n" .
+    "    courier     = Courier IMAP server\n" .
+    "    cyrus       = Cyrus IMAP server\n" .
+    "    dovecot     = Dovecot Secure IMAP server\n" .
+    "    exchange    = Microsoft Exchange IMAP server\n" .
+    "    hmailserver = hMailServer\n" .
+    "    macosx      = Mac OS X Mailserver\n" .
+    "    mercury32   = Mercury/32\n" .
+    "    uw          = University of Washington's IMAP server\n";
+
 #####################################################################################
 if ( $config_use_color == 1 ) {
     $WHT = "\x1B[37;1m";
 #####################################################################################
 if ( $config_use_color == 1 ) {
     $WHT = "\x1B[37;1m";
@@ -411,7 +543,7 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
         print "2.  Server Settings\n";
         print "3.  Folder Defaults\n";
         print "4.  General Options\n";
         print "2.  Server Settings\n";
         print "3.  Folder Defaults\n";
         print "4.  General Options\n";
-        print "5.  Themes\n";
+        print "5.  User Interface\n";
         print "6.  Address Books\n";
         print "7.  Message of the Day (MOTD)\n";
         print "8.  Plugins\n";
         print "6.  Address Books\n";
         print "7.  Message of the Day (MOTD)\n";
         print "8.  Plugins\n";
@@ -454,7 +586,7 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
           print "4.  IMAP Server            : $WHT$imapServerAddress$NRM\n";
           print "5.  IMAP Port              : $WHT$imapPort$NRM\n";
           print "6.  Authentication type    : $WHT$imap_auth_mech$NRM\n";
           print "4.  IMAP Server            : $WHT$imapServerAddress$NRM\n";
           print "5.  IMAP Port              : $WHT$imapPort$NRM\n";
           print "6.  Authentication type    : $WHT$imap_auth_mech$NRM\n";
-          print "7.  Secure IMAP (TLS)      : $WHT$use_imap_tls$NRM\n";
+          print "7.  Secure IMAP (TLS)      : $WHT" . display_use_tls($use_imap_tls) . "$NRM\n";
           print "8.  Server software        : $WHT$imap_server_type$NRM\n";
           print "9.  Delimiter              : $WHT$optional_delimiter$NRM\n";
           print "\n";
           print "8.  Server software        : $WHT$imap_server_type$NRM\n";
           print "9.  Delimiter              : $WHT$optional_delimiter$NRM\n";
           print "\n";
@@ -470,8 +602,8 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
             print "4.   SMTP Server           : $WHT$smtpServerAddress$NRM\n";
             print "5.   SMTP Port             : $WHT$smtpPort$NRM\n";
             print "6.   POP before SMTP       : $WHT$pop_before_smtp$NRM\n";
             print "4.   SMTP Server           : $WHT$smtpServerAddress$NRM\n";
             print "5.   SMTP Port             : $WHT$smtpPort$NRM\n";
             print "6.   POP before SMTP       : $WHT$pop_before_smtp$NRM\n";
-            print "7.   SMTP Authentication   : $WHT$smtp_auth_mech$NRM\n";
-            print "8.   Secure SMTP (TLS)     : $WHT$use_smtp_tls$NRM\n";
+            print "7.   SMTP Authentication   : $WHT$smtp_auth_mech" . display_smtp_sitewide_userpass() ."$NRM\n";
+            print "8.   Secure SMTP (TLS)     : $WHT" . display_use_tls($use_smtp_tls) . "$NRM\n";
             print "9.   Header encryption key : $WHT$encode_header_key$NRM\n";
             print "\n";
           }
             print "9.   Header encryption key : $WHT$encode_header_key$NRM\n";
             print "\n";
           }
@@ -536,24 +668,25 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
         print "9.  Allow editing of identity   : $WHT$edit_identity$NRM\n";
         print "    Allow editing of name       : $WHT$edit_name$NRM\n";
         print "    Remove username from header : $WHT$hide_auth_header$NRM\n";
         print "9.  Allow editing of identity   : $WHT$edit_identity$NRM\n";
         print "    Allow editing of name       : $WHT$edit_name$NRM\n";
         print "    Remove username from header : $WHT$hide_auth_header$NRM\n";
-        print "10. Allow server thread sort    : $WHT$allow_thread_sort$NRM\n";
-        print "11. Allow server-side sorting   : $WHT$allow_server_sort$NRM\n";
+        print "10. Disable server thread sort  : $WHT$disable_thread_sort$NRM\n";
+        print "11. Disable server-side sorting : $WHT$disable_server_sort$NRM\n";
         print "12. Allow server charset search : $WHT$allow_charset_search$NRM\n";
         print "13. Allow advanced search       : $WHT$allow_advanced_search$NRM\n";
         print "14. PHP session name            : $WHT$session_name$NRM\n";
         print "15. Time zone configuration     : $WHT$time_zone_type$NRM\n";
         print "12. Allow server charset search : $WHT$allow_charset_search$NRM\n";
         print "13. Allow advanced search       : $WHT$allow_advanced_search$NRM\n";
         print "14. PHP session name            : $WHT$session_name$NRM\n";
         print "15. Time zone configuration     : $WHT$time_zone_type$NRM\n";
+        print "16. Location base               : $WHT$config_location_base$NRM\n";
         print "\n";
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 5 ) {
         print "\n";
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 5 ) {
-        print $WHT. "Themes\n" . $NRM;
-        print "1.  Change Themes\n";
-        for ( $count = 0 ; $count <= $#theme_name/2 ; $count++ ) {
-            $temp_name = $theme_name[$count*2];
-            printf "     %s%*s    %s\n", $temp_name,
-                   40 - length($temp_name), " ",
-                   $theme_name[($count*2)+1];
-        }
-        print "2.  CSS File : $WHT$theme_css$NRM\n";
+        print $WHT. "User Interface\n" . $NRM;
+        print "1.  Use Icons?                   : $WHT$use_icons$NRM\n";
+#        print "3.  Default Icon Set             : $WHT$icon_theme_def$NRM\n";
+        print "2.  Default font size            : $WHT$default_fontsize$NRM\n";
+        print "3.  Manage template sets\n";
+        print "4.  Manage user themes\n";
+        print "5.  Manage font sets\n";
+        print "6.  Manage icon themes\n";
+
         print "\n";
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 6 ) {
         print "\n";
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 6 ) {
@@ -566,6 +699,7 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
         print "3.  Global address book file                    : $WHT$abook_global_file$NRM\n";
         print "4.  Allow writing into global file address book : $WHT$abook_global_file_writeable$NRM\n";
         print "5.  Allow listing of global file address book   : $WHT$abook_global_file_listing$NRM\n";
         print "3.  Global address book file                    : $WHT$abook_global_file$NRM\n";
         print "4.  Allow writing into global file address book : $WHT$abook_global_file_writeable$NRM\n";
         print "5.  Allow listing of global file address book   : $WHT$abook_global_file_listing$NRM\n";
+        print "6.  Allowed address book line length            : $WHT$abook_file_line_length$NRM\n";
         print "\n";
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 7 ) {
         print "\n";
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 7 ) {
@@ -576,7 +710,13 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
         print "\n";
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 8 ) {
         print "\n";
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 8 ) {
-        print $WHT. "Plugins\n" . $NRM;
+        if (lc($disable_plugins) eq 'true' && $disable_plugins_user ne '') {
+            print $WHT. "Plugins (WARNING: All plugins are currently disabled\n                  for the user \"$disable_plugins_user\"!)\n" . $NRM;
+        } elsif (lc($disable_plugins) eq 'true') {
+            print $WHT. "Plugins (WARNING: All plugins are currently disabled!)\n" . $NRM;
+        } else {
+            print $WHT. "Plugins\n" . $NRM;
+        }
         print "  Installed Plugins\n";
         $num = 0;
         for ( $count = 0 ; $count <= $#plugins ; $count++ ) {
         print "  Installed Plugins\n";
         $num = 0;
         for ( $count = 0 ; $count <= $#plugins ; $count++ ) {
@@ -610,6 +750,14 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
         closedir DIR;
 
         print "\n";
         closedir DIR;
 
         print "\n";
+        if (lc($disable_plugins) eq 'true' && $disable_plugins_user ne '') {
+            print "E   Enable active plugins (all plugins currently\n    disabled for the user \"$disable_plugins_user\")\n";
+        } elsif (lc($disable_plugins) eq 'true') {
+            print "E   Enable active plugins (all plugins currently\n    disabled)\n";
+        } else {
+            print "D   Disable all plugins\n";
+        }
+        print "U   Set the user for whom plugins can be disabled\n";
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 9 ) {
         print $WHT. "Database\n" . $NRM;
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 9 ) {
         print $WHT. "Database\n" . $NRM;
@@ -639,9 +787,7 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 11 ) {
     print $WHT. "Interface tweaks\n" . $NRM;
         print "R   Return to Main Menu\n";
     } elsif ( $menu == 11 ) {
     print $WHT. "Interface tweaks\n" . $NRM;
-    print "1.  Advanced tree                : $WHT$advanced_tree$NRM\n";
-    print "2.  Display html mails in iframe : $WHT$use_iframe$NRM\n";
-    print "3.  Use Icons                    : $WHT$use_icons$NRM\n";
+    print "1.  Display html mails in iframe : $WHT$use_iframe$NRM\n";
     print "\n";
     print $WHT. "PHP tweaks\n" . $NRM;
     print "4.  Use php recode functions     : $WHT$use_php_recode$NRM\n";
     print "\n";
     print $WHT. "PHP tweaks\n" . $NRM;
     print "4.  Use php recode functions     : $WHT$use_php_recode$NRM\n";
@@ -723,7 +869,7 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
               if    ( $command == 4 )  { $imapServerAddress      = command12(); }
               elsif ( $command == 5 )  { $imapPort               = command13(); }
               elsif ( $command == 6 )  { $imap_auth_mech     = command112a(); }
               if    ( $command == 4 )  { $imapServerAddress      = command12(); }
               elsif ( $command == 5 )  { $imapPort               = command13(); }
               elsif ( $command == 6 )  { $imap_auth_mech     = command112a(); }
-              elsif ( $command == 7 )  { $use_imap_tls       = command113("IMAP",$use_imap_tls); }
+              elsif ( $command == 7 )  { $use_imap_tls       = command_use_tls("IMAP",$use_imap_tls); }
               elsif ( $command == 8 )  { $imap_server_type       = command19(); }
               elsif ( $command == 9 )  { $optional_delimiter     = command111(); }
             } elsif ( $show_smtp_settings && lc($useSendmail) eq 'true' ) {
               elsif ( $command == 8 )  { $imap_server_type       = command19(); }
               elsif ( $command == 9 )  { $optional_delimiter     = command111(); }
             } elsif ( $show_smtp_settings && lc($useSendmail) eq 'true' ) {
@@ -735,7 +881,7 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
               elsif ( $command == 5 )  { $smtpPort               = command17(); }
               elsif ( $command == 6 )  { $pop_before_smtp        = command18a(); }
               elsif ( $command == 7 )  { $smtp_auth_mech    = command112b(); }
               elsif ( $command == 5 )  { $smtpPort               = command17(); }
               elsif ( $command == 6 )  { $pop_before_smtp        = command18a(); }
               elsif ( $command == 7 )  { $smtp_auth_mech    = command112b(); }
-              elsif ( $command == 8 )  { $use_smtp_tls      = command113("SMTP",$use_smtp_tls); }
+              elsif ( $command == 8 )  { $use_smtp_tls      = command_use_tls("SMTP",$use_smtp_tls); }
               elsif ( $command == 9 )  { $encode_header_key      = command114(); }
             }
         } elsif ( $menu == 3 ) {
               elsif ( $command == 9 )  { $encode_header_key      = command114(); }
             }
         } elsif ( $menu == 3 ) {
@@ -767,25 +913,35 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
             elsif ( $command == 7 )  { $hide_sm_attributions     = command38(); }
             elsif ( $command == 8 )  { $default_use_mdn          = command39(); }
             elsif ( $command == 9 )  { $edit_identity            = command310(); }
             elsif ( $command == 7 )  { $hide_sm_attributions     = command38(); }
             elsif ( $command == 8 )  { $default_use_mdn          = command39(); }
             elsif ( $command == 9 )  { $edit_identity            = command310(); }
-            elsif ( $command == 10 ) { $allow_thread_sort        = command312(); }
-            elsif ( $command == 11 ) { $allow_server_sort        = command313(); }
+            elsif ( $command == 10 ) { $disable_thread_sort     = command312(); }
+            elsif ( $command == 11 ) { $disable_server_sort     = command313(); }
             elsif ( $command == 12 ) { $allow_charset_search     = command314(); }
             elsif ( $command == 13 ) { $allow_advanced_search    = command316(); }
             elsif ( $command == 14 ) { $session_name             = command317(); }
             elsif ( $command == 15 ) { $time_zone_type           = command318(); }
             elsif ( $command == 12 ) { $allow_charset_search     = command314(); }
             elsif ( $command == 13 ) { $allow_advanced_search    = command316(); }
             elsif ( $command == 14 ) { $session_name             = command317(); }
             elsif ( $command == 15 ) { $time_zone_type           = command318(); }
+            elsif ( $command == 16 ) { $config_location_base     = command_config_location_base(); }
         } elsif ( $menu == 5 ) {
         } elsif ( $menu == 5 ) {
-            if ( $command == 1 ) { command41(); }
-            elsif ( $command == 2 ) { $theme_css = command42(); }
+            if ( $command == 1 )     { $use_icons      = commandB3(); }
+#            elsif ( $command == 3 )  { $icon_theme_def = commandB7(); }
+            elsif ( $command == 2 )  { $default_fontsize = command_default_fontsize(); }
+            elsif ( $command == 3 )  { $templateset_default = command_templates(); }
+            elsif ( $command == 4 )  { command_userThemes(); }
+            elsif ( $command == 5 )  { command_fontsets(); }
+            elsif ( $command == 6 )  { command_iconSets(); }
         } elsif ( $menu == 6 ) {
             if    ( $command == 1 ) { command61(); }
             elsif ( $command == 2 ) { command62(); }
             elsif ( $command == 3 ) { $abook_global_file=command63(); }
             elsif ( $command == 4 ) { command64(); }
             elsif ( $command == 5 ) { command65(); }
         } elsif ( $menu == 6 ) {
             if    ( $command == 1 ) { command61(); }
             elsif ( $command == 2 ) { command62(); }
             elsif ( $command == 3 ) { $abook_global_file=command63(); }
             elsif ( $command == 4 ) { command64(); }
             elsif ( $command == 5 ) { command65(); }
+            elsif ( $command == 6 ) { command_abook_file_line_length(); }
         } elsif ( $menu == 7 ) {
             if ( $command == 1 ) { $motd = command71(); }
         } elsif ( $menu == 8 ) {
         } elsif ( $menu == 7 ) {
             if ( $command == 1 ) { $motd = command71(); }
         } elsif ( $menu == 8 ) {
-            if ( $command =~ /^[0-9]+/ ) { @plugins = command81(); }
+            if    ( $command =~ /^[0-9]+/ ) { @plugins              = command81(); }
+            elsif ( $command eq "u" )       { $disable_plugins_user = command82(); }
+            elsif ( $command eq "d" )       { $disable_plugins      = 'true'; }
+            elsif ( $command eq "e" )       { $disable_plugins      = 'false'; }
         } elsif ( $menu == 9 ) {
             if    ( $command == 1 ) { $addrbook_dsn     = command91(); }
             elsif ( $command == 2 ) { $addrbook_table   = command92(); }
         } elsif ( $menu == 9 ) {
             if    ( $command == 1 ) { $addrbook_dsn     = command91(); }
             elsif ( $command == 2 ) { $addrbook_table   = command92(); }
@@ -805,9 +961,7 @@ while ( ( $command ne "q" ) && ( $command ne "Q" ) && ( $command ne ":q" ) ) {
             elsif ( $command == 4 ) { $aggressive_decoding           = commandA4(); }
             elsif ( $command == 5 ) { $lossy_encoding                = commandA5(); }
         } elsif ( $menu == 11 ) {
             elsif ( $command == 4 ) { $aggressive_decoding           = commandA4(); }
             elsif ( $command == 5 ) { $lossy_encoding                = commandA5(); }
         } elsif ( $menu == 11 ) {
-            if    ( $command == 1 ) { $advanced_tree  = commandB1(); }
-            if    ( $command == 2 ) { $use_iframe     = commandB2(); }
-            elsif ( $command == 3 ) { $use_icons      = commandB3(); }
+            if    ( $command == 1 ) { $use_iframe     = commandB2(); }
             elsif ( $command == 4 ) { $use_php_recode = commandB4(); }
             elsif ( $command == 5 ) { $use_php_iconv  = commandB5(); }
             elsif ( $command == 6 ) { $allow_remote_configtest = commandB6(); }
             elsif ( $command == 4 ) { $use_php_recode = commandB4(); }
             elsif ( $command == 5 ) { $use_php_iconv  = commandB5(); }
             elsif ( $command == 6 ) { $allow_remote_configtest = commandB6(); }
@@ -901,8 +1055,6 @@ sub command3 {
     print "If your Organization Title includes a '\$', please precede it with a \\. \n";
     print "Other '\$' will be considered the beginning of a variable that\n";
     print "must be defined before the \$org_title is printed.\n";
     print "If your Organization Title includes a '\$', please precede it with a \\. \n";
     print "Other '\$' will be considered the beginning of a variable that\n";
     print "must be defined before the \$org_title is printed.\n";
-    print "\$version, for example can be used, and will print the\n";
-    print "string representing the current SquirrelMail version.\n";
     print "\n";
     print "[$WHT$org_title$NRM]: $WHT";
     $new_org_title = <STDIN>;
     print "\n";
     print "[$WHT$org_title$NRM]: $WHT";
     $new_org_title = <STDIN>;
@@ -968,7 +1120,7 @@ sub command7 {
 
 sub command8 {
     print "Here you can set the name of the link on the right of the page.\n";
 
 sub command8 {
     print "Here you can set the name of the link on the right of the page.\n";
-    print "The default is 'SquirrelMail/'\n";
+    print "The default is 'SquirrelMail'\n";
     print "\n";
     print "[$WHT$provider_name$NRM]: $WHT";
     $new_provider_name = <STDIN>;
     print "\n";
     print "[$WHT$provider_name$NRM]: $WHT";
     $new_provider_name = <STDIN>;
@@ -977,6 +1129,7 @@ sub command8 {
     } else {
         $new_provider_name =~ s/[\r\n]//g;
         $new_provider_name =~ s/^\s+$//g;
     } else {
         $new_provider_name =~ s/[\r\n]//g;
         $new_provider_name =~ s/^\s+$//g;
+        $new_provider_name =~ s/\'/\\'/g;
     }
     return $new_provider_name;
 }
     }
     return $new_provider_name;
 }
@@ -994,7 +1147,7 @@ sub command11 {
     if ( $new_domain eq "\n" ) {
         $new_domain = $domain;
     } else {
     if ( $new_domain eq "\n" ) {
         $new_domain = $domain;
     } else {
-        $new_domain =~ s/[\r\n]//g;
+        $new_domain =~ s/\s//g;
     }
     return $new_domain;
 }
     }
     return $new_domain;
 }
@@ -1051,10 +1204,6 @@ sub command14 {
 
 # sendmail_path
 sub command15 {
 
 # sendmail_path
 sub command15 {
-    # TODO: fix check
-    if ( $sendmail_path[0] !~ /./ ) {
-        $sendmail_path = "/usr/sbin/sendmail";
-    }
     print "Specify where the sendmail executable is located.  Usually /usr/sbin/sendmail\n";
     print "[$WHT$sendmail_path$NRM]: $WHT";
     $new_sendmail_path = <STDIN>;
     print "Specify where the sendmail executable is located.  Usually /usr/sbin/sendmail\n";
     print "[$WHT$sendmail_path$NRM]: $WHT";
     $new_sendmail_path = <STDIN>;
@@ -1074,7 +1223,7 @@ sub command_sendmail_args {
     print "is added automatically by SquirrelMail scripts. Variable defaults to standard\n";
     print "/usr/sbin/sendmail arguments. If you use qmail-inject, nbsmtp or any other \n";
     print "sendmail wrapper, which does not support -i and -t arguments, set variable to\n";
     print "is added automatically by SquirrelMail scripts. Variable defaults to standard\n";
     print "/usr/sbin/sendmail arguments. If you use qmail-inject, nbsmtp or any other \n";
     print "sendmail wrapper, which does not support -i and -t arguments, set variable to\n";
-    print "empty string or use arguments suitable for your mailer.\n"; 
+    print "empty string or use arguments suitable for your mailer.\n";
     print "\n";
     print "[$WHT$sendmail_args$NRM]: $WHT";
     $new_sendmail_args = <STDIN>;
     print "\n";
     print "[$WHT$sendmail_args$NRM]: $WHT";
     $new_sendmail_args = <STDIN>;
@@ -1113,26 +1262,6 @@ sub command17 {
     return $new_smtpPort;
 }
 
     return $new_smtpPort;
 }
 
-# authenticated server
-sub command18 {
-    return;
-    # This sub disabled by tassium - it has been replaced with smtp_auth_mech
-    print "Do you wish to use an authenticated SMTP server?  Your server must\n";
-    print "support this in order for SquirrelMail to work with it.  We implemented\n";
-    print "it according to RFC 2554.\n";
-
-    $YesNo = 'n';
-    $YesNo = 'y' if ( lc($use_authenticated_smtp) eq 'true' );
-
-    print "Use authenticated SMTP server (y/n) [$WHT$YesNo$NRM]: $WHT";
-
-    $new_use_authenticated_smtp = <STDIN>;
-    $new_use_authenticated_smtp =~ tr/yn//cd;
-    return 'true'  if ( $new_use_authenticated_smtp eq "y" );
-    return 'false' if ( $new_use_authenticated_smtp eq "n" );
-    return $use_authenticated_smtp;
-}
-
 # pop before SMTP
 sub command18a {
     print "Do you wish to use POP3 before SMTP?  Your server must\n";
 # pop before SMTP
 sub command18a {
     print "Do you wish to use POP3 before SMTP?  Your server must\n";
@@ -1158,14 +1287,7 @@ sub command19 {
     print "these servers.  If you would like to use them, please select your\n";
     print "IMAP server.  If you do not wish to use these work-arounds, you can\n";
     print "set this to \"other\", and none will be used.\n";
     print "these servers.  If you would like to use them, please select your\n";
     print "IMAP server.  If you do not wish to use these work-arounds, you can\n";
     print "set this to \"other\", and none will be used.\n";
-    print "    courier     = Courier IMAP server\n";
-    print "    cyrus       = Cyrus IMAP server\n";
-    print "    dovecot     = Dovecot Secure IMAP server\n";
-    print "    exchange    = Microsoft Exchange IMAP server\n";
-    print "    hmailserver = hMailServer\n";
-    print "    macosx      = Mac OS X Mailserver\n";
-    print "    mercury32   = Mercury Mail Transport System\n";
-    print "    uw          = University of Washington's IMAP server\n";
+    print $list_supported_imap_servers;
     print "\n";
     print "    other       = Not one of the above servers\n";
     print "\n";
     print "\n";
     print "    other       = Not one of the above servers\n";
     print "\n";
@@ -1226,8 +1348,11 @@ sub command111 {
 # Now offers to detect supported mechs, assuming server & port are set correctly
 
 sub command112a {
 # Now offers to detect supported mechs, assuming server & port are set correctly
 
 sub command112a {
-    if ($use_imap_tls =~ /^true\b/i) {
-        print "Auto-detection of login methods is unavailable when using TLS.\n";
+    if ($use_imap_tls ne "0") {
+        # 1. Script does not handle TLS.
+        # 2. Server does not have to declare all supported authentication mechs when 
+        #    STARTTLS is used. Supported mechs are declared only after STARTTLS.
+        print "Auto-detection of login methods is unavailable when using TLS or STARTTLS.\n";
     } else {
         print "If you have already set the hostname and port number, I can try to\n";
         print "detect the mechanisms your IMAP server supports.\n";
     } else {
         print "If you have already set the hostname and port number, I can try to\n";
         print "detect the mechanisms your IMAP server supports.\n";
@@ -1289,9 +1414,10 @@ sub command112a {
 # SMTP authentication type
 # Possible choices: none, plain, cram-md5, digest-md5
 sub command112b {
 # SMTP authentication type
 # Possible choices: none, plain, cram-md5, digest-md5
 sub command112b {
-    if ($use_smtp_tls =~ /^true\b/i) {
-        print "Auto-detection of login methods is unavailable when using TLS.\n";
-    } else {
+    if ($use_smtp_tls ne "0") {
+        print "Auto-detection of login methods is unavailable when using TLS or STARTTLS.\n";
+    } elsif (eval ("use IO::Socket; 1")) {
+        # try loading IO::Socket module
         print "If you have already set the hostname and port number, I can try to\n";
         print "automatically detect some of the mechanisms your SMTP server supports.\n";
         print "Auto-detection is *optional* - you can safely say \"n\" here.\n";
         print "If you have already set the hostname and port number, I can try to\n";
         print "automatically detect some of the mechanisms your SMTP server supports.\n";
         print "Auto-detection is *optional* - you can safely say \"n\" here.\n";
@@ -1305,7 +1431,6 @@ sub command112b {
             # Special case!
             # Check none by trying to relay to junk@microsoft.com
             $host = $smtpServerAddress . ':' . $smtpPort;
             # Special case!
             # Check none by trying to relay to junk@microsoft.com
             $host = $smtpServerAddress . ':' . $smtpPort;
-            use IO::Socket;
             my $sock = IO::Socket::INET->new($host);
             print "Testing none:\t\t$WHT";
             if (!defined($sock)) {
             my $sock = IO::Socket::INET->new($host);
             print "Testing none:\t\t$WHT";
             if (!defined($sock)) {
@@ -1379,45 +1504,140 @@ sub command112b {
     $inval=<STDIN>;
     chomp($inval);
     if ($inval =~ /^none\b/i) {
     $inval=<STDIN>;
     chomp($inval);
     if ($inval =~ /^none\b/i) {
-      # SMTP doesn't necessarily require logins
-      return "none";
+        # remove sitewide smtp authentication information
+        $smtp_sitewide_user = '';
+        $smtp_sitewide_pass = '';
+        # SMTP doesn't necessarily require logins
+        return "none";
+    } elsif ( ($inval =~ /^cram-md5\b/i) || ($inval =~ /^digest-md5\b/i) ||
+              ($inval =~ /^login\b/i) || ($inval =~/^plain\b/i)) {
+        command_smtp_sitewide_userpass($inval);
+        return lc($inval);
+    } elsif (trim($inval) eq '') {
+        # user selected default value
+        command_smtp_sitewide_userpass($smtp_auth_mech);
+        return $smtp_auth_mech;
+    } else {
+        # user entered garbage 
+        return $smtp_auth_mech;
     }
     }
-    if ( ($inval =~ /^cram-md5\b/i) || ($inval =~ /^digest-md5\b/i) ||
-    ($inval =~ /^login\b/i) || ($inval =~/^plain\b/i)) {
-      return lc($inval);
+}
+
+sub command_smtp_sitewide_userpass($) {
+    # get first function argument
+    my $auth_mech = shift(@_);
+    my $default, $tmp;
+    $auth_mech = lc(trim($auth_mech));
+    if ($auth_mech eq 'none') {
+        return;
+    }
+    print "SMTP authentication uses IMAP username and password by default.\n";
+    print "\n";
+    print "Would you like to use other login and password for all SquirrelMail \n";
+    print "SMTP connections?";
+    if ($smtp_sitewide_user ne '') {
+        $default = 'y';
+        print " [Yn]:";
+    } else {
+        $default = 'n';
+        print " [yN]:";
+    }
+    $tmp=<STDIN>;
+    $tmp = trim($tmp);
+    
+    if ($tmp eq '') {
+        $tmp = $default;
+    } else {
+        $tmp = lc($tmp);
+    }
+
+    if ($tmp eq 'n') {
+        $smtp_sitewide_user = '';
+        $smtp_sitewide_pass = '';
+    } elsif ($tmp eq 'y') {
+        print "Enter username [$smtp_sitewide_user]:";
+        my $new_user = <STDIN>;
+        $new_user = trim($new_user);
+        if ($new_user ne '') {
+            $smtp_sitewide_user = $new_user;
+        }
+        if ($smtp_sitewide_user ne '') {
+            print "If you don't enter any password, current sitewide password will be used.\n";
+            print "If you enter space, password will be set to empty string.\n";
+            print "Enter password:";
+            my $new_pass = <STDIN>;
+            if ($new_pass ne "\n") {
+                $smtp_sitewide_pass = trim($new_pass);
+            }
+        } else {
+            print "Invalid input. You must set username used for SMTP authentication.\n";
+            print "Click enter to continue\n";
+            $tmp = <STDIN>;
+        }
     } else {
     } else {
-      # user entered garbage, or default value so nothing needs to be set
-      return $smtp_auth_mech;
+        print "Invalid input\n";
+        print "Click enter to continue\n";
+        $tmp = <STDIN>;
+    }
+}
+
+# Sub adds information about SMTP authentication type to menu
+sub display_smtp_sitewide_userpass() {
+    my $ret = '';
+    if ($smtp_auth_mech ne 'none') {
+        if ($smtp_sitewide_user ne '') {
+            $ret = ' (with custom username and password)';
+        } else {
+            $ret = ' (with IMAP username and password)';
+        }
     }
     }
+    return $ret;
 }
 
 # TLS
 # This sub is reused for IMAP and SMTP
 # Args: service name, default value
 }
 
 # TLS
 # This sub is reused for IMAP and SMTP
 # Args: service name, default value
-sub command113 {
+sub command_use_tls {
     my($default_val,$service,$inval);
     $service=$_[0];
     $default_val=$_[1];
     print "TLS (Transport Layer Security) encrypts the traffic between server and client.\n";
     my($default_val,$service,$inval);
     $service=$_[0];
     $default_val=$_[1];
     print "TLS (Transport Layer Security) encrypts the traffic between server and client.\n";
-    print "If you're familiar with SSL, you get the idea.\n";
-    print "To use this feature, your " . $service . " server must offer TLS\n";
-    print "capability, plus PHP 4.3.x with OpenSSL support.\n";
-    print "\nIf your " . $service . " server is localhost, you can safely disable this.\n";
+    print "STARTTLS extensions allow to start encryption on existing plain text connection.\n";
+    print "These options add specific PHP and IMAP server configuration requirements.\n";
+    print "See SquirrelMail documentation about connection security.\n";
+    print "\n";
+    print "If your " . $service . " server is localhost, you can safely disable this.\n";
     print "If it is remote, you may wish to seriously consider enabling this.\n";
     print "If it is remote, you may wish to seriously consider enabling this.\n";
-    print "Enable TLS (y/n) [$WHT";
-    if ($default_val eq 'true') {
-      print "y";
-    } else {
-      print "n";
+    $valid_input=0;
+    while ($valid_input eq 0) {
+        print "\nSelect connection security model:\n";
+        print " 0 - Use plain text connection\n";
+        print " 1 - Use TLS connection\n";
+        print " 2 - Use STARTTLS extension\n";
+        print "Select [$default_val]: ";
+        $inval=<STDIN>;
+        $inval=trim($inval);
+        if ($inval =~ /^[012]$/ || $inval eq '') {
+            $valid_input = 1;
+        }
     }
     }
-    print "$NRM]: $WHT";
-    $inval=<STDIN>;
-    $inval =~ tr/yn//cd;
-    return 'true'  if ( $inval eq "y" );
-    return 'false' if ( $inval eq "n" );
+    if ($inval ne '') {$default_val = $inval};
     return $default_val;
 }
 
     return $default_val;
 }
 
+# This sub is used to display human readable text for 
+# $use_imap_tls and $use_smtp_tls values in conf.pl menu
+sub display_use_tls($) {
+    my $val = shift(@_);
+    my $ret = 'disabled';
+    if ($val eq '2') {
+        $ret = 'STARTTLS';
+    } elsif ($val eq '1') {
+        $ret = 'TLS';
+    }
+    return $ret;
+}
+
 # $encode_header_key
 sub command114{
     print "Encryption key allows to hide SquirrelMail Received: headers\n";
 # $encode_header_key
 sub command114{
     print "Encryption key allows to hide SquirrelMail Received: headers\n";
@@ -1498,6 +1718,25 @@ sub command81 {
     return @plugins;
 }
 
     return @plugins;
 }
 
+# disable_plugins_user
+sub command82 {
+    print "When all active plugins are disabled, they can be disabled only\n";
+    print "for the one user named here.  If left blank, plugins will be\n";
+    print "disabled for ALL users.  This setting has no effect if plugins\n";
+    print "are not disabled.\n";
+    print "\n";
+    print "This must be the exact IMAP login name for the desired user.\n";
+    print "\n";
+    print "[$WHT$disable_plugins_user$NRM]: $WHT";
+    $new_disable_plugins_user = <STDIN>;
+    if ( $new_disable_plugins_user eq "\n" ) {
+        $new_disable_plugins_user = $disable_plugins_user;
+    } else {
+        $new_disable_plugins_user =~ s/[\r\n]//g;
+    }
+    return $new_disable_plugins_user;
+}
+
 ################# FOLDERS ###################
 
 # default_folder_prefix
 ################# FOLDERS ###################
 
 # default_folder_prefix
@@ -1582,7 +1821,11 @@ sub command23a {
     if ( $new_trash_folder eq "\n" ) {
         $new_trash_folder = $trash_folder;
     } else {
     if ( $new_trash_folder eq "\n" ) {
         $new_trash_folder = $trash_folder;
     } else {
-        $new_trash_folder =~ s/[\r\n]//g;
+        if (check_imap_folder($new_trash_folder)) {
+            $new_trash_folder =~ s/[\r\n]//g;
+        } else {
+            $new_trash_folder = $trash_folder;
+        }
     }
     return $new_trash_folder;
 }
     }
     return $new_trash_folder;
 }
@@ -1603,7 +1846,11 @@ sub command23b {
     if ( $new_sent_folder eq "\n" ) {
         $new_sent_folder = $sent_folder;
     } else {
     if ( $new_sent_folder eq "\n" ) {
         $new_sent_folder = $sent_folder;
     } else {
-        $new_sent_folder =~ s/[\r\n]//g;
+        if (check_imap_folder($new_sent_folder)) {
+            $new_sent_folder =~ s/[\r\n]//g;
+        } else {
+            $new_sent_folder = $sent_folder;
+        }
     }
     return $new_sent_folder;
 }
     }
     return $new_sent_folder;
 }
@@ -1625,7 +1872,11 @@ sub command23c {
     if ( $new_draft_folder eq "\n" ) {
         $new_draft_folder = $draft_folder;
     } else {
     if ( $new_draft_folder eq "\n" ) {
         $new_draft_folder = $draft_folder;
     } else {
-        $new_draft_folder =~ s/[\r\n]//g;
+        if (check_imap_folder($new_draft_folder)) {
+            $new_draft_folder =~ s/[\r\n]//g;
+        } else {
+            $new_draft_folder = $draft_folder;
+        }
     }
     return $new_draft_folder;
 }
     }
     return $new_draft_folder;
 }
@@ -1891,7 +2142,7 @@ sub command215 {
         print "Deleting folders will bypass the trash folder and be immediately deleted\n\n";
         print "If this is not the correct value for your server,\n";
         print "please use option D on the Main Menu to configure your server correctly.\n\n";
         print "Deleting folders will bypass the trash folder and be immediately deleted\n\n";
         print "If this is not the correct value for your server,\n";
         print "please use option D on the Main Menu to configure your server correctly.\n\n";
-        print "Press any key to continue...\n";
+        print "Press enter to continue...\n";
         $new_delete = <STDIN>;
         $delete_folder = 'true';
     } else {
         $new_delete = <STDIN>;
         $delete_folder = 'true';
     } else {
@@ -2150,14 +2401,14 @@ sub command39 {
 
 
 sub command310 {
 
 
 sub command310 {
-    print "  In loosely managed environments, you may want to allow users 
-  to edit their full name and email address. In strictly managed 
+    print "  In loosely managed environments, you may want to allow users
+  to edit their full name and email address. In strictly managed
   environments, you may want to force users to use the name
   and email address assigned to them.
   environments, you may want to force users to use the name
   and email address assigned to them.
-  
+
   'y' - allow a user to edit their full name and email address,
   'n' - users must use the assigned values.
   'y' - allow a user to edit their full name and email address,
   'n' - users must use the assigned values.
-  
+
   ";
 
     if ( lc($edit_identity) eq 'true' ) {
   ";
 
     if ( lc($edit_identity) eq 'true' ) {
@@ -2180,9 +2431,9 @@ sub command310 {
 }
 
 sub command311 {
 }
 
 sub command311 {
-    print "  Given that users are not allowed to modify their 
+    print "  Given that users are not allowed to modify their
   email address, can they edit their full name?
   email address, can they edit their full name?
-  
+
   ";
 
     if ( lc($edit_name) eq 'true' ) {
   ";
 
     if ( lc($edit_name) eq 'true' ) {
@@ -2202,18 +2453,18 @@ sub command311 {
 
 sub command311b {
     print "  SquirrelMail adds username information to every sent email
 
 sub command311b {
     print "  SquirrelMail adds username information to every sent email
-  in order to prevent possible sender forging when users are allowed 
+  in order to prevent possible sender forging when users are allowed
   to change their email and/or full name.
 
   to change their email and/or full name.
 
-  You can remove user information from this header (y), if you think that 
-  it violates privacy or security. 
-  
-  Note: If users are allowed to change their email addresses, 
+  You can remove user information from this header (y), if you think that
+  it violates privacy or security.
+
+  Note: If users are allowed to change their email addresses,
   this setting will make it difficult to determine who sent what where.
   Use at your own risk.
   this setting will make it difficult to determine who sent what where.
   Use at your own risk.
-  
+
   ";
   ";
-    
+
     if ( lc($hide_auth_header) eq "true" ) {
         $default_value = "y";
     } else {
     if ( lc($hide_auth_header) eq "true" ) {
         $default_value = "y";
     } else {
@@ -2230,44 +2481,51 @@ sub command311b {
 }
 
 sub command312 {
 }
 
 sub command312 {
-    print "This option allows you to choose if users can use thread sorting\n";
-    print "Your IMAP server must support the THREAD command for this to work\n";
-    print "PHP versions later than 4.0.3 recommended\n";
+    print "This option allows you to disable server side thread sorting if your server \n";
+    print "declares THREAD support, but you don't want to provide threading options \n";
+    print "to end users or THREAD extension is broken or extension does not work with \n";
+    print "options used by SquirrelMail. Option is not used, if THREAD extension is \n";
+    print "not declared in IMAP CAPABILITY.\n";
     print "\n";
 
     print "\n";
 
-    if ( lc($allow_thread_sort) eq 'true' ) {
+    if ( lc($disable_thread_sort) eq 'true' ) {
         $default_value = "y";
     } else {
         $default_value = "n";
     }
         $default_value = "y";
     } else {
         $default_value = "n";
     }
-    print "Allow server side thread sorting? (y/n) [$WHT$default_value$NRM]: $WHT";
-    $allow_thread_sort = <STDIN>;
-    if ( ( $allow_thread_sort =~ /^y\n/i ) || ( ( $allow_thread_sort =~ /^\n/ ) && ( $default_value eq "y" ) ) ) {
-        $allow_thread_sort = 'true';
+    print "Disable server side thread sorting? (y/n) [$WHT$default_value$NRM]: $WHT";
+    $disable_thread_sort = <STDIN>;
+    if ( ( $disable_thread_sort =~ /^y\n/i ) || ( ( $disable_thread_sort =~ /^\n/ ) && ( $default_value eq "y" ) ) ) {
+        $disable_thread_sort = 'true';
     } else {
     } else {
-        $allow_thread_sort = 'false';
+        $disable_thread_sort = 'false';
     }
     }
-    return $allow_thread_sort;
+    return $disable_thread_sort;
 }
 
 sub command313 {
 }
 
 sub command313 {
-    print "This option allows you to choose if SM uses server-side sorting\n";
-    print "Your IMAP server must support the SORT  command for this to work\n";
+    print "This option allows you to disable server side sorting if your server declares \n";
+    print "SORT support, but SORT extension is broken or does not work with options \n";
+    print "used by SquirrelMail. Option is not used, if SORT extension is not declared \n";
+    print "in IMAP CAPABILITY.\n";
+    print "\n";
+    print "It is strongly recommended to keep server side sorting enabled, if your ";
+    print "IMAP server supports it.";
     print "\n";
 
     print "\n";
 
-    if ( lc($allow_server_sort) eq 'true' ) {
+    if ( lc($disable_server_sort) eq 'true' ) {
         $default_value = "y";
     } else {
         $default_value = "n";
     }
         $default_value = "y";
     } else {
         $default_value = "n";
     }
-    print "Allow server-side sorting? (y/n) [$WHT$default_value$NRM]: $WHT";
-    $allow_server_sort = <STDIN>;
-    if ( ( $allow_server_sort =~ /^y\n/i ) || ( ( $allow_server_sort =~ /^\n/ ) && ( $default_value eq "y" ) ) ) {
-        $allow_server_sort = 'true';
+    print "Disable server-side sorting? (y/n) [$WHT$default_value$NRM]: $WHT";
+    $disable_server_sort = <STDIN>;
+    if ( ( $disable_server_sort =~ /^y\n/i ) || ( ( $disable_server_sort =~ /^\n/ ) && ( $default_value eq "y" ) ) ) {
+        $disable_server_sort = 'true';
     } else {
     } else {
-        $allow_server_sort = 'false';
+        $disable_server_sort = 'false';
     }
     }
-    return $allow_server_sort;
+    return $disable_server_sort;
 }
 
 sub command314 {
 }
 
 sub command314 {
@@ -2347,19 +2605,71 @@ sub command318 {
     return $time_zone_type;
 }
 
     return $time_zone_type;
 }
 
+# set the location base for redirects (since 1.5.2)
+sub command_config_location_base {
+    print "Here you can set the base part of the SquirrelMail URL.\n";
+    print "It is normally autodetected but if that fails, use this\n";
+    print "option to override.\n";
+    print "It should contain only the protocol and hostname/port parts\n";
+    print "of the URL; the full path will be appended automatically.\n\n";
+    print "Examples:\nhttp://webmail.example.org\nhttp://webmail.example.com:8080\nhttps://webmail.example.com:6691\n\n";
+    print "Do not add any path elements.\n";
+
+    print "URL base? [" .$WHT."autodetect$NRM]: $WHT";
+    $new_config_location_base = <STDIN>;
+    chomp($new_config_location_base);
+    $config_location_base = $new_config_location_base;
+    
+    return $config_location_base;
+}
+
+
+sub command_userThemes {
+    print "\nDefine the user themes that you wish to use.  If you have added\n";
+    print "a theme of your own, just follow the instructions (?) about\n";
+    print "how to add them.  You can also change the default theme.\n\n";
+    
+    print "Available user themes:\n";
+    $count = 0;
+    while ( $count <= $#user_theme_name ) {
+        if ( $count == $user_theme_default ) {
+            print " *";
+        } else {
+            print "  ";
+        }
+        if ( $count < 10 ) {
+            print " ";
+        }
+        $name       = $user_theme_name[$count];
+        $num_spaces = 35 - length($name);
+        for ( $i = 0 ; $i < $num_spaces ; $i++ ) {
+            $name = $name . " ";
+        }
+
+        print " $count.  $name";
+        print "($user_theme_path[$count])\n";
 
 
-sub command41 {
-    print "\nDefine the themes that you wish to use.  If you have added ";
-    print "a theme of your own, just follow the instructions (?) about how to add ";
-    print "them.  You can also change the default theme.\n";
-    print "[theme] command (?=help) > ";
+        $count++;
+    }
+    
+    print "\n";
+    print ".------------------------------------.\n";
+    print "| t             (detect user themes) |\n";
+    print "| +                 (add user theme) |\n";
+    print "| - N            (remove user theme) |\n";
+    print "| m N      (mark default user theme) |\n";
+    print "| l               (list user themes) |\n";
+    print "| d                           (done) |\n";
+    print "`------------------------------------'\n";
+    
+    print "\n[user_themes] command (?=help) > ";
     $input = <STDIN>;
     $input =~ s/[\r\n]//g;
     while ( $input ne "d" ) {
         if ( $input =~ /^\s*l\s*/i ) {
             $count = 0;
     $input = <STDIN>;
     $input =~ s/[\r\n]//g;
     while ( $input ne "d" ) {
         if ( $input =~ /^\s*l\s*/i ) {
             $count = 0;
-            while ( $count <= $#theme_name ) {
-                if ( $count == $theme_default ) {
+            while ( $count <= $#user_theme_name ) {
+                if ( $count == $user_theme_default ) {
                     print " *";
                 } else {
                     print "  ";
                     print " *";
                 } else {
                     print "  ";
@@ -2367,238 +2677,741 @@ sub command41 {
                 if ( $count < 10 ) {
                     print " ";
                 }
                 if ( $count < 10 ) {
                     print " ";
                 }
-                $name       = $theme_name[$count];
+                $name       = $user_theme_name[$count];
                 $num_spaces = 35 - length($name);
                 for ( $i = 0 ; $i < $num_spaces ; $i++ ) {
                     $name = $name . " ";
                 }
 
                 print " $count.  $name";
                 $num_spaces = 35 - length($name);
                 for ( $i = 0 ; $i < $num_spaces ; $i++ ) {
                     $name = $name . " ";
                 }
 
                 print " $count.  $name";
-                print "($theme_path[$count])\n";
+                print "($user_theme_path[$count])\n";
 
                 $count++;
             }
         } elsif ( $input =~ /^\s*m\s*[0-9]+/i ) {
 
                 $count++;
             }
         } elsif ( $input =~ /^\s*m\s*[0-9]+/i ) {
-            $old_def       = $theme_default;
-            $theme_default = $input;
-            $theme_default =~ s/^\s*m\s*//;
-            if ( ( $theme_default > $#theme_name ) || ( $theme_default < 0 ) ) {
-                print "Cannot set default theme to $theme_default.  That theme does not exist.\n";
-                $theme_default = $old_def;
+            $old_def       = $user_theme_default;
+            $user_theme_default = $input;
+            $user_theme_default =~ s/^\s*m\s*//;
+            if ( ( $user_theme_default > $#user_theme_name ) || ( $user_theme_default < 0 ) ) {
+                print "Cannot set default theme to $user_theme_default.  That theme does not exist.\n";
+                $user_theme_default = $old_def;
             }
         } elsif ( $input =~ /^\s*\+/ ) {
             }
         } elsif ( $input =~ /^\s*\+/ ) {
-            print "What is the name of this theme: ";
+            print "What is the name of this theme? ";
             $name = <STDIN>;
             $name =~ s/[\r\n]//g;
             $name = <STDIN>;
             $name =~ s/[\r\n]//g;
-            $theme_name[ $#theme_name + 1 ] = $name;
-            print "Be sure to put ../themes/ before the filename.\n";
-            print "What file is this stored in (ex: ../themes/default_theme.php): ";
+            $user_theme_name[ $#user_theme_name + 1 ] = $name;
+            print "Be sure to put ../css/ before the filename.\n";
+            print "What file is this stored in (ex: ../css/my_theme/): ";
             $name = <STDIN>;
             $name =~ s/[\r\n]//g;
             $name = <STDIN>;
             $name =~ s/[\r\n]//g;
-            $theme_path[ $#theme_path + 1 ] = $name;
+            $user_theme_path[ $#user_theme_path + 1 ] = $name;
         } elsif ( $input =~ /^\s*-\s*[0-9]?/ ) {
             if ( $input =~ /[0-9]+\s*$/ ) {
                 $rem_num = $input;
                 $rem_num =~ s/^\s*-\s*//g;
                 $rem_num =~ s/\s*$//;
             } else {
         } elsif ( $input =~ /^\s*-\s*[0-9]?/ ) {
             if ( $input =~ /[0-9]+\s*$/ ) {
                 $rem_num = $input;
                 $rem_num =~ s/^\s*-\s*//g;
                 $rem_num =~ s/\s*$//;
             } else {
-                $rem_num = $#theme_name;
+                $rem_num = $#user_theme_name;
             }
             }
-            if ( $rem_num == $theme_default ) {
+            if ( $rem_num == $user_theme_default ) {
                 print "You cannot remove the default theme!\n";
             } else {
                 $count          = 0;
                 @new_theme_name = ();
                 @new_theme_path = ();
                 print "You cannot remove the default theme!\n";
             } else {
                 $count          = 0;
                 @new_theme_name = ();
                 @new_theme_path = ();
-                while ( $count <= $#theme_name ) {
+                while ( $count <= $#user_theme_name ) {
                     if ( $count != $rem_num ) {
                     if ( $count != $rem_num ) {
-                        @new_theme_name = ( @new_theme_name, $theme_name[$count] );
-                        @new_theme_path = ( @new_theme_path, $theme_path[$count] );
+                        @new_theme_name = ( @new_theme_name, $user_theme_name[$count] );
+                        @new_theme_path = ( @new_theme_path, $user_theme_path[$count] );
                     }
                     $count++;
                 }
                     }
                     $count++;
                 }
-                @theme_name = @new_theme_name;
-                @theme_path = @new_theme_path;
-                if ( $theme_default > $rem_num ) {
-                    $theme_default--;
+                @user_theme_name = @new_theme_name;
+                @user_theme_path = @new_theme_path;
+                if ( $user_theme_default > $rem_num ) {
+                    $user_theme_default--;
                 }
             }
         } elsif ( $input =~ /^\s*t\s*/i ) {
             print "\nStarting detection...\n\n";
 
                 }
             }
         } elsif ( $input =~ /^\s*t\s*/i ) {
             print "\nStarting detection...\n\n";
 
-            opendir( DIR, "../themes" );
-            @files = grep { /\.php$/i } readdir(DIR);
+            opendir( DIR, "../css" );
+            @files = readdir(DIR);
             $cnt = 0;
             while ( $cnt <= $#files ) {
             $cnt = 0;
             while ( $cnt <= $#files ) {
-                $filename = "../themes/" . $files[$cnt];
-                if ( $filename ne "../themes/index.php" ) {
+                $filename = "../css/" . $files[$cnt] .'/';
+                if ( $filename ne "../css/rtl.css" && -e $filename . "default.css" ) {
                     $found = 0;
                     $found = 0;
-                    for ( $x = 0 ; $x <= $#theme_path ; $x++ ) {
-                        if ( $theme_path[$x] eq $filename ) {
+                    for ( $x = 0 ; $x <= $#user_theme_path ; $x++ ) {
+                        if ( $user_theme_path[$x] eq $filename ) {
                             $found = 1;
                         }
                     }
                     if ( $found != 1 ) {
                             $found = 1;
                         }
                     }
                     if ( $found != 1 ) {
-                        print "** Found theme: $filename\n";
+                        print "** Found user theme: $filename\n";
                         print "   What is its name? ";
                         $nm = <STDIN>;
                         $nm =~ s/[\n\r]//g;
                         print "   What is its name? ";
                         $nm = <STDIN>;
                         $nm =~ s/[\n\r]//g;
-                        $theme_name[ $#theme_name + 1 ] = $nm;
-                        $theme_path[ $#theme_path + 1 ] = $filename;
+                        $user_theme_name[ $#user_theme_name + 1 ] = $nm;
+                        $user_theme_path[ $#user_theme_path + 1 ] = $filename;
                     }
                 }
                 $cnt++;
             }
             print "\n";
                     }
                 }
                 $cnt++;
             }
             print "\n";
-            for ( $cnt = 0 ; $cnt <= $#theme_path ; $cnt++ ) {
-                $filename = $theme_path[$cnt];
-                if ( !( -e $filename ) ) {
+            for ( $cnt = 0 ; $cnt <= $#user_theme_path ; $cnt++ ) {
+                $filename = $user_theme_path[$cnt];
+                if ( $filename != 'none' && !( -e $filename ."/default.css" ) ) {
                     print "  Removing $filename (file not found)\n";
                     $offset         = 0;
                     print "  Removing $filename (file not found)\n";
                     $offset         = 0;
-                    @new_theme_name = ();
-                    @new_theme_path = ();
-                    for ( $x = 0 ; $x < $#theme_path ; $x++ ) {
-                        if ( $theme_path[$x] eq $filename ) {
+                    @new_user_theme_name = ();
+                    @new_user_theme_path = ();
+                    for ( $x = 0 ; $x < $#user_theme_path ; $x++ ) {
+                        if ( $user_theme_path[$x] eq $filename ) {
                             $offset = 1;
                         }
                         if ( $offset == 1 ) {
                             $offset = 1;
                         }
                         if ( $offset == 1 ) {
-                            $new_theme_name[$x] = $theme_name[ $x + 1 ];
-                            $new_theme_path[$x] = $theme_path[ $x + 1 ];
+                            $new_user_theme_name[$x] = $user_theme_name[ $x + 1 ];
+                            $new_user_theme_path[$x] = $user_theme_path[ $x + 1 ];
                         } else {
                         } else {
-                            $new_theme_name[$x] = $theme_name[$x];
-                            $new_theme_path[$x] = $theme_path[$x];
+                            $new_user_theme_name[$x] = $user_theme_name[$x];
+                            $new_user_theme_path[$x] = $user_theme_path[$x];
                         }
                     }
                         }
                     }
-                    @theme_name = @new_theme_name;
-                    @theme_path = @new_theme_path;
+                    @user_theme_name = @new_user_theme_name;
+                    @user_theme_path = @new_user_theme_path;
                 }
             }
             print "\nDetection complete!\n\n";
 
             closedir DIR;
         } elsif ( $input =~ /^\s*\?\s*/ ) {
                 }
             }
             print "\nDetection complete!\n\n";
 
             closedir DIR;
         } elsif ( $input =~ /^\s*\?\s*/ ) {
-            print ".-------------------------.\n";
-            print "| t       (detect themes) |\n";
-            print "| +           (add theme) |\n";
-            print "| - N      (remove theme) |\n";
-            print "| m N      (mark default) |\n";
-            print "| l         (list themes) |\n";
-            print "| d                (done) |\n";
-            print "`-------------------------'\n";
+            print ".------------------------------------.\n";
+            print "| t             (detect user themes) |\n";
+            print "| +                 (add user theme) |\n";
+            print "| - N            (remove user theme) |\n";
+            print "| m N      (mark default user theme) |\n";
+            print "| l               (list user themes) |\n";
+            print "| d                           (done) |\n";
+            print "`------------------------------------'\n";
         }
         }
-        print "[theme] command (?=help) > ";
+        print "[user_themes] command (?=help) > ";
         $input = <STDIN>;
         $input =~ s/[\r\n]//g;
     }
 }
 
         $input = <STDIN>;
         $input =~ s/[\r\n]//g;
     }
 }
 
-# Theme - CSS file
-sub command42 {
-    print "You may specify a cascading style-sheet (CSS) file to be included\n";
-    print "on each html page generated by SquirrelMail. The CSS file is useful\n";
-    print "for specifying a site-wide font. If you're not familiar with CSS\n";
-    print "files, leave this blank.\n";
-    print "\n";
-    print "To clear out an existing value, just type a space for the input.\n";
-    print "\n";
-    print "Please be aware of the following: \n";
-    print "  - Relative URLs are relative to the config dir\n";
-    print "    to use the themes directory, use ../themes/css/newdefault.css\n";
-    print "  - To specify a css file defined outside the SquirrelMail source tree\n";
-    print "    use the absolute URL the webserver would use to include the file\n";
-    print "    e.g. http://some.host.com/css/mystyle.css or /css/mystyle.css\n";
-    print "\n";
-    print "[$WHT$theme_css$NRM]: $WHT";
-    $new_theme_css = <STDIN>;
+sub command_iconSets {
+    print "\nDefine the icon themes that you wish to use.  If you have added\n";
+    print "a theme of your own, just follow the instructions (?) about\n";
+    print "how to add them.  You can also change the default and fallback\n";
+    print "themes.  The default theme will be used when no icon theme is\n";
+    print "set by the user.  The fallback theme will be used if an icon\n";
+    print "cannot be found in the currently selected icon theme.\n\n";
+    
+    print "Available icon themes:\n\n";
 
 
-    if ( $new_theme_css eq "\n" ) {
-        $new_theme_css = $theme_css;
-    } else {
-        $new_theme_css =~ s/[\r\n]//g;
-    }
-    $new_theme_css =~ s/^\s*//;
-    return $new_theme_css;
-}
+    $count = 0;
+    while ( $count <= $#icon_theme_name ) {
+        if ( $count == $icon_theme_def ) {
+            print " d";
+        } else {
+            print "  ";
+        }
+        if ( $count eq $icon_theme_fallback ) {
+            print "f ";
+        } else {
+            print "  ";
+        }
+        if ( $count < 10 ) {
+            print " ";
+        }
+        $name       = $icon_theme_name[$count];
+        $num_spaces = 35 - length($name);
+        for ( $i = 0 ; $i < $num_spaces ; $i++ ) {
+            $name = $name . " ";
+        }
 
 
-sub command61 {
-    print "You can now define different LDAP servers.\n";
-    print "[ldap] command (?=help) > ";
+        print " $count.  $name";
+        print "($icon_theme_path[$count])\n";
+
+        $count++;
+    }
+    
+    print "\n d = Default icon theme\n";
+    print " f = Fallback icon theme\n";
+    print "\n";
+    print ".------------------------------------.\n";
+    print "| t             (detect icon themes) |\n";
+    print "| +                 (add icon theme) |\n";
+    print "| - N            (remove icon theme) |\n";
+    print "| m N      (mark default icon theme) |\n";
+    print "| f N        (set fallback icon set) |\n";
+    print "| l               (list icon themes) |\n";
+    print "| d                           (done) |\n";
+    print "`------------------------------------'\n";
+    
+    print "\n[icon_themes] command (?=help) > ";
     $input = <STDIN>;
     $input =~ s/[\r\n]//g;
     while ( $input ne "d" ) {
         if ( $input =~ /^\s*l\s*/i ) {
             $count = 0;
     $input = <STDIN>;
     $input =~ s/[\r\n]//g;
     while ( $input ne "d" ) {
         if ( $input =~ /^\s*l\s*/i ) {
             $count = 0;
-            while ( $count <= $#ldap_host ) {
-                print "$count. $ldap_host[$count]\n";
-                print "        base: $ldap_base[$count]\n";
-                if ( $ldap_charset[$count] ) {
-                    print "     charset: $ldap_charset[$count]\n";
-                }
-                if ( $ldap_port[$count] ) {
-                    print "        port: $ldap_port[$count]\n";
-                }
-                if ( $ldap_name[$count] ) {
-                    print "        name: $ldap_name[$count]\n";
-                }
-                if ( $ldap_maxrows[$count] ) {
-                    print "     maxrows: $ldap_maxrows[$count]\n";
-                }
-                if ( $ldap_filter[$count] ) {
-                    print "      filter: $ldap_filter[$count]\n";
-                }
-                if ( $ldap_binddn[$count] ) {
-                    print "      binddn: $ldap_binddn[$count]\n";
-                    if ( $ldap_bindpw[$count] ) {
-                        print "      bindpw: $ldap_bindpw[$count]\n";
-                    }
-                }
-                if ( $ldap_protocol[$count] ) {
-                    print "    protocol: $ldap_protocol[$count]\n";
-                }
-                if ( $ldap_limit_scope[$count] ) {
-                    print " limit_scope: $ldap_limit_scope[$count]\n";
-                }
-                if ( $ldap_listing[$count] ) {
-                    print "     listing: $ldap_listing[$count]\n";
-                }
-                if ( $ldap_search_tree[$count] ) {
-                    print " search_tree: $ldap_search_tree[$count]\n";
-                }
-                if ( $ldap_starttls[$count] ) {
-                    print "    starttls: $ldap_starttls[$count]\n";
+            print "\n";
+            while ( $count <= $#icon_theme_name ) {
+                       if ( $count == $icon_theme_def ) {
+                           print " d";
+                       } else {
+                           print "  ";
+                       }
+                       if ( $count eq $icon_theme_fallback ) {
+                           print "f ";
+                       } else {
+                           print "  ";
+                       }
+                $name       = $icon_theme_name[$count];
+                $num_spaces = 35 - length($name);
+                for ( $i = 0 ; $i < $num_spaces ; $i++ ) {
+                    $name = $name . " ";
                 }
 
                 }
 
-                print "\n";
+                print " $count.  $name";
+                print "($icon_theme_path[$count])\n";
+
                 $count++;
                 $count++;
+            }
+                   print "\n d = Default icon theme\n";
+                   print " f = Fallback icon theme\n\n";
+        } elsif ( $input =~ /^\s*m\s*[0-9]+/i ) {
+            $old_def       = $icon_theme_def;
+            $icon_theme_def = $input;
+            $icon_theme_def =~ s/^\s*m\s*//;
+            if ( ( $icon_theme_default > $#icon_theme_name ) || ( $icon_theme_default < 0 ) ) {
+                print "Cannot set default icon theme to $icon_theme_default.  That theme does not exist.\n";
+                $icon_theme_def = $old_def;
+            }
+        } elsif ( $input =~ /^\s*f\s*[0-9]+/i ) {
+            $old_fb       = $icon_theme_fallback;
+            $icon_theme_fallback = $input;
+            $icon_theme_fallback =~ s/^\s*f\s*//;
+            if ( ( $icon_theme_fallback > $#icon_theme_name ) || ( $icon_theme_fallback < 0 ) ) {
+                print "Cannot set fallback icon theme to $icon_theme_fallback.  That theme does not exist.\n";
+                $icon_theme_fallback = $old_fb;
             }
         } elsif ( $input =~ /^\s*\+/ ) {
             }
         } elsif ( $input =~ /^\s*\+/ ) {
-            $sub = $#ldap_host + 1;
-
-            print "First, we need to have the hostname or the IP address where\n";
-            print "this LDAP server resides.  Example: ldap.bigfoot.com\n";
-            print "hostname: ";
-            $name = <STDIN>;
-            $name =~ s/[\r\n]//g;
-            $ldap_host[$sub] = $name;
-
-            print "\n";
-
-            print "Next, we need the server root (base dn).  For this, an empty\n";
-            print "string is allowed.\n";
-            print "Example: ou=member_directory,o=netcenter.com\n";
-            print "base: ";
+            print "What is the name of this icon theme? ";
             $name = <STDIN>;
             $name =~ s/[\r\n]//g;
             $name = <STDIN>;
             $name =~ s/[\r\n]//g;
-            $ldap_base[$sub] = $name;
-
-            print "\n";
-
-            print "This is the TCP/IP port number for the LDAP server.  Default\n";
-            print "port is 389.  This is optional.  Press ENTER for default.\n";
-            print "port: ";
+            $icon_theme_name[ $#icon_theme_name + 1 ] = $name;
+            print "Be sure to put ../images/themes/ before the filename.\n";
+            print "What directory is this icon theme stored in (ex: ../images/themes/my_theme/)? ";
             $name = <STDIN>;
             $name =~ s/[\r\n]//g;
             $name = <STDIN>;
             $name =~ s/[\r\n]//g;
-            $ldap_port[$sub] = $name;
+            $icon_theme_path[ $#icon_theme_path + 1 ] = $name;
+        } elsif ( $input =~ /^\s*-\s*[0-9]?/ ) {
+            if ( $input =~ /[0-9]+\s*$/ ) {
+                $rem_num = $input;
+                $rem_num =~ s/^\s*-\s*//g;
+                $rem_num =~ s/\s*$//;
+            } else {
+                $rem_num = $#icon_theme_name;
+            }
+            if ( $rem_num == $icon_theme_def ) {
+                print "You cannot remove the default icon theme!\n";
+            } elsif ( $rem_num == $icon_theme_fallback ) {
+                print "You cannot remove the fallback icon theme!\n";
+            } else {
+                $count          = 0;
+                @new_theme_name = ();
+                @new_theme_path = ();
+                while ( $count <= $#icon_theme_name ) {
+                    if ( $count != $rem_num ) {
+                        @new_theme_name = ( @new_theme_name, $icon_theme_name[$count] );
+                        @new_theme_path = ( @new_theme_path, $icon_theme_path[$count] );
+                    }
+                    $count++;
+                }
+                @icon_theme_name = @new_theme_name;
+                @icon_theme_path = @new_theme_path;
+                if ( $icon_theme_def > $rem_num ) {
+                    $icon_theme_def--;
+                }
+            }
+        } elsif ( $input =~ /^\s*t\s*/i ) {
+            print "\nStarting detection...\n\n";
+
+            opendir( DIR, "../images/themes/" );
+            @files = readdir(DIR);
+            $cnt = 0;
+            while ( $cnt <= $#files ) {
+                $filename = "../images/themes/" . $files[$cnt] .'/';
+                if ( -d "../images/themes/" . $files[$cnt] && $files[$cnt] !~ /^\./ && $files[$cnt] ne "CVS" ) {
+                    $found = 0;
+                    for ( $x = 0 ; $x <= $#icon_theme_path ; $x++ ) {
+                        if ( $icon_theme_path[$x] eq $filename ) {
+                            $found = 1;
+                        }
+                    }
+                    if ( $found != 1 ) {
+                        print "** Found icon theme: $filename\n";
+                        print "   What is its name? ";
+                        $nm = <STDIN>;
+                        $nm =~ s/[\n\r]//g;
+                        $icon_theme_name[ $#icon_theme_name + 1 ] = $nm;
+                        $icon_theme_path[ $#icon_theme_path + 1 ] = $filename;
+                    }
+                }
+                $cnt++;
+            }
+            print "\n";
+            for ( $cnt = 0 ; $cnt <= $#icon_theme_path ; $cnt++ ) {
+                $filename = $icon_theme_path[$cnt];
+                if ( $filename ne "none" && $filename ne "template" && ! -d $filename ) {
+                    print "  Removing $filename (file not found)\n";
+                    $offset         = 0;
+                    @new_icon_theme_name = ();
+                    @new_icon_theme_path = ();
+                    for ( $x = 0 ; $x < $#icon_theme_path ; $x++ ) {
+                        if ( $icon_theme_path[$x] eq $filename ) {
+                            $offset = 1;
+                        }
+                        if ( $offset == 1 ) {
+                            $new_icon_theme_name[$x] = $icon_theme_name[ $x + 1 ];
+                            $new_icon_theme_path[$x] = $icon_theme_path[ $x + 1 ];
+                        } else {
+                            $new_icon_theme_name[$x] = $icon_theme_name[$x];
+                            $new_icon_theme_path[$x] = $icon_theme_path[$x];
+                        }
+                    }
+                    @icon_theme_name = @new_icon_theme_name;
+                    @icon_theme_path = @new_icon_theme_path;
+                }
+            }
+            print "\nDetection complete!\n\n";
+
+            closedir DIR;
+        } elsif ( $input =~ /^\s*\?\s*/ ) {
+            print ".------------------------------------.\n";
+            print "| t             (detect icon themes) |\n";
+            print "| +                 (add icon theme) |\n";
+            print "| - N            (remove icon theme) |\n";
+            print "| m N      (mark default icon theme) |\n";
+            print "| f N        (set fallback icon set) |\n";
+            print "| l               (list icon themes) |\n";
+            print "| d                           (done) |\n";
+            print "`------------------------------------'\n";
+        }
+        print "[icon_themes] command (?=help) > ";
+        $input = <STDIN>;
+        $input =~ s/[\r\n]//g;
+    }
+}
+
+sub command_templates {
+    print "\nDefine the template sets that you wish to use.  If you have added\n";
+    print "a template set of your own, just follow the instructions (?) about\n";
+    print "how to add them.  You can also change the default template.\n";
+
+    print "\n  Available Templates:\n";
+
+    $count = 0;
+    while ( $count <= $#templateset_name ) {
+        if ( $templateset_id[$count] eq $templateset_default ) {
+            print " d";
+        } else {
+            print "  ";
+        }
+        if ( $templateset_id[$count] eq $templateset_fallback ) {
+            print "f ";
+        } else {
+            print "  ";
+        }
+        if ( $count < 10 ) {
+            print " ";
+        }
+        $name       = $templateset_name[$count];
+        $num_spaces = 35 - length($name);
+        for ( $i = 0 ; $i < $num_spaces ; $i++ ) {
+            $name = $name . " ";
+        }
+
+        print " $count.  $name";
+        print "($templateset_id[$count])\n";
+
+        $count++;
+   }
+   print "\n  d = default template set\n"
+       . "  f = fallback template set\n\n";
+
+    $menu_text = ".-------------------------------------.\n"
+               . "| t             (detect template set) |\n"
+               . "| +                (add template set) |\n"
+               . "| - N           (remove template set) |\n"
+               . "| m N     (mark default template set) |\n"
+               . "| f N     (set fallback template set) |\n"
+               . "| l              (list template sets) |\n"
+               . "| d                            (done) |\n"
+               . "|-------------------------------------|\n"
+               . "| where N is a template set number    |\n"
+               . "`-------------------------------------'\n";
+    print "\n";
+    print $menu_text;
+    print "\n[template set] command (?=help) > ";
+
+    $input = <STDIN>;
+    $input =~ s/[\r\n]//g;
+    while ( $input ne "d" ) {
+
+        # list template sets
+        #
+        if ( $input =~ /^\s*l\s*/i ) {
+            $count = 0;
+            while ( $count <= $#templateset_name ) {
+                if ( $templateset_id[$count] eq $templateset_default ) {
+                    print " d";
+                } else {
+                    print "  ";
+                }
+                if ( $templateset_id[$count] eq $templateset_fallback ) {
+                    print "f ";
+                } else {
+                    print "  ";
+                }
+                if ( $count < 10 ) {
+                    print " ";
+                }
+                $name       = $templateset_name[$count];
+                $num_spaces = 35 - length($name);
+                for ( $i = 0 ; $i < $num_spaces ; $i++ ) {
+                    $name = $name . " ";
+                }
+
+                print " $count.  $name";
+                print "($templateset_id[$count])\n";
+
+                $count++;
+            }
+            print "\n  d = default template set\n"
+                . "  f = fallback template set\n\n";
+
+        # mark default template set
+        #
+        } elsif ( $input =~ /^\s*m\s*[0-9]+/i ) {
+            $old_def       = $templateset_default;
+            $input =~ s/^\s*m\s*//;
+            $templateset_default = $templateset_id[$input];
+            if ( $templateset_default =~ /^\s*$/ ) {
+                print "Cannot set default template set to $input.  That template set does not exist.\n";
+                $templateset_default = $old_def;
+            }
+
+        # set fallback template set
+        #
+        } elsif ( $input =~ /^\s*f\s*[0-9]+/i ) {
+            $old_def       = $templateset_fallback;
+            $input =~ s/^\s*f\s*//;
+            $templateset_fallback = $templateset_id[$input];
+            if ( $templateset_fallback =~ /^\s*$/ ) {
+                print "Cannot set fallback template set to $input.  That template set does not exist.\n";
+                $templateset_fallback = $old_def;
+            }
+
+        # add template set
+        #
+        } elsif ( $input =~ /^\s*\+/ ) {
+            print "\nWhat is the name of this template (as shown to your users): ";
+            $name = <STDIN>;
+            $name =~ s/[\r\n]//g;
+            $templateset_name[ $#templateset_name + 1 ] = $name;
+            print "\n\nThe directory name should not contain any path information\n"
+                . "or slashes, and should be the name of the directory that the\n"
+                . "template set is found in within the SquirrelMail templates\n"
+                . "directory.\n\n";
+            print "What directory is this stored in (ex: default_advanced): ";
+            $name = <STDIN>;
+            $name =~ s/[\r\n]//g;
+            $templateset_id[ $#templateset_id + 1 ] = $name;
+
+        # detect template sets
+        #
+        } elsif ( $input =~ /^\s*t\s*/i ) {
+            print "\nStarting detection...\n\n";
+            opendir( DIR, "../templates" );
+            @files = readdir(DIR);
+            $cnt = 0;
+            while ( $cnt <= $#files ) {
+                if ( -d "../templates/" . $files[$cnt] && $files[$cnt] !~ /^\./ && $files[$cnt] ne "CVS" ) {
+                    $filename = $files[$cnt];
+                    $found = 0;
+                    for ( $x = 0 ; $x <= $#templateset_id ; $x++ ) {
+                        if ( $templateset_id[$x] eq $filename ) {
+                            $found = 1;
+                            last;
+                        }
+                    }
+                    if ( $found != 1) {
+                        print "** Found template set: $filename\n";
+                        print "   What is it's name (as shown to your users)? ";
+                        $nm = <STDIN>;
+                        $nm =~ s/[\n\r]//g;
+                        $templateset_id[ $#templateset_id + 1 ] = $filename;
+                        $templateset_name[ $#templateset_name + 1 ] = $nm;
+                    }
+                }
+                $cnt++;
+            }
+            print "\n";
+            for ( $cnt= 0 ; $cnt <= $#templateset_id ; ) {
+                $filename = $templateset_id[$cnt];
+                if ( !(-d  change_to_rel_path('SM_PATH . \'templates/' . $filename)) ) {
+                    print "  Removing \"$filename\" (template set directory not found)\n";
+                    if ( $templateset_default eq $filename ) { $templateset_default = 'default'; }
+                    if ( $templateset_fallback eq $filename ) { $templateset_fallback = 'default'; }
+                    $offset         = 0;
+                    @new_templateset_name = ();
+                    @new_templateset_id = ();
+                    for ( $x = 0 ; $x < $#templateset_id ; $x++ ) {
+                        if ( $templateset_id[$x] eq $filename ) {
+                            $offset = 1;
+                        }
+                        if ( $offset == 1 ) {
+                            $new_templateset_name[$x] = $templateset_name[ $x + 1 ];
+                            $new_templateset_id[$x] = $templateset_id[ $x + 1 ];
+                        } else {
+                            $new_templateset_name[$x] = $templateset_name[$x];
+                            $new_templateset_id[$x] = $templateset_id[$x];
+                        }
+                    }
+                    @templateset_name = @new_templateset_name;
+                    @templateset_id = @new_templateset_id;
+                } else { $cnt++; }
+            }
+            print "\nDetection complete!\n\n";
+
+            closedir DIR;
+
+        # remove template set
+        #
+        # undocumented functionality of removing last template set isn't that great
+        #} elsif ( $input =~ /^\s*-\s*[0-9]?/ ) {
+        } elsif ( $input =~ /^\s*-\s*[0-9]+/ ) {
+            if ( $input =~ /[0-9]+\s*$/ ) {
+                $rem_num = $input;
+                $rem_num =~ s/^\s*-\s*//g;
+                $rem_num =~ s/\s*$//;
+            } else {
+                $rem_num = $#templateset_name;
+            }
+            if ( $templateset_id[$rem_num] eq $templateset_default ) {
+                print "You cannot remove the default template set!\n";
+            } elsif ( $templateset_id[$rem_num] eq $templateset_fallback ) {
+                print "You cannot remove the fallback template set!\n";
+            } else {
+                $count          = 0;
+                @new_templateset_name = ();
+                @new_templateset_id = ();
+                while ( $count <= $#templateset_name ) {
+                    if ( $count != $rem_num ) {
+                        @new_templateset_name = ( @new_templateset_name, $templateset_name[$count] );
+                        @new_templateset_id = ( @new_templateset_id, $templateset_id[$count] );
+                    }
+                    $count++;
+                }
+                @templateset_name = @new_templateset_name;
+                @templateset_id = @new_templateset_id;
+            }
+
+        # help
+        #
+        } elsif ( $input =~ /^\s*\?\s*/ ) {
+            print $menu_text;
+
+        # command not understood
+        #
+        } else {
+            print "Command not understood\n";
+        }
+
+        print "[template set] command (?=help) > ";
+        $input = <STDIN>;
+        $input =~ s/[\r\n]//g;
+    }
+    return $templateset_default;
+}
+
+
+# sets default font size option
+sub command_default_fontsize {
+    print "Enter default font size [$WHT$$default_fontsize$NRM]: $WHT";
+    $new_size = <STDIN>;
+    if ( $new_size eq "\n" ) {
+        $new_size = $size;
+    } else {
+        $new_size =~ s/[\r\n]//g;
+    }
+    return $new_size;
+}
+
+# controls available fontsets
+sub command_fontsets {
+    # Greeting
+    print "You can control fontsets available to end users here.\n";
+    # set initial $input value
+    $input = 'l';
+    while ( $input ne "x" ) {
+        if ( $input =~ /^\s*a\s*/i ) {
+            # add new fontset
+            print "\nFontset name: ";
+            $name = <STDIN>;
+            if (! $fontsets{trim($name)}) {
+                print "Fontset string: ";
+                $value = <STDIN>;
+                $fontsets{trim($name)} = trim($value);
+            } else {
+                print "\nERROR: Such fontset already exists.\n";
+            }
+        } elsif ( $input =~ /^\s*e\s*/i ) {
+            # edit existing fontset
+            print "\nFontset name: ";
+            $name = <STDIN>;
+            if (! $fontsets{trim($name)}) {
+                print "\nERROR: No such fontset.\n";
+            } else {
+                print "Fontset string [$fontsets{trim($name)}]: ";
+                $value = <STDIN>;
+                $fontsets{trim($name)} = trim($value);
+            }
+        } elsif ( $input =~ /^\s*d\s*/ ) {
+            # delete existing fontset
+            print "\nFontset name: ";
+            $name = <STDIN>;
+            if (! $fontsets{trim($name)}) {
+                print "\nERROR: No such fontset.\n";
+            } else {
+                delete $fontsets{trim($name)};
+            }
+        } elsif ( $input =~ /^\s*l\s*/ ) {
+            # list fontsets
+            print "\nConfigured fontsets:\n";
+            while (($fontset_name, $fontset_string) = each(%fontsets)) {
+                print "  $fontset_name = $fontset_string\n";
+            }
+            print "Default fontset: $default_fontset\n";
+        } elsif ( $input =~ /^\s*m\s*/ ) {
+            # set default fontset
+            print "\nSet default fontset [$default_fontset]: ";
+            $name = <STDIN>;
+            if (trim($name) ne '' and ! $fontsets{trim($name)}) {
+                print "\nERROR: No such fontset.\n";
+            } else {
+                $default_fontset = trim($name);
+            }
+        } else {
+            # print available commands on any other input
+            print "\nAvailable commands:\n";
+            print "  a - Adds new fontset.\n";
+            print "  d - Deletes existing fontset.\n";
+            print "  e - Edits existing fontset.\n";
+            print "  h or ? - Shows this help screen.\n";
+            print "  l - Lists available fontsets.\n";
+            print "  m - Sets default fontset.\n";
+            print "  x - Exits fontset editor mode.\n";
+        }
+        print "\nCommand [fontsets] (a,d,e,h,?=help,l,m,x)> ";
+        $input = <STDIN>;
+        $input =~ s/[\r\n]//g;
+    }
+}
+
+sub command61 {
+    print "You can now define different LDAP servers.\n";
+    print "Please ensure proper permissions for config.php when including\n";
+    print "sensitive passwords.\n\n";
+    print "[ldap] command (?=help) > ";
+    $input = <STDIN>;
+    $input =~ s/[\r\n]//g;
+    while ( $input ne "d" ) {
+        if ( $input =~ /^\s*l\s*/i ) {
+            $count = 0;
+            while ( $count <= $#ldap_host ) {
+                print "$count. $ldap_host[$count]\n";
+                print "        base: $ldap_base[$count]\n";
+                if ( $ldap_charset[$count] ) {
+                    print "     charset: $ldap_charset[$count]\n";
+                }
+                if ( $ldap_port[$count] ) {
+                    print "        port: $ldap_port[$count]\n";
+                }
+                if ( $ldap_name[$count] ) {
+                    print "        name: $ldap_name[$count]\n";
+                }
+                if ( $ldap_maxrows[$count] ) {
+                    print "     maxrows: $ldap_maxrows[$count]\n";
+                }
+                if ( $ldap_filter[$count] ) {
+                    print "      filter: $ldap_filter[$count]\n";
+                }
+                if ( $ldap_binddn[$count] ) {
+                    print "      binddn: $ldap_binddn[$count]\n";
+                    if ( $ldap_bindpw[$count] ) {
+                        print "      bindpw: $ldap_bindpw[$count]\n";
+                    }
+                }
+                if ( $ldap_protocol[$count] ) {
+                    print "    protocol: $ldap_protocol[$count]\n";
+                }
+                if ( $ldap_limit_scope[$count] ) {
+                    print " limit_scope: $ldap_limit_scope[$count]\n";
+                }
+                if ( $ldap_listing[$count] ) {
+                    print "     listing: $ldap_listing[$count]\n";
+                }
+                if ( $ldap_writeable[$count] ) {
+                    print "   writeable: $ldap_writeable[$count]\n";
+                }
+                if ( $ldap_search_tree[$count] ) {
+                    print " search_tree: $ldap_search_tree[$count]\n";
+                }
+                if ( $ldap_starttls[$count] ) {
+                    print "    starttls: $ldap_starttls[$count]\n";
+                }
+
+                print "\n";
+                $count++;
+            }
+        } elsif ( $input =~ /^\s*\+/ ) {
+            $sub = $#ldap_host + 1;
+
+            print "First, we need to have the hostname or the IP address where\n";
+            print "this LDAP server resides. Example: ldap.bigfoot.com\n";
+            print "\n";
+            print "You can use any URI compatible with your LDAP library. Please\n";
+            print "note that StartTLS option is not compatible with ldaps and\n";
+            print "ldapi URIs.\n";
+            print "hostname: ";
+            $name = <STDIN>;
+            $name =~ s/[\r\n]//g;
+            $ldap_host[$sub] = $name;
+
+            print "\n";
+
+            print "Next, we need the server root (base dn).  For this, an empty\n";
+            print "string is allowed.\n";
+            print "Example: ou=member_directory,o=netcenter.com\n";
+            print "base: ";
+            $name = <STDIN>;
+            $name =~ s/[\r\n]//g;
+            $ldap_base[$sub] = $name;
+
+            print "\n";
+
+            print "This is the TCP/IP port number for the LDAP server.  Default\n";
+            print "port is 389.  This is optional.  Press ENTER for default.\n";
+            print "port: ";
+            $name = <STDIN>;
+            $name =~ s/[\r\n]//g;
+            $ldap_port[$sub] = $name;
 
             print "\n";
 
 
             print "\n";
 
@@ -2680,7 +3493,6 @@ sub command61 {
               print "Number of displayed entries is limited by maxrows setting.\n";
               print "\n";
               print "Don't enable this option for public LDAP directories.\n";
               print "Number of displayed entries is limited by maxrows setting.\n";
               print "\n";
               print "Don't enable this option for public LDAP directories.\n";
-              print "This feature is experimental.\n";
               print "\n";
               print "Allow listing of LDAP directory? (y/N):";
               $name = <STDIN>;
               print "\n";
               print "Allow listing of LDAP directory? (y/N):";
               $name = <STDIN>;
@@ -2693,6 +3505,23 @@ sub command61 {
 
               print "\n";
 
 
               print "\n";
 
+              print "You can control write access to LDAP address book here. This option can\n";
+              print "be useful if you run small LDAP server and want to provide writable\n";
+              print "shared address book stored in LDAP to users of webmail interface.\n";
+              print "\n";
+              print "Don't enable this option for public LDAP directories.\n";
+              print "\n";
+              print "Allow writing to LDAP directory? (y/N):";
+              $name = <STDIN>;
+              if ( $name =~ /^y\n/i ) {
+                $name = 'true';
+              } else {
+                $name = 'false';
+              }
+              $ldap_writeable[$sub] = $name;
+
+              print "\n";
+
               print "You can specify an additional search filter.\n";
               print "This could be something like \"(objectclass=posixAccount)\".\n";
               print "No filtering is performed by default. Press ENTER for default.\n";
               print "You can specify an additional search filter.\n";
               print "This could be something like \"(objectclass=posixAccount)\".\n";
               print "No filtering is performed by default. Press ENTER for default.\n";
@@ -2769,6 +3598,7 @@ sub command61 {
             @new_ldap_protocol = ();
             @new_ldap_limit_scope = ();
             @new_ldap_listing = ();
             @new_ldap_protocol = ();
             @new_ldap_limit_scope = ();
             @new_ldap_listing = ();
+            @new_ldap_writeable = ();
             @new_ldap_search_tree = ();
             @new_ldap_starttls = ();
 
             @new_ldap_search_tree = ();
             @new_ldap_starttls = ();
 
@@ -2786,6 +3616,7 @@ sub command61 {
                     @new_ldap_protocol  = ( @new_ldap_protocol,  $ldap_protocol[$count] );
                     @new_ldap_limit_scope = ( @new_ldap_limit_scope,  $ldap_limit_scope[$count] );
                     @new_ldap_listing = ( @new_ldap_listing, $ldap_listing[$count] );
                     @new_ldap_protocol  = ( @new_ldap_protocol,  $ldap_protocol[$count] );
                     @new_ldap_limit_scope = ( @new_ldap_limit_scope,  $ldap_limit_scope[$count] );
                     @new_ldap_listing = ( @new_ldap_listing, $ldap_listing[$count] );
+                    @new_ldap_writeable = ( @new_ldap_writeable, $ldap_writeable[$count] );
                     @new_ldap_search_tree = ( @new_ldap_search_tree, $ldap_search_tree[$count] );
                     @new_ldap_starttls = ( @new_ldap_starttls, $ldap_starttls[$count] );
                 }
                     @new_ldap_search_tree = ( @new_ldap_search_tree, $ldap_search_tree[$count] );
                     @new_ldap_starttls = ( @new_ldap_starttls, $ldap_starttls[$count] );
                 }
@@ -2803,6 +3634,7 @@ sub command61 {
             @ldap_protocol = @new_ldap_protocol;
             @ldap_limit_scope = @new_ldap_limit_scope;
             @ldap_listing = @new_ldap_listing;
             @ldap_protocol = @new_ldap_protocol;
             @ldap_limit_scope = @new_ldap_limit_scope;
             @ldap_listing = @new_ldap_listing;
+            @ldap_writeable = @new_ldap_writeable;
             @ldap_search_tree = @new_ldap_search_tree;
             @ldap_starttls = @new_ldap_starttls;
 
             @ldap_search_tree = @new_ldap_search_tree;
             @ldap_starttls = @new_ldap_starttls;
 
@@ -2912,14 +3744,47 @@ sub command65 {
     return $abook_global_file_listing;
 }
 
     return $abook_global_file_listing;
 }
 
+# controls $abook_file_line_length setting
+sub command_abook_file_line_length {
+    print "This setting controls space allocated to file based address book records.\n";
+    print "End users will be unable to save address book entry, if total entry size \n";
+    print "(quoted address book fields + 4 delimiters + linefeed) exceeds allowed \n";
+    print "address book length size.\n";
+    print "\n";
+    print "Same setting is applied to personal and global file based address books.\n";
+    print "\n";
+    print "It is strongly recommended to keep default setting value. Change it only\n";
+    print "if you really want to store address book entries that are bigger than two\n";
+    print "kilobytes (2048).\n";
+    print "\n";
+
+    print "Enter allowed address book line length [$abook_file_line_length]: ";
+    my $tmp = <STDIN>;
+    $tmp = trim($tmp);
+    # value is not modified, if user hits Enter or enters space
+    if ($tmp ne '') {
+        # make sure that input is numeric
+        if ($tmp =~ /^\d+$/) {
+            $abook_file_line_length = $tmp;
+        } else {
+            print "If you want to change this setting, you must enter number.\n";
+            print "If you want to keep original setting - enter space.\n\n";
+            print "Press Enter to continue...";
+            $tmp = <STDIN>;
+        }
+    }
+}
+
 sub command91 {
     print "If you want to store your users address book details in a database then\n";
     print "you need to set this DSN to a valid value. The format for this is:\n";
     print "mysql://user:pass\@hostname/dbname\n";
     print "Where mysql can be one of the databases PHP supports, the most common\n";
 sub command91 {
     print "If you want to store your users address book details in a database then\n";
     print "you need to set this DSN to a valid value. The format for this is:\n";
     print "mysql://user:pass\@hostname/dbname\n";
     print "Where mysql can be one of the databases PHP supports, the most common\n";
-    print "of these are mysql, msql and pgsql\n";
+    print "of these are mysql, msql and pgsql.\n";
+    print "Please ensure proper permissions for config.php when including\n";
+    print "sensitive passwords.\n\n";
     print "If the DSN is left empty (hit space and then return) the database\n";
     print "If the DSN is left empty (hit space and then return) the database\n";
-    print "related code for address books will not be used\n";
+    print "related code for address books will not be used.\n";
     print "\n";
 
     if ( $addrbook_dsn eq "" ) {
     print "\n";
 
     if ( $addrbook_dsn eq "" ) {
@@ -2957,9 +3822,11 @@ sub command93 {
     print "you need to set this DSN to a valid value. The format for this is:\n";
     print "mysql://user:pass\@hostname/dbname\n";
     print "Where mysql can be one of the databases PHP supports, the most common\n";
     print "you need to set this DSN to a valid value. The format for this is:\n";
     print "mysql://user:pass\@hostname/dbname\n";
     print "Where mysql can be one of the databases PHP supports, the most common\n";
-    print "of these are mysql, msql and pgsql\n";
+    print "of these are mysql, msql and pgsql.\n";
+    print "Please ensure proper permissions for config.php when including\n";
+    print "sensitive passwords.\n\n";
     print "If the DSN is left empty (hit space and then return) the database\n";
     print "If the DSN is left empty (hit space and then return) the database\n";
-    print "related code for address books will not be used\n";
+    print "related code for address books will not be used.\n";
     print "\n";
 
     if ( $prefs_dsn eq "" ) {
     print "\n";
 
     if ( $prefs_dsn eq "" ) {
@@ -3060,9 +3927,11 @@ sub command98 {
     print "you need to set this DSN to a valid value. The format for this is:\n";
     print "mysql://user:pass\@hostname/dbname\n";
     print "Where mysql can be one of the databases PHP supports, the most common\n";
     print "you need to set this DSN to a valid value. The format for this is:\n";
     print "mysql://user:pass\@hostname/dbname\n";
     print "Where mysql can be one of the databases PHP supports, the most common\n";
-    print "of these are mysql, msql and pgsql\n";
+    print "of these are mysql, msql and pgsql.\n";
+    print "Please ensure proper permissions for config.php when including\n";
+    print "sensitive passwords.\n\n";
     print "If the DSN is left empty (hit space and then return) the database\n";
     print "If the DSN is left empty (hit space and then return) the database\n";
-    print "related code for global SQL address book will not be used\n";
+    print "related code for global SQL address book will not be used.\n";
     print "\n";
 
     if ( $addrbook_global_dsn eq "" ) {
     print "\n";
 
     if ( $addrbook_global_dsn eq "" ) {
@@ -3156,7 +4025,7 @@ sub commandA2 {
     print "This option controls what character set is used when sending\n";
     print "mail and when sending HTML to the browser. Option works only\n";
     print "with US English (en_US) translation. Other translations use\n";
     print "This option controls what character set is used when sending\n";
     print "mail and when sending HTML to the browser. Option works only\n";
     print "with US English (en_US) translation. Other translations use\n";
-    print "charsets that are set in functions/i18n.php.\n";
+    print "charsets that are set in translation settings.\n";
     print "\n";
 
     print "[$WHT$default_charset$NRM]: $WHT";
     print "\n";
 
     print "[$WHT$default_charset$NRM]: $WHT";
@@ -3236,28 +4105,6 @@ sub commandA5 {
     return $lossy_encoding;
 }
 
     return $lossy_encoding;
 }
 
-
-# Advanced tree
-sub commandB1 {
-    print "Enable this option if you want to use DHTML based folder listing.\n";
-    print "Code is experimental, works only with some browsers and there might\n";
-    print "be some glitches.\n";
-    print "\n";
-
-    if ( lc($advanced_tree) eq 'true' ) {
-        $default_value = "y";
-    } else {
-        $default_value = "n";
-    }
-    print "Use advanced tree in folder listing? (y/n) [$WHT$default_value$NRM]: $WHT";
-    $advanced_tree = <STDIN>;
-    if ( ( $advanced_tree =~ /^y\n/i ) || ( ( $advanced_tree =~ /^\n/ ) && ( $default_value eq "y" ) ) ) {
-        $advanced_tree = 'true';
-    } else {
-        $advanced_tree = 'false';
-    }
-    return $advanced_tree;
-}
 # display html emails in iframe
 sub commandB2 {
     print "This option can enable html email rendering inside iframe.\n";
 # display html emails in iframe
 sub commandB2 {
     print "This option can enable html email rendering inside iframe.\n";
@@ -3374,7 +4221,32 @@ sub commandB6 {
     return $allow_remote_configtest;
 }
 
     return $allow_remote_configtest;
 }
 
+# Default Icon theme
+sub commandB7 {
+    print "You may change the path to the default icon theme to be used, if icons\n";
+    print "have been enabled.  This theme will be used when an icon cannot be\n";
+    print "found in the current theme, or when no icon theme is specified.  If\n";
+    print "left blank, and icons are enabled, the default theme will be used\n";
+    print "from images/themes/default/.\n";
+    print "\n";
+    print "To clear out an existing value, just type a space for the input.\n";
+    print "\n";
+    print "Please be aware of the following: \n";
+    print "  - Relative URLs are relative to the config dir\n";
+    print "    to use the icon themes directory, use ../images/themes/newtheme/\n";
+    print "  - The icon theme may be outside the SquirrelMail directory, but\n";
+    print "    it must be web accessible.\n";
+    print "[$WHT$icon_theme_def$NRM]: $WHT";
+    $new_icon_theme_def = <STDIN>;
 
 
+    if ( $new_icon_theme_def eq "\n" ) {
+        $new_icon_theme_def = $icon_theme_def;
+    } else {
+        $new_icon_theme_def =~ s/[\r\n]//g;
+    }
+    $new_icon_theme_def =~ s/^\s*//;
+    return $new_icon_theme_def;
+}
 
 sub save_data {
     $tab = "    ";
 
 sub save_data {
     $tab = "    ";
@@ -3466,98 +4338,160 @@ sub save_data {
         print CF "\$encode_header_key      = '$encode_header_key';\n";
         print CF "\n";
 
         print CF "\$encode_header_key      = '$encode_header_key';\n";
         print CF "\n";
 
-    # string
+        # string
         print CF "\$default_folder_prefix          = '$default_folder_prefix';\n";
         print CF "\$default_folder_prefix          = '$default_folder_prefix';\n";
-    # string
+        # string
         print CF "\$trash_folder                   = '$trash_folder';\n";
         print CF "\$trash_folder                   = '$trash_folder';\n";
-    # string
+        # string
         print CF "\$sent_folder                    = '$sent_folder';\n";
         print CF "\$sent_folder                    = '$sent_folder';\n";
-    # string
+        # string
         print CF "\$draft_folder                   = '$draft_folder';\n";
         print CF "\$draft_folder                   = '$draft_folder';\n";
-    # boolean
+        # boolean
         print CF "\$default_move_to_trash          = $default_move_to_trash;\n";
         print CF "\$default_move_to_trash          = $default_move_to_trash;\n";
-    # boolean
+        # boolean
         print CF "\$default_move_to_sent           = $default_move_to_sent;\n";
         print CF "\$default_move_to_sent           = $default_move_to_sent;\n";
-    # boolean
+        # boolean
         print CF "\$default_save_as_draft          = $default_save_as_draft;\n";
         print CF "\$default_save_as_draft          = $default_save_as_draft;\n";
-    # boolean
+        # boolean
         print CF "\$show_prefix_option             = $show_prefix_option;\n";
         print CF "\$show_prefix_option             = $show_prefix_option;\n";
-    # boolean
+        # boolean
         print CF "\$list_special_folders_first     = $list_special_folders_first;\n";
         print CF "\$list_special_folders_first     = $list_special_folders_first;\n";
-    # boolean
+        # boolean
         print CF "\$use_special_folder_color       = $use_special_folder_color;\n";
         print CF "\$use_special_folder_color       = $use_special_folder_color;\n";
-    # boolean
+        # boolean
         print CF "\$auto_expunge                   = $auto_expunge;\n";
         print CF "\$auto_expunge                   = $auto_expunge;\n";
-    # boolean
+        # boolean
         print CF "\$default_sub_of_inbox           = $default_sub_of_inbox;\n";
         print CF "\$default_sub_of_inbox           = $default_sub_of_inbox;\n";
-    # boolean
+        # boolean
         print CF "\$show_contain_subfolders_option = $show_contain_subfolders_option;\n";
         print CF "\$show_contain_subfolders_option = $show_contain_subfolders_option;\n";
-    # integer
+        # integer
         print CF "\$default_unseen_notify          = $default_unseen_notify;\n";
         print CF "\$default_unseen_notify          = $default_unseen_notify;\n";
-    # integer
+        # integer
         print CF "\$default_unseen_type            = $default_unseen_type;\n";
         print CF "\$default_unseen_type            = $default_unseen_type;\n";
-    # boolean
+        # boolean
         print CF "\$auto_create_special            = $auto_create_special;\n";
         print CF "\$auto_create_special            = $auto_create_special;\n";
-    # boolean
+        # boolean
         print CF "\$delete_folder                  = $delete_folder;\n";
         print CF "\$delete_folder                  = $delete_folder;\n";
-    # boolean
+        # boolean
         print CF "\$noselect_fix_enable            = $noselect_fix_enable;\n";
 
         print CF "\n";
 
         print CF "\$noselect_fix_enable            = $noselect_fix_enable;\n";
 
         print CF "\n";
 
-    # string
+        # string
         print CF "\$data_dir                 = " . &change_to_SM_path($data_dir) . ";\n";
         print CF "\$data_dir                 = " . &change_to_SM_path($data_dir) . ";\n";
-    # string that can contain a variable
+        # string that can contain a variable
         print CF "\$attachment_dir           = " . &change_to_SM_path($attachment_dir) . ";\n";
         print CF "\$attachment_dir           = " . &change_to_SM_path($attachment_dir) . ";\n";
-    # integer
+        # integer
         print CF "\$dir_hash_level           = $dir_hash_level;\n";
         print CF "\$dir_hash_level           = $dir_hash_level;\n";
-    # string
+        # string
         print CF "\$default_left_size        = '$default_left_size';\n";
         print CF "\$default_left_size        = '$default_left_size';\n";
-    # boolean
+        # boolean
         print CF "\$force_username_lowercase = $force_username_lowercase;\n";
         print CF "\$force_username_lowercase = $force_username_lowercase;\n";
-    # boolean
+        # boolean
         print CF "\$default_use_priority     = $default_use_priority;\n";
         print CF "\$default_use_priority     = $default_use_priority;\n";
-    # boolean
+        # boolean
         print CF "\$hide_sm_attributions     = $hide_sm_attributions;\n";
         print CF "\$hide_sm_attributions     = $hide_sm_attributions;\n";
-    # boolean
+        # boolean
         print CF "\$default_use_mdn          = $default_use_mdn;\n";
         print CF "\$default_use_mdn          = $default_use_mdn;\n";
-    # boolean
+        # boolean
         print CF "\$edit_identity            = $edit_identity;\n";
         print CF "\$edit_identity            = $edit_identity;\n";
-    # boolean
+        # boolean
         print CF "\$edit_name                = $edit_name;\n";
         print CF "\$edit_name                = $edit_name;\n";
-    # boolean
+        # boolean
         print CF "\$hide_auth_header         = $hide_auth_header;\n";
         print CF "\$hide_auth_header         = $hide_auth_header;\n";
-    # boolean
-        print CF "\$allow_thread_sort        = $allow_thread_sort;\n";
-    # boolean
-        print CF "\$allow_server_sort        = $allow_server_sort;\n";
-    # boolean
+        # boolean
+        print CF "\$disable_thread_sort      = $disable_thread_sort;\n";
+        # boolean
+        print CF "\$disable_server_sort      = $disable_server_sort;\n";
+        # boolean
         print CF "\$allow_charset_search     = $allow_charset_search;\n";
         print CF "\$allow_charset_search     = $allow_charset_search;\n";
-    # integer
+        # integer
         print CF "\$allow_advanced_search    = $allow_advanced_search;\n";
         print CF "\n";
         # integer
         print CF "\$time_zone_type           = $time_zone_type;\n";
         print CF "\n";
         print CF "\$allow_advanced_search    = $allow_advanced_search;\n";
         print CF "\n";
         # integer
         print CF "\$time_zone_type           = $time_zone_type;\n";
         print CF "\n";
+        # string
+        print CF "\$config_location_base     = '$config_location_base';\n";
+        print CF "\n";
+        # boolean
+        print CF "\$disable_plugins          = $disable_plugins;\n";
+        # string
+        print CF "\$disable_plugins_user     = '$disable_plugins_user';\n";
+        print CF "\n";
 
 
-    # all plugins are strings
+        # all plugins are strings
         for ( $ct = 0 ; $ct <= $#plugins ; $ct++ ) {
             print CF "\$plugins[] = '$plugins[$ct]';\n";
         }
         print CF "\n";
 
         for ( $ct = 0 ; $ct <= $#plugins ; $ct++ ) {
             print CF "\$plugins[] = '$plugins[$ct]';\n";
         }
         print CF "\n";
 
-    # strings
-        print CF "\$theme_css = " . &change_to_SM_path($theme_css) . ";\n";
-    if ( $theme_default eq '' ) { $theme_default = '0'; }
-        print CF "\$theme_default = $theme_default;\n";
+        # strings
+        if ( $user_theme_default eq '' ) { $user_theme_default = '0'; }
+        print CF "\$user_theme_default = $user_theme_default;\n";
 
 
-        for ( $count = 0 ; $count <= $#theme_name ; $count++ ) {
-            print CF "\$theme[$count]['PATH'] = " . &change_to_SM_path($theme_path[$count]) . ";\n";
+        for ( $count = 0 ; $count <= $#user_theme_name ; $count++ ) {
+            if ($user_theme_path[$count] eq 'none') {
+                $path = '\'none\'';
+            } else {
+                $path = &change_to_SM_path($user_theme_path[$count]);
+            }
+            print CF "\$user_themes[$count]['PATH'] = " . $path . ";\n";
             # escape theme name so it can contain single quotes.
             # escape theme name so it can contain single quotes.
-            $esc_name =  $theme_name[$count];
+            $esc_name =  $user_theme_name[$count];
             $esc_name =~ s/\\/\\\\/g;
             $esc_name =~ s/'/\\'/g;
             $esc_name =~ s/\\/\\\\/g;
             $esc_name =~ s/'/\\'/g;
-            print CF "\$theme[$count]['NAME'] = '$esc_name';\n";
+            print CF "\$user_themes[$count]['NAME'] = '$esc_name';\n";
+        }
+        print CF "\n";
+
+        if ( $icon_theme_def eq '' ) { $icon_theme_def = '0'; }
+        print CF "\$icon_theme_def = $icon_theme_def;\n";
+        if ( $icon_theme_fallback eq '' ) { $icon_theme_fallback = '0'; }
+           print CF "\$icon_theme_fallback = $icon_theme_fallback;\n";
+           
+        for ( $count = 0 ; $count <= $#icon_theme_name ; $count++ ) {
+            $path = $icon_theme_path[$count];
+            if ($path eq 'none' || $path eq 'template') {
+                $path = "'".$path."'";
+            } else {
+                $path = &change_to_SM_path($icon_theme_path[$count]);
+            }
+            print CF "\$icon_themes[$count]['PATH'] = " . $path . ";\n";
+            # escape theme name so it can contain single quotes.
+            $esc_name =  $icon_theme_name[$count];
+            $esc_name =~ s/\\/\\\\/g;
+            $esc_name =~ s/'/\\'/g;
+            print CF "\$icon_themes[$count]['NAME'] = '$esc_name';\n";
+        }
+        print CF "\n";
+
+        if ( $templateset_default eq '' ) { $templateset_default = 'default'; }
+        print CF "\$templateset_default = '$templateset_default';\n";
+
+        if ( $templateset_fallback eq '' ) { $templateset_fallback = 'default'; }
+        print CF "\$templateset_fallback = '$templateset_fallback';\n";
+
+        for ( $count = 0 ; $count <= $#templateset_name ; $count++ ) {
+            print CF "\$aTemplateSet[$count]['ID'] = '" . $templateset_id[$count] . "';\n";
+            # escape theme name so it can contain single quotes.
+            $esc_name =  $templateset_name[$count];
+            $esc_name =~ s/\\/\\\\/g;
+            $esc_name =~ s/'/\\'/g;
+            print CF "\$aTemplateSet[$count]['NAME'] = '$esc_name';\n";
+        }
+        print CF "\n";
+
+
+        # integer
+        print CF "\$default_fontsize = '$default_fontsize';\n";
+        # string
+        print CF "\$default_fontset = '$default_fontset';\n";
+        print CF "\n";
+        # assoc. array (maybe initial value should be set somewhere else)
+        print CF '$fontsets = array();'."\n";
+        while (($fontset_name, $fontset_value) = each(%fontsets)) {
+            print CF "\$fontsets\['$fontset_name'\] = '$fontset_value';\n";
         }
         print CF "\n";
 
         }
         print CF "\n";
 
@@ -3566,28 +4500,28 @@ sub save_data {
         print CF "\$default_use_javascript_addr_book = $default_use_javascript_addr_book;\n";
         for ( $count = 0 ; $count <= $#ldap_host ; $count++ ) {
             print CF "\$ldap_server[$count] = array(\n";
         print CF "\$default_use_javascript_addr_book = $default_use_javascript_addr_book;\n";
         for ( $count = 0 ; $count <= $#ldap_host ; $count++ ) {
             print CF "\$ldap_server[$count] = array(\n";
-        # string
+            # string
             print CF "    'host' => '$ldap_host[$count]',\n";
             print CF "    'host' => '$ldap_host[$count]',\n";
-        # string
+            # string
             print CF "    'base' => '$ldap_base[$count]'";
             if ( $ldap_name[$count] ) {
                 print CF ",\n";
             print CF "    'base' => '$ldap_base[$count]'";
             if ( $ldap_name[$count] ) {
                 print CF ",\n";
-        # string
+                # string
                 print CF "    'name' => '$ldap_name[$count]'";
             }
             if ( $ldap_port[$count] ) {
                 print CF ",\n";
                 print CF "    'name' => '$ldap_name[$count]'";
             }
             if ( $ldap_port[$count] ) {
                 print CF ",\n";
-        # integer
+                # integer
                 print CF "    'port' => $ldap_port[$count]";
             }
             if ( $ldap_charset[$count] ) {
                 print CF ",\n";
                 print CF "    'port' => $ldap_port[$count]";
             }
             if ( $ldap_charset[$count] ) {
                 print CF ",\n";
-        # string
+                # string
                 print CF "    'charset' => '$ldap_charset[$count]'";
             }
             if ( $ldap_maxrows[$count] ) {
                 print CF ",\n";
                 print CF "    'charset' => '$ldap_charset[$count]'";
             }
             if ( $ldap_maxrows[$count] ) {
                 print CF ",\n";
-        # integer
+                # integer
                 print CF "    'maxrows' => $ldap_maxrows[$count]";
             }
             # string
                 print CF "    'maxrows' => $ldap_maxrows[$count]";
             }
             # string
@@ -3620,6 +4554,11 @@ sub save_data {
                 # boolean
                 print CF "    'listing' => $ldap_listing[$count]";
             }
                 # boolean
                 print CF "    'listing' => $ldap_listing[$count]";
             }
+           if ( $ldap_writeable[$count] ) {
+                print CF ",\n";
+                # boolean
+                print CF "    'writeable' => $ldap_writeable[$count]";
+            }
             if ( $ldap_search_tree[$count] ) {
                 print CF ",\n";
                 # integer
             if ( $ldap_search_tree[$count] ) {
                 print CF ",\n";
                 # integer
@@ -3635,89 +4574,82 @@ sub save_data {
             print CF "\n";
         }
 
             print CF "\n";
         }
 
-    # string
+        # string
         print CF "\$addrbook_dsn = '$addrbook_dsn';\n";
         print CF "\$addrbook_dsn = '$addrbook_dsn';\n";
-    # string
+        # string
         print CF "\$addrbook_table = '$addrbook_table';\n\n";
         print CF "\$addrbook_table = '$addrbook_table';\n\n";
-    # string
+        # string
         print CF "\$prefs_dsn = '$prefs_dsn';\n";
         print CF "\$prefs_dsn = '$prefs_dsn';\n";
-    # string
+        # string
         print CF "\$prefs_table = '$prefs_table';\n";
         print CF "\$prefs_table = '$prefs_table';\n";
-    # string
+        # string
         print CF "\$prefs_user_field = '$prefs_user_field';\n";
         print CF "\$prefs_user_field = '$prefs_user_field';\n";
-    # integer
+        # integer
         print CF "\$prefs_user_size = $prefs_user_size;\n";
         print CF "\$prefs_user_size = $prefs_user_size;\n";
-    # string
+        # string
         print CF "\$prefs_key_field = '$prefs_key_field';\n";
         print CF "\$prefs_key_field = '$prefs_key_field';\n";
-    # integer
+        # integer
         print CF "\$prefs_key_size = $prefs_key_size;\n";
         print CF "\$prefs_key_size = $prefs_key_size;\n";
-    # string
+        # string
         print CF "\$prefs_val_field = '$prefs_val_field';\n";
         print CF "\$prefs_val_field = '$prefs_val_field';\n";
-    # integer
+        # integer
         print CF "\$prefs_val_size = $prefs_val_size;\n\n";
         print CF "\$prefs_val_size = $prefs_val_size;\n\n";
-    # string
+        # string
         print CF "\$addrbook_global_dsn = '$addrbook_global_dsn';\n";
         print CF "\$addrbook_global_dsn = '$addrbook_global_dsn';\n";
-    # string
+        # string
         print CF "\$addrbook_global_table = '$addrbook_global_table';\n";
         print CF "\$addrbook_global_table = '$addrbook_global_table';\n";
-    # boolean
+        # boolean
         print CF "\$addrbook_global_writeable = $addrbook_global_writeable;\n";
         print CF "\$addrbook_global_writeable = $addrbook_global_writeable;\n";
-    # boolean
+        # boolean
         print CF "\$addrbook_global_listing = $addrbook_global_listing;\n\n";
         print CF "\$addrbook_global_listing = $addrbook_global_listing;\n\n";
-    # string
+        # string
         print CF "\$abook_global_file = '$abook_global_file';\n";
         print CF "\$abook_global_file = '$abook_global_file';\n";
-    # boolean
+        # boolean
         print CF "\$abook_global_file_writeable = $abook_global_file_writeable;\n\n";
         print CF "\$abook_global_file_writeable = $abook_global_file_writeable;\n\n";
-    # boolean
+        # boolean
         print CF "\$abook_global_file_listing = $abook_global_file_listing;\n\n";
         print CF "\$abook_global_file_listing = $abook_global_file_listing;\n\n";
-    # boolean
+        # integer
+        print CF "\$abook_file_line_length = $abook_file_line_length;\n\n";
+        # boolean
         print CF "\$no_list_for_subscribe = $no_list_for_subscribe;\n";
 
         print CF "\$no_list_for_subscribe = $no_list_for_subscribe;\n";
 
-    # string
+        # string
         print CF "\$smtp_auth_mech = '$smtp_auth_mech';\n";
         print CF "\$smtp_auth_mech = '$smtp_auth_mech';\n";
-    # string
+        print CF "\$smtp_sitewide_user = '". quote_single($smtp_sitewide_user) ."';\n";
+        print CF "\$smtp_sitewide_pass = '". quote_single($smtp_sitewide_pass) ."';\n";
+        # string
         print CF "\$imap_auth_mech = '$imap_auth_mech';\n";
         print CF "\$imap_auth_mech = '$imap_auth_mech';\n";
-    # boolean
+        # boolean
         print CF "\$use_imap_tls = $use_imap_tls;\n";
         print CF "\$use_imap_tls = $use_imap_tls;\n";
-    # boolean
+        # boolean
         print CF "\$use_smtp_tls = $use_smtp_tls;\n";
         print CF "\$use_smtp_tls = $use_smtp_tls;\n";
-    # string
+        # string
         print CF "\$session_name = '$session_name';\n";
 
         print CF "\$session_name = '$session_name';\n";
 
-    print CF "\n";
-
-    # boolean
-    print CF "\$advanced_tree = $advanced_tree;\n";
-    print CF "\n";
-    # boolean
-    print CF "\$use_iframe = $use_iframe;\n";
-    print CF "\n";
-    # boolean
-    print CF "\$use_icons = $use_icons;\n";
-    print CF "\n";
-    # boolean
-    print CF "\$use_php_recode = $use_php_recode;\n";
-    print CF "\n";
-    # boolean
-    print CF "\$use_php_iconv = $use_php_iconv;\n";
-    print CF "\n";
-    # boolean
-    print CF "\$allow_remote_configtest = $allow_remote_configtest;\n";
-    print CF "\n";
-
-        print CF "\@include SM_PATH . 'config/config_local.php';\n";
-
-        print CF "\n/**\n";
-        print CF " * Make sure there are no characters after the PHP closing\n";
-        print CF " * tag below (including newline characters and whitespace).\n";
-        print CF " * Otherwise, that character will cause the headers to be\n";
-        print CF " * sent and regular output to begin, which will majorly screw\n";
-        print CF " * things up when we try to send more headers later.\n";
-        print CF " */\n";
-        print CF "?>";
+        print CF "\n";
+
+        # boolean
+        print CF "\$use_iframe = $use_iframe;\n";
+        print CF "\n";
+        # boolean
+        print CF "\$use_icons = $use_icons;\n";
+        print CF "\n";
+        # boolean
+        print CF "\$use_php_recode = $use_php_recode;\n";
+        print CF "\n";
+        # boolean
+        print CF "\$use_php_iconv = $use_php_iconv;\n";
+        print CF "\n";
+        # boolean
+        print CF "\$allow_remote_configtest = $allow_remote_configtest;\n";
+        print CF "\n";
 
         close CF;
 
         print "Data saved in config.php\n";
 
         close CF;
 
         print "Data saved in config.php\n";
+
+        build_plugin_hook_array();
+
     } else {
         print "Error saving config.php: $!\n";
     }
     } else {
         print "Error saving config.php: $!\n";
     }
@@ -3744,15 +4676,7 @@ sub set_defaults {
     $continue = 0;
     while ( $continue != 1 ) {
         print "Please select your IMAP server:\n";
     $continue = 0;
     while ( $continue != 1 ) {
         print "Please select your IMAP server:\n";
-        print "    bincimap    = Binc IMAP server\n";
-        print "    courier     = Courier IMAP server\n";
-        print "    cyrus       = Cyrus IMAP server\n";
-        print "    dovecot     = Dovecot Secure IMAP server\n";
-        print "    exchange    = Microsoft Exchange IMAP server\n";
-        print "    hmailserver = hMailServer\n";
-        print "    macosx      = Mac OS X Mailserver\n";
-        print "    mercury32   = Mercury/32\n";
-        print "    uw          = University of Washington's IMAP server\n";
+        print $list_supported_imap_servers;
         print "\n";
         print "    quit        = Do not change anything\n";
         print "\n";
         print "\n";
         print "    quit        = Do not change anything\n";
         print "\n";
@@ -3777,6 +4701,9 @@ sub set_defaults {
             $disp_default_folder_prefix     = "<none>";
             $force_username_lowercase       = false;
 
             $disp_default_folder_prefix     = "<none>";
             $force_username_lowercase       = false;
 
+            # Delimiter might differ if unixhierarchysep is set to yes.
+            $message = "\nIf you have enabled unixhierarchysep, you must change delimiter and special folder names.\n";
+
             $continue = 1;
         } elsif ( $server eq "uw" ) {
             $imap_server_type               = "uw";
             $continue = 1;
         } elsif ( $server eq "uw" ) {
             $imap_server_type               = "uw";
@@ -4002,6 +4929,7 @@ sub change_to_rel_path() {
     my $new_path = $old_path;
 
     if ( $old_path =~ /^SM_PATH/ ) {
     my $new_path = $old_path;
 
     if ( $old_path =~ /^SM_PATH/ ) {
+        # FIXME: the following replacement loses the opening quote mark!
         $new_path =~ s/^SM_PATH . \'/\.\.\//;
         $new_path =~ s/\.\.\/config\///;
     }
         $new_path =~ s/^SM_PATH . \'/\.\.\//;
         $new_path =~ s/\.\.\/config\///;
     }
@@ -4009,13 +4937,16 @@ sub change_to_rel_path() {
     return $new_path;
 }
 
     return $new_path;
 }
 
-sub detect_auth_support {
 # Attempts to auto-detect if a specific auth mechanism is supported.
 # Called by 'command112a' and 'command112b'
 # ARGS: service-name (IMAP or SMTP), host:port, mech-name (ie. CRAM-MD5)
 # Attempts to auto-detect if a specific auth mechanism is supported.
 # Called by 'command112a' and 'command112b'
 # ARGS: service-name (IMAP or SMTP), host:port, mech-name (ie. CRAM-MD5)
-
+sub detect_auth_support {
+    # Try loading IO::Socket
+    unless (eval("use IO::Socket; 1")) {
+        print "Perl IO::Socket module is not available.";
+        return undef;
+    }
     # Misc setup
     # Misc setup
-    use IO::Socket;
     my $service = shift;
     my $host = shift;
     my $mech = shift;
     my $service = shift;
     my $host = shift;
     my $mech = shift;
@@ -4107,3 +5038,234 @@ sub clear_screen() {
         system "clear";
     }
 }
         system "clear";
     }
 }
+
+# checks IMAP mailbox name. Refuses to accept 8bit folders
+# returns 0 (folder name is not correct) or 1 (folder name is correct)
+sub check_imap_folder($) {
+    my $folder_name = shift(@_);
+
+    if ($folder_name =~ /[\x80-\xFFFF]/) {
+        print "Folder name contains 8bit characters. Configuration utility requires\n";
+        print "UTF7-IMAP encoded folder names.\n";
+        print "Press enter to continue...";
+        my $tmp = <STDIN>;
+        return 0;
+    } elsif ($folder_name =~ /[&\*\%]/) {
+        # check for ampersand and list-wildcards
+        print "Folder name contains special UTF7-IMAP characters.\n";
+        print "Are you sure that folder name is correct? (yN): ";
+        my $tmp = <STDIN>;
+        $tmp = lc(trim($tmp));
+        if ($tmp =~ /^y$/) {
+            return 1;
+        } else {
+            return 0;
+        }
+    } else {
+        return 1;
+    }
+}
+
+# quotes string written in single quotes
+sub quote_single($) {
+    my $string = shift(@_);
+    $string =~ s/\'/\\'/g;
+    return $string;
+}
+
+# parses the setup.php files for all activated plugins and
+# builds static plugin hooks array so we don't have to load
+# ALL plugins are runtime and build the hook array on every
+# page request
+#
+# hook array is saved in config/plugin_hooks.php
+#
+# Note the $verbose variable at the top of this routine
+# can be set to zero to quiet it down.
+#
+# NOTE/FIXME: we aren't necessarily interested in writing
+#             a full-blown PHP parsing engine, so plenty
+#             of assumptions are included herein about the
+#             coding of the plugin setup files, and things
+#             like commented out curly braces or other 
+#             such oddities can break this in a bad way.
+#
+sub build_plugin_hook_array() {
+
+    $verbose = 1;
+
+    if ($verbose) {
+        print "\n\n";
+    }
+
+    if ( open( HOOKFILE, ">plugin_hooks.php" ) ) {
+        print HOOKFILE "<?php\n";
+        print HOOKFILE "\n";
+
+        print HOOKFILE "/**\n";
+        print HOOKFILE " * SquirrelMail Plugin Hook Registration File\n";
+        print HOOKFILE " * Auto-generated using the configure script, conf.pl\n";
+        print HOOKFILE " */\n";
+        print HOOKFILE "\n";
+        print HOOKFILE "global \$squirrelmail_plugin_hooks;\n";
+        print HOOKFILE "\n";
+
+PLUGIN: for ( $ct = 0 ; $ct <= $#plugins ; $ct++ ) {
+
+        if ($verbose) {
+            print "Activating plugin \"" . $plugins[$ct] . "\"...\n";
+        }
+
+        $setup_file = '../plugins/' . $plugins[$ct] . '/setup.php';
+        if ( -e "$setup_file" ) {
+            # Make sure that file is readable
+            if (! -r "$setup_file") {
+                print "\n";
+                print "WARNING:\n";
+                print "The file \"$setup_file\" was found, but you don't\n";
+                print "have rights to read it.  The plugin \"";
+                print $plugins[$ct] . "\" will not be activated until you fix this.\n";
+                print "\nPress enter to continue";
+                $ctu = <STDIN>;
+                print "\n";
+                next;
+            }
+            open( FILE, "$setup_file" );
+            $inside_init_fxn = 0;
+            $brace_count = 0;
+            while ( $line = <FILE> ) {
+
+                # throw away lines until we get to target function
+                #
+                if (!$inside_init_fxn 
+                 && $line !~ /^\s*function\s*squirrelmail_plugin_init_/i) {
+                    next;
+                } 
+                $inside_init_fxn = 1;
+
+
+                # count open braces
+                #
+                if ($line =~ /{/) {
+                    $brace_count++;
+                } 
+
+
+                # count close braces
+                #
+                if ($line =~ /}/) {
+                    $brace_count--;
+
+                    # leaving <plugin>_init() function...
+                    if ($brace_count == 0) {
+                        close(FILE);
+                        next PLUGIN;
+                    }
+
+                } 
+
+
+                # throw away lines that are not exactly one "brace set" deep
+                #
+                if ($brace_count > 1) { 
+                    next;
+                } 
+
+
+                # also not interested in lines that are not
+                # hook registration points
+                #
+                if ($line !~ /^\s*\$squirrelmail_plugin_hooks/i) {
+                    next;
+                } 
+
+
+                # if $line does not have an ending semicolon,
+                # we need to recursively read in subsequent 
+                # lines until we find one
+                while ( $line !~ /;\s*$/ ) {
+                    $line =~ s/[\n\r]\s*$//;
+                    $line .= <FILE>;
+                }
+
+
+                $line =~ s/^\s+//;
+                $line =~ s/^\$//;
+                $var = $line;
+
+                $var =~ s/=/EQUALS/;
+                if ( $var =~ /^([a-z])/i ) {
+                    @options = split ( /\s*EQUALS\s*/, $var );
+                    $options[1] =~ s/[\n\r]//g;
+                    $options[1] =~ s/[\'\"];\s*$//;
+                    $options[1] =~ s/;$//;
+                    $options[1] =~ s/^[\'\"]//;
+                    # de-escape escaped strings
+                    $options[1] =~ s/\\'/'/g;
+                    $options[1] =~ s/\\\\/\\/g;
+
+                    if ( $options[0] =~ /^squirrelmail_plugin_hooks\s*\[\s*['"]([a-z0-9 \/._*-]+)['"]\s*\]\s*\[\s*['"]([0-9a-z._-]+)['"]\s*\]/i ) {
+                        $hook_name = $1;
+                        $hooked_plugin_name = $2;
+                        # Note: if we wanted to stop plugins from registering
+                        #       a *different* plugin on a hook, we could catch
+                        #       it here, however this has actually proven to be
+                        #       a useful *feature*
+                        #if ($hooked_plugin_name ne $plugins[$ct]) {
+                        #    print "...plugin is tring to hook in under different name...\n";
+                        #}
+
+#FIXME: do we want to count the number of hook registrations for each plugin and warn if a plugin doesn't have any?
+                        # hook registration has been found!
+                        if ($verbose) {
+                            if ($hooked_plugin_name ne $plugins[$ct]) {
+                                print "   registering on hook \"" . $hook_name . "\" (as \"$hooked_plugin_name\" plugin)\n";
+                            } else {
+                                print "   registering on hook \"" . $hook_name . "\"\n";
+                            }
+                        }
+                        $line =~ s/ {2,}/ /g;
+                        $line =~ s/=/\n    =/;
+                        print HOOKFILE "\$$line";
+
+                    }
+
+                }
+
+            }
+            close(FILE);
+
+        } else {
+            print "\n";
+            print "WARNING:\n";
+            print "The file \"$setup_file\" was not found.\n";
+            print "The plugin \"" . $plugins[$ct];
+            print "\" will not be activated until you fix this.\n";
+            print "\nPress enter to continue";
+            $ctu = <STDIN>;
+            print "\n";
+            next;
+        }
+
+    }
+
+    print HOOKFILE "\n\n";
+    close(HOOKFILE);
+#    if ($verbose) {
+        print "\nDone activating plugins; registration data saved in plugin_hooks.php\n\n";
+#    }
+
+    } else {
+
+        print "\n";
+        print "WARNING:\n";
+        print "The file \"plugin_hooks.php\" was not able to be written to.\n";
+        print "No plugins will be activated until you fix this.\n";
+        print "\nPress enter to continue";
+        $ctu = <STDIN>;
+        print "\n";
+
+    }
+
+}
+