[LON-CAPA-cvs] cvs: loncom /auth lonlogin.pm /interface domainprefs.pm loncommon.pm /lonnet/perl lonnet.pm

raeburn lon-capa-cvs-allow@mail.lon-capa.org
Tue, 03 Apr 2007 18:47:30 -0000


This is a MIME encoded message

--raeburn1175626050
Content-Type: text/plain

raeburn		Tue Apr  3 14:47:30 2007 EDT

  Modified files:              
    /loncom/interface	domainprefs.pm loncommon.pm 
    /loncom/auth	lonlogin.pm 
    /loncom/lonnet/perl	lonnet.pm 
  Log:
  - domainprefs.pm
     - DCs can modify font colors, background colors and images for login page and also for defaults for different roles (student, coordinator, author, admin).
     - default settings (from /home/httpd/lonTabs/lonDomColors/default.tab) displayed if no custom choices made.
     - thumbnail images shown for both custom images and defaults
     - uploaded files stored in portfolio for domain config user (username: $dom-domainconfig), with indefinite public access permissions
     - $dom-domainconfig user created if not present
  
  - loncommon.pm
    - Only default.tab file is now read from /home/httpd/lonTabs/lonDomColors.
    - defaults available in global hash: %Apache::loncommon::defaultdesign
    - &designparm() now gets custom settings for a specific domain from lonnet::get_domainconf($domain)
    - In &bodytag(), top frame rendering only uses $lonhttpdPort for images served from /adm, i.e., defaults.
    - Domain logo information now from config data from lonnet::get_domainconf($domain)
  
  - lonlogin.pm
    - Display of Course Catalog link (default is display) and Server Administrator Email address (default is no display) now determined from domain configuration set for domain.
  
  - lonnet.pm
    - get_domainconf() retrieves domain configuration.  Caching used (1800s lifetime).
        if configuration.db exists for primary library server in domain data from there,
            otherwise from /home/httpd/lonTabs/lonDomColors/$dom.tab (if one exists)
    - &get_dom() and &put_dom() can now take a fourth optional argument ($uhome) to allow domain data to be retrieved/stored in .db on specified host server ($uhome) in domain.
        Default is the primary library server in the domain.
    - &userfileupload() and &finishuserfileupload() can now accept to additional optional arguments (width and height in pixels for a thumbnail image to be stored for the uploaded file).
    - thumbnail is stored in same directory as full size image, and is named with a tn- prepended to the name of the full size image.
    - documentation updated for &get_dom and &put_dom().
  
  
  
--raeburn1175626050
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20070403144730.txt"

Index: loncom/interface/domainprefs.pm
diff -u loncom/interface/domainprefs.pm:1.5 loncom/interface/domainprefs.pm:1.6
--- loncom/interface/domainprefs.pm:1.5	Wed Mar  7 20:58:44 2007
+++ loncom/interface/domainprefs.pm	Tue Apr  3 14:47:23 2007
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Handler to set domain-wide configuration settings
 #
-# $Id: domainprefs.pm,v 1.5 2007/03/08 01:58:44 albertel Exp $
+# $Id: domainprefs.pm,v 1.6 2007/04/03 18:47:23 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -37,6 +37,7 @@
 use Apache::lonhtmlcommon();
 use Apache::lonlocal;
 use LONCAPA();
+use LONCAPA::Enrollment;
 
 sub handler {
     my $r=shift;
@@ -64,15 +65,26 @@
         $phase = $env{'form.phase'};
     }
     my %domconfig =
-      &Apache::lonnet::get_dom('configuration',['login','quotas',
-                               'autoenroll','autoupdate'],$dom);
-
+      &Apache::lonnet::get_dom('configuration',['login','rolecolors',
+                               'quotas','autoenroll','autoupdate'],$dom);
     my @prefs = (
+      { text => 'Default color schemes',
+        help => 'Default_Color_Schemes',
+        action => 'rolecolors',
+        header => [{col1 => 'Student Settings',
+                    col2 => '',},
+                   {col1 => 'Coordinator Settings',
+                    col2 => '',},
+                   {col1 => 'Author Settings',
+                    col2 => '',},
+                   {col1 => 'Administrator Settings',
+                    col2 => '',}],
+        },
       { text => 'Log-in page options',
         help => 'Domain_Log-in_Page',
         action => 'login',
         header => [{col1 => 'Item',
-                    col2 => 'Selection',}],
+                    col2 => '',}],
         },
       { text => 'Default quotas for user portfolios',
         help => 'Default_User_Quota',
@@ -95,6 +107,7 @@
                     col2 => 'Updataeable user data'}],
       },
     );
+    my @roles = ('student','coordinator','author','admin');
     &Apache::lonhtmlcommon::add_breadcrumb
     ({href=>"javascript:changePage(document.$phase,'display')",
       text=>"Domain Configuration"});
@@ -105,7 +118,7 @@
         &print_header($r,$phase);
         foreach my $item (@prefs) {
             $r->print('<h3>'.&mt($item->{'text'}).'</h3>'.
-                   &process_changes($dom,$item->{'action'},%domconfig));
+                   &process_changes($r,$dom,$item->{'action'},\@roles,%domconfig));
         }
         $r->print('<p>');
         &print_footer($r,$phase,'display','Back to actions menu');
@@ -119,11 +132,11 @@
         &print_header($r,$phase);
         $r->print('<table border="0" width="100%" cellpadding="2" cellspacing="4"><tr><td align="left" valign="top" width="45%">');
         foreach my $item (@prefs) {
-            if ($item->{'action'} eq 'autoupdate') {
+            if ($item->{'action'} eq 'login') {
                 $r->print('</td><td width="6%">&nbsp;</td><td align="left" valign="top" width="47%">');
             }
-            &print_config_box($r,$dom,$item->{'action'},$item,
-                              $domconfig{$item->{'action'}});
+            &print_config_box($r,$dom,$phase,$item->{'action'},
+                              $item,$domconfig{$item->{'action'}});
         }
         $r->print('
            </table>
@@ -139,10 +152,12 @@
 }
 
 sub process_changes {
-    my ($dom,$action,%domconfig) = @_;
+    my ($r,$dom,$action,$roles,%domconfig) = @_;
     my $output;
     if ($action eq 'login') {
-        $output = &modify_login($dom,%domconfig);
+        $output = &modify_login($r,$dom,%domconfig);
+    } elsif ($action eq 'rolecolors') {
+        $output = &modify_rolecolors($r,$dom,$roles,%domconfig);
     } elsif ($action eq 'quotas') {
         $output = &modify_quotas($dom,%domconfig);
     } elsif ($action eq 'autoenroll') {
@@ -154,23 +169,29 @@
 }
 
 sub print_config_box {
-    my ($r,$dom,$action,$item,$settings) = @_;
+    my ($r,$dom,$phase,$action,$item,$settings) = @_;
     $r->print('
          <table class="LC_nested_outer">
           <tr>
            <th>'.&mt($item->{text}).'&nbsp;'.
            &Apache::loncommon::help_open_topic($item->{'help'}).'</th>
           </tr>');
-    if ($action eq 'autoupdate') {
+    if (($action eq 'autoupdate') || ($action eq 'rolecolors')) {
+        my $colspan = ($action eq 'rolecolors')?' colspan="2"':'';
         $r->print('
           <tr>
            <td>
             <table class="LC_nested">
              <tr class="LC_info_row">
-              <td class="LC_left_item">'.$item->{'header'}->[0]->{'col1'}.'</td>
+              <td class="LC_left_item"'.$colspan.'>'.$item->{'header'}->[0]->{'col1'}.'</td>
               <td class="LC_right_item">'.$item->{'header'}->[0]->{'col2'}.'</td>
-             </tr>'.
-        &print_autoupdate('top',$dom,$settings).'
+             </tr>');
+        if ($action eq 'autoupdate') {
+            $r->print(&print_autoupdate('top',$dom,$settings));
+        } else {
+            $r->print(&print_rolecolors($phase,'student',$dom,$settings));
+        }
+        $r->print('
            </table>
           </td>
          </tr>
@@ -178,21 +199,54 @@
            <td>
             <table class="LC_nested">
              <tr class="LC_info_row">
-              <td class="LC_left_item">'.$item->{'header'}->[1]->{'col1'}.'</td>
+              <td class="LC_left_item"'.$colspan.'>'.$item->{'header'}->[1]->{'col1'}.'</td>
               <td class="LC_right_item">'.$item->{'header'}->[1]->{'col2'}.'</td>
+             </tr>');
+        if ($action eq 'autoupdate') {
+            $r->print(&print_autoupdate('bottom',$dom,$settings));
+        } else {
+            $r->print(&print_rolecolors($phase,'coordinator',$dom,$settings).'
+           </table>
+          </td>
+         </tr>
+         <tr>
+           <td>
+            <table class="LC_nested">
+             <tr class="LC_info_row">
+              <td class="LC_left_item"'.$colspan.'>'.$item->{'header'}->[2]->{'col1'}.'</td>
+              <td class="LC_right_item">'.$item->{'header'}->[2]->{'col2'}.'</td>
              </tr>'.
-        &print_autoupdate('bottom',$dom,$settings));
+            &print_rolecolors($phase,'author',$dom,$settings).'
+           </table>
+          </td>
+         </tr>
+         <tr>
+           <td>
+            <table class="LC_nested">
+             <tr class="LC_info_row">
+              <td class="LC_left_item"'.$colspan.'>'.$item->{'header'}->[3]->{'col1'}.'</td>
+              <td class="LC_right_item">'.$item->{'header'}->[3]->{'col2'}.'</td>
+             </tr>'.
+            &print_rolecolors($phase,'admin',$dom,$settings));
+        }
     } else {
         $r->print('
           <tr>
            <td>
             <table class="LC_nested">
-             <tr class="LC_info_row">
-              <td class="LC_left_item">'.$item->{'header'}->[0]->{'col1'}.'</td>
+             <tr class="LC_info_row">');
+        if ($action eq 'login') {
+            $r->print('  
+              <td class="LC_left_item" colspan="2">'.$item->{'header'}->[0]->{'col1'}.'</td>');
+        } else {
+            $r->print('
+              <td class="LC_left_item">'.$item->{'header'}->[0]->{'col1'}.'</td>');
+        }
+        $r->print('
               <td class="LC_right_item">'.$item->{'header'}->[0]->{'col2'}.'</td>
              </tr>');
         if ($action eq 'login') {
-           $r->print(&print_login($settings));
+           $r->print(&print_login($dom,$phase,$settings));
         } elsif ($action eq 'quotas') {
            $r->print(&print_quotas($dom,$settings));
         } elsif ($action eq 'autoenroll') {
@@ -209,18 +263,28 @@
 
 sub print_header {
     my ($r,$phase) = @_;
-    my $js = qq|
+    my $js = '
 <script type="text/javascript">
 function changePage(formname,newphase) {
     formname.phase.value = newphase;
     formname.submit();
 }
+'.
+&color_pick_js().'
 </script>
-|;
+';
     $r->print(&Apache::loncommon::start_page('View/Modify Domain Settings',
                                            $js));
     $r->print(&Apache::lonhtmlcommon::breadcrumbs('Domain Settings'));
-    $r->print('<form method="post" name="'.$phase.'" action="/adm/domainprefs">');
+    $r->print('
+<form name="parmform">
+<input type="hidden" name="pres_marker" />
+<input type="hidden" name="pres_type" />
+<input type="hidden" name="pres_value" />
+</form>
+');
+    $r->print('<form method="post" name="'.$phase.'" action="/adm/domainprefs"'.
+              ' enctype="multipart/form-data">');
     return;
 }
 
@@ -241,11 +305,29 @@
 }
 
 sub print_login {
-    my ($settings) = @_;
-    my $catalogon = ' checked="checked" ';
-    my $catalogoff;
-    my $adminmailon = ' ';
-    my $adminmailoff = ' checked="checked" ';
+    my ($dom,$phase,$settings) = @_;
+    my %choices = &login_choices();
+    my ($catalogon,$catalogoff,$adminmailon,$adminmailoff);
+    $catalogon = ' checked="checked" ';
+    $adminmailoff = ' checked="checked" ';
+    my @images = ('img','logo','domlogo');
+    my @bgs = ('pgbg','mainbg','sidebg');
+    my @links = ('link','alink','vlink');
+    my %designhash = &Apache::lonnet::get_domainconf($dom);
+    my %defaultdesign = %Apache::loncommon::defaultdesign;
+    my (%is_custom,%designs);
+    my %defaults = (
+                   font => $defaultdesign{'login.font'},
+                   );
+    foreach my $item (@images) {
+        $defaults{$item} = $defaultdesign{'login.'.$item};
+    }
+    foreach my $item (@bgs) {
+        $defaults{'bgs'}{$item} = $defaultdesign{'login.'.$item};
+    }
+    foreach my $item (@links) {
+        $defaults{'links'}{$item} = $defaultdesign{'login.'.$item};
+    }
     if (ref($settings) eq 'HASH') {
         if ($settings->{'coursecatalog'} eq '0') {
             $catalogoff = $catalogon;
@@ -255,30 +337,356 @@
             $adminmailon = $adminmailoff;
             $adminmailoff = ' ';
         }
+        foreach my $item (@images) {
+            if ($settings->{$item} ne '') {
+                $designs{$item} = $settings->{$item};
+                $is_custom{$item} = 1;
+            }
+        }
+        if ($settings->{'font'} ne '') {
+            $designs{'font'} = $settings->{'font'};
+            $is_custom{'font'} = 1;
+        }
+        foreach my $item (@bgs) {
+            if ($settings->{$item} ne '') {
+                $designs{'bgs'}{$item} = $settings->{$item};
+                $is_custom{$item} = 1;
+            }
+        }
+        foreach my $item (@links) {
+            if ($settings->{$item} ne '') {
+                $designs{'links'}{$item} = $settings->{$item};
+                $is_custom{$item} = 1;
+            }
+        }
+    } else {
+        $designs{'domlogo'} = '';
+        if (-e '/home/httpd/html/adm/lonDomLogos/'.$dom.'.gif') {
+            $designs{'domlogo'} = '/home/httpd/html/adm/lonDomLogos/'.$dom.'.gif';
+            $is_custom{'domlogo'} = 1;
+        }
+        if ($designhash{$dom.'.login.img'} ne '') {
+            $designs{'img'} = $designhash{$dom.'.login.img'};
+            $is_custom{'img'} = 1;
+        }
+        if ($designhash{$dom.'.login.logo'} ne '') {
+            $designs{'logo'} = $designhash{$dom.'.login.logo'};
+            $is_custom{'logo'} = 1;
+        }
+        if ($designhash{$dom.'.login.font'} ne '') {
+            $designs{'font'} = $designhash{$dom.'.login.font'};
+            $is_custom{'font'} = 1;
+        }
+        foreach my $item (@bgs) {
+            if ($designhash{$dom.'.login.'.$item} ne '') {
+                $designs{'bgs'}{$item} = $designhash{$dom.'.login.'.$item};
+                $is_custom{$item} = 1;
+            }
+        }
+        foreach my $item (@links) {
+            if ($designhash{$dom.'.login.'.$item} ne '') {
+                $designs{'links'}{$item} = $designhash{$dom.'.login.'.$item};
+                $is_custom{$item} = 1;
+            }
+        }
     }
-    my %choices = 
-        &Apache::lonlocal::texthash(
-            coursecatalog => 'Display Course Catalog link?',
-            adminmail => "Display Administrator's E-mail Address?"
-        );
+    my %alt_text = &Apache::lonlocal::texthash  ( img => 'Log-in banner',
+                                                  logo => 'Institution Logo',
+                                                  domlogo => 'Domain Logo');
+    my $itemcount = 1;
+    my $css_class = $itemcount%2?' class="LC_odd_row"':'';
     my $datatable = 
-        '<tr class="LC_odd_row"><td>'.$choices{'coursecatalog'}.
-        '</td><td class="LC_right_item">'.
+        '<tr'.$css_class.'><td colspan="2">'.$choices{'coursecatalog'}.
+        '</td><td>'.
         '<nobr><input type="radio" name="coursecatalog"'.
         $catalogon.' value="1" />'.&mt('Yes').'&nbsp;'.
         '<input type="radio" name="coursecatalog"'.
         $catalogoff.'value="0" />'.&mt('No').'</nobr></td>'.
-        '</tr><tr>'.
-        '<td>'.$choices{'adminmail'}.'</td>'.
-        '<td class="LC_right_item"><nobr>'.
+        '</tr>';
+    $itemcount ++;
+    $css_class = $itemcount%2?' class="LC_odd_row"':'';
+    $datatable .= '<tr'.$css_class.'>'.
+        '<td colspan="2">'.$choices{'adminmail'}.'</td>'.
+        '<td><nobr>'.
         '<input type="radio" name="adminmail"'.
         $adminmailon.' value="1" />'.&mt('Yes').'&nbsp;'.
         '<input type="radio" name="adminmail"'.
-        $adminmailoff.'value="0" />'.&mt('No').'</nobr></td>'.
-        '</tr>';
+        $adminmailoff.'value="0" />'.&mt('No').'</nobr></td>';
+    $itemcount ++;
+    $datatable .= &display_color_options($dom,$phase,'login',$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text);
+    $datatable .= '</tr></table></td></tr>';
+    return $datatable;
+}
+
+sub login_choices {
+    my %choices =
+        &Apache::lonlocal::texthash (
+            coursecatalog => 'Display Course Catalog link?',
+            adminmail => "Display Administrator's E-mail Address?",
+            img => "Header",
+            logo => "Main Logo",
+            domlogo => "Domain Logo",
+            bgs => "Background colors",
+            links => "Link colors",
+            font => "Font color",
+            pgbg => "Page",
+            mainbg => "Main panel",
+            sidebg => "Side panel",
+            link => "Link",
+            alink => "Active link",
+            vlink => "Visited link",
+        );
+    return %choices;
+}
+
+sub print_rolecolors {
+    my ($phase,$role,$dom,$settings) = @_;
+    my %choices = &color_font_choices();
+    my @bgs = ('pgbg','tabbg','sidebg');
+    my @links = ('link','alink','vlink');
+    my @images = ('img');
+    my %alt_text = &Apache::lonlocal::texthash(img => "Banner for $role role");
+    my %designhash = &Apache::lonnet::get_domainconf($dom);
+    my %defaultdesign = %Apache::loncommon::defaultdesign;
+    my (%is_custom,%designs);
+    my %defaults = (
+                   img => $defaultdesign{$role.'.img'},
+                   font => $defaultdesign{$role.'.font'},
+                   );
+    foreach my $item (@bgs) {
+        $defaults{'bgs'}{$item} = $defaultdesign{$role.'.'.$item};
+    }
+    foreach my $item (@links) {
+        $defaults{'links'}{$item} = $defaultdesign{$role.'.'.$item};
+    }
+    if (ref($settings) eq 'HASH') {
+        if (ref($settings->{$role}) eq 'HASH') {
+            if ($settings->{$role}->{'img'} ne '') {
+                $designs{'img'} = $settings->{$role}->{'img'};
+                $is_custom{'img'} = 1;
+            }
+            if ($settings->{$role}->{'font'} ne '') {
+                $designs{'font'} = $settings->{$role}->{'font'};
+                $is_custom{'font'} = 1;
+            }
+            foreach my $item (@bgs) {
+                if ($settings->{$role}->{$item} ne '') {
+                    $designs{'bgs'}{$item} = $settings->{$role}->{$item};
+                    $is_custom{$item} = 1;
+                }
+            }
+            foreach my $item (@links) {
+                if ($settings->{$role}->{$item} ne '') {
+                    $designs{'links'}{$item} = $settings->{$role}->{$item};
+                    $is_custom{$item} = 1;
+                }
+            }
+        }
+    } else {
+        if ($designhash{$dom.'.'.$role.'.img'} ne '') {
+            $designs{img} = $designhash{$dom.'.'.$role.'.img'};
+            $is_custom{'img'} = 1;
+        }
+        if ($designhash{$dom.'.'.$role.'.font'} ne '') {
+            $designs{font} = $designhash{$dom.'.'.$role.'.font'};
+            $is_custom{'font'} = 1;
+        }
+        foreach my $item (@bgs) {
+            if ($designhash{$dom.'.'.$role.'.'.$item} ne '') {
+                $designs{'bgs'}{$item} = $designhash{$dom.'.'.$role.'.'.$item};
+                $is_custom{$item} = 1;
+            
+            }
+        }
+        foreach my $item (@links) {
+            if ($designhash{$dom.'.'.$role.'.'.$item} ne '') {
+                $designs{'links'}{$item} = $designhash{$dom.'.'.$role.'.'.$item};
+                $is_custom{$item} = 1;
+            }
+        }
+    }
+    my $itemcount = 1;
+    my $datatable = display_color_options($dom,$phase,$role,$itemcount,\%choices,\%is_custom,\%defaults,\%designs,\@images,\@bgs,\@links,\%alt_text);
+    $datatable .= '</tr></table></td></tr>';
     return $datatable;
 }
 
+sub display_color_options {
+    my ($dom,$phase,$role,$itemcount,$choices,$is_custom,$defaults,$designs,
+        $images,$bgs,$links,$alt_text) = @_;
+    my $configuname = $dom.'-domainconfig';
+    my $css_class = $itemcount%2?' class="LC_odd_row"':'';
+    my $datatable = '<tr'.$css_class.'>'.
+        '<td>'.$choices->{'font'}.'</td>';
+    if (!$is_custom->{'font'}) {
+        $datatable .=  '<td>'.&mt('Default in use:').'&nbsp;'.$defaults->{'font'}.'</td>';
+    } else {
+        $datatable .= '<td>&nbsp;</td>';
+    }
+    my $fontlink = &color_pick($phase,$role,'font',$choices->{'font'},$designs->{'font'});
+    $datatable .= '<td><nobr>'.
+                  '<input type="text" size="10" name="'.$role.'_font"'.
+                  ' value="'.$designs->{'font'}.'" />&nbsp'.$fontlink.
+                  '</nobr></td></tr>';
+    foreach my $img (@{$images}) {
+        $itemcount ++;
+        $css_class = $itemcount%2?' class="LC_odd_row"':'';
+        $datatable .= '</tr><tr'.$css_class.'>'.
+                      '<td>'.$choices->{$img}.'</td>';
+        my $imgfile;
+        if ($designs->{$img} ne '') {
+            $imgfile = $designs->{$img};
+        } else {
+            $imgfile = $defaults->{$img};
+        }
+        if ($imgfile) {
+            my $showfile;
+            if ($imgfile =~ m-^(/uploaded/\Q$dom\E/\Q$configuname\E/portfolio.*)/([^/]+)$-) {
+                my $urldir = $1;
+                my $filename = $2;
+                my @info = &Apache::lonnet::stat_file($designs->{$img});
+                if (@info) {
+                    my $thumbfile = 'tn-'.$filename;
+                    my @thumb=&Apache::lonnet::stat_file($urldir.'/'.$thumbfile);
+                    if (@thumb) {
+                        $showfile = $urldir.'/'.$thumbfile;
+                    } else {
+                        $showfile = $imgfile;
+                    }
+                } else {
+                    $showfile = '';
+                }
+            } elsif ($imgfile =~ m-^/(adm/[^/]+)/([^/]+)$-) {
+                my $imgdir = $1;
+                my $filename = $2;
+                if (-e "/home/httpd/html/$imgdir/tn-".$filename) {
+                    $showfile = "/$imgdir/tn-".$filename;
+                } else {
+                    my $input = "/home/httpd/html".$imgfile;
+                    my $output = '/home/httpd/html/'.$imgdir.'/tn-'.$filename;
+                    if (!-e $output) {
+                        system("convert -sample 200x50 $input $output");
+                    }
+                    $showfile = '/'.$imgdir.'/tn-'.$filename;
+                }
+            } 
+            if ($showfile) {
+                $datatable.= '<td>';
+                if (!$is_custom->{$img}) {
+                    $datatable .= &mt('Default in use:').'<br />';
+                }
+                $datatable.= '<img src="'.$showfile.'" alt="'.
+                             $alt_text->{$img}.'" /></td>';
+                if ($is_custom->{$img}) {
+                    $datatable.='<td><nobr><input type="checkbox" name="'.$role.'_del_'.$img.'" value="1">'.
+                                &mt('Delete?').'&nbsp;'.&mt('Replace:').'</nobr><br />';
+                } else {
+                    $datatable.='<td valign="bottom">'.&mt('Upload:').'<br />';
+                }
+            } else {
+                $datatable .= '<td colspan="2" class="LC_right_item"><br />'.
+                              &mt('Upload:');
+            }
+        } else {
+            $datatable .= '<td colspan="2" class="LC_right_item"><br />'.
+                          &mt('Upload:');
+        }
+        $datatable .= '&nbsp;<input type="file" name="'.$role.'_'.$img.'" /></nobr></td></tr>';
+    }
+    $itemcount ++;
+    $css_class = $itemcount%2?' class="LC_odd_row"':'';
+    $datatable .= '<tr'.$css_class.'>'.
+                  '<td>'.$choices->{'bgs'}.'</td>';
+    my $bgs_def;
+    foreach my $item (@{$bgs}) {
+        if (!$is_custom->{$item}) {
+            $bgs_def .= '<td>'.$choices->{$item}.'<br />'.$defaults->{'bgs'}{$item}.'</td>';
+        }
+    }
+    if ($bgs_def) {
+        $datatable .= '<td>'.&mt('Default(s) in use').'<br /><table border="0"><tr>'.$bgs_def.'</tr></table></td>';
+    } else {
+        $datatable .= '<td>&nbsp;</td>';
+    }
+    $datatable .= '<td class="LC_right_item">'.
+                  '<table border="0"><tr>';
+    foreach my $item (@{$bgs}) {
+        my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'bgs'}{$item});
+        $datatable .= '<td align="center">'.$link;
+        if ($designs->{'bgs'}{$item}) {
+            $datatable .= '<span style="background-color:'.$designs->{'bgs'}{$item}.'width: 10px">&nbsp;</span>';
+        }
+        $datatable .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.$designs->{'bgs'}{$item}.
+                      '" /></td>';
+    }
+    $datatable .= '</tr></table></td></tr>';
+    $itemcount ++;
+    $css_class = $itemcount%2?' class="LC_odd_row"':'';
+    $datatable .= '<tr'.$css_class.'>'.
+                  '<td>'.$choices->{'links'}.'</td>';
+    my $links_def;
+    foreach my $item (@{$links}) {
+        if (!$is_custom->{$item}) {
+            $links_def .= '<td>'.$choices->{$item}.'<br />'.$defaults->{'links'}{$item}.'</td>';
+        }
+    }
+    if ($links_def) {
+        $datatable .= '<td>'.&mt('Default(s) in use').'<br /><table border="0"><tr>'.$links_def.'</tr></table></td>';
+    } else {
+        $datatable .= '<td>&nbsp;</td>';
+    }
+    $datatable .= '<td class="LC_right_item">'.
+                  '<table border="0"><tr>';
+    foreach my $item (@{$links}) {
+        $datatable .= '<td align="center">';
+        my $link = &color_pick($phase,$role,$item,$choices->{$item},$designs->{'links'}{$item});
+        if ($designs->{'links'}{$item}) {
+            $datatable.='<span style="color: '.$designs->{'links'}{$item}.';">'.
+                        $link.'</span>';
+        } else {
+            $datatable .= $link;
+        }
+        $datatable .= '<br /><input type="text" size="8" name="'.$role.'_'.$item.'" value="'.$designs->{'links'}{$item}.
+                      '" /></td>';
+    }
+    return $datatable;
+}
+
+sub color_pick {
+    my ($phase,$role,$item,$desc,$curcol) = @_;
+    my $link = '<a href="javascript:pjump('."'color_custom','".$desc.
+               "','".$curcol."','".$role.'_'.$item."','parmform.pres','psub'".
+               ');">'.$desc.'</a>';
+    return $link;
+}
+
+sub color_pick_js {
+    my $pjump_def = &Apache::lonhtmlcommon::pjump_javascript_definition();
+    my $output = <<"ENDCOL";
+    function pclose() {
+        parmwin=window.open("/adm/rat/empty.html","LONCAPAparms","height=350,width=350,scrollbars=no,menubar=no");
+        parmwin.close();
+    }
+
+    $pjump_def
+
+    function psub() {
+        pclose();
+        if (document.parmform.pres_marker.value!='') {
+            if (document.parmform.pres_type.value!='') {
+                eval('document.display.'+
+                     document.parmform.pres_marker.value+
+                     '.value=document.parmform.pres_value.value;');
+            }
+        } else {
+            document.parmform.pres_value.value='';
+            document.parmform.pres_marker.value='';
+        }
+    }
+ENDCOL
+    return $output;
+}
+
 sub print_quotas {
     my ($dom,$settings) = @_;
     my $datatable;
@@ -496,16 +904,20 @@
 }
 
 sub modify_login {
-    my ($dom,%domconfig) = @_;
-    my ($resulttext,%changes);
+    my ($r,$dom,%domconfig) = @_;
+    my ($resulttext,$errors,$colchgtext,%changes,%colchanges);
     my %title = ( coursecatalog => 'Display course catalog',
                   adminmail => 'Display administrator E-mail address');
     my @offon = ('off','on');
-    my %loginhash =  (
-                       login => { coursecatalog => $env{'form.coursecatalog'},
-                                  adminmail => $env{'form.adminmail'},
-                                }
-                     );
+    my %loginhash;
+    ($errors,%colchanges) = &modify_colors($r,$dom,['login'],\%domconfig,
+                                          \%loginhash);
+    $loginhash{login}{coursecatalog} = $env{'form.coursecatalog'};
+    $loginhash{login}{adminmail} = $env{'form.adminmail'};
+    if (ref($colchanges{'login'}) eq 'HASH') {  
+        $colchgtext = &display_colorchgs($dom,\%colchanges,['login'],
+                                         \%loginhash);
+    }
     my $putresult = &Apache::lonnet::put_dom('configuration',\%loginhash,
                                              $dom);
     if ($putresult eq 'ok') {
@@ -525,18 +937,248 @@
                  ($env{'form.adminmail'} eq '1')) {
             $changes{'adminmail'} = 1;
         }
-        if (keys(%changes) > 0) {
+        if (keys(%changes) > 0 || $colchgtext) {
             $resulttext = &mt('Changes made:').'<ul>';
             foreach my $item (sort(keys(%changes))) {
                 $resulttext .= '<li>'.&mt("$title{$item} set to $offon[$env{'form.'.$item}]").'</li>';
             }
-            $resulttext .= '</ul>';
+            $resulttext .= $colchgtext.'</ul>';
         } else {
             $resulttext = &mt('No changes made to log-in page settings');
         }
     } else {
         $resulttext = &mt('An error occurred: [_1]',$putresult);
     }
+    if ($errors) {
+        $resulttext .= &mt('The following errors occurred: ').'<ul>'.
+                       $errors.'</ul>';
+    }
+    return $resulttext;
+}
+
+sub color_font_choices {
+    my %choices =
+        &Apache::lonlocal::texthash (
+            img => "Header",
+            bgs => "Background colors",
+            links => "Link colors",
+            font => "Font color",
+            pgbg => "Page",
+            tabbg => "Header",
+            sidebg => "Border",
+            link => "Link",
+            alink => "Active link",
+            vlink => "Visited link",
+        );
+    return %choices;
+}
+
+sub modify_rolecolors {
+    my ($r,$dom,$roles,%domconfig) = @_;
+    my ($resulttext,%rolehash);
+    $rolehash{'rolecolors'} = {};
+    my ($errors,%changes) = &modify_colors($r,$dom,$roles,
+                         $domconfig{'rolecolors'},$rolehash{'rolecolors'});
+    my $putresult = &Apache::lonnet::put_dom('configuration',\%rolehash,
+                                             $dom);
+    if ($putresult eq 'ok') {
+        if (keys(%changes) > 0) {
+            $resulttext = &display_colorchgs($dom,\%changes,$roles,
+                                             $rolehash{'rolecolors'});
+        } else {
+            $resulttext = &mt('No changes made to default color schemes');
+        }
+    } else {
+        $resulttext = &mt('An error occurred: [_1]',$putresult);
+    }
+    if ($errors) {
+        $resulttext .= &mt('The following errors occurred: ').'<ul>'.
+                       $errors.'</ul>';
+    }
+    return $resulttext;
+}
+
+sub modify_colors {
+    my ($r,$dom,$roles,$domconfig,$confhash) = @_;
+    my %changes;
+    my @bgs = ('pgbg','mainbg','sidebg');
+    my @links = ('link','alink','vlink');
+    my @images;
+    my $configuname = $dom.'-domainconfig';
+    my $servadm = $r->dir_config('lonAdmEMail');
+    my $errors;
+    foreach my $role (@{$roles}) {
+        if ($role eq 'login') {
+            @images = ('img','logo','domlogo');
+        } else {
+            @images = ('img');
+        }
+        $confhash->{$role}{'font'} = $env{'form.'.$role.'_font'};
+        foreach my $item (@bgs,@links) {
+            $confhash->{$role}{$item} = $env{'form.'.$role.'_'.$item};
+        }
+        foreach my $img (@images) { 
+            if ($env{'form.'.$role.'_'.$img.'.filename'} ne '') {
+                my $configuserok; 
+                if (&Apache::lonnet::homeserver($configuname,$dom) eq 'no_host') {
+                    srand( time() ^ ($$ + ($$ << 15))  ); # Seed rand.
+                    my $configpass = &LONCAPA::Enrollment::create_password();
+                    $configuserok = &Apache::lonnet::modifyuser($dom,$configuname,'','internal',$configpass,'','','','','',undef,$servadm);
+                } else {
+                    $configuserok = 'ok';
+                }
+                if ($configuserok eq 'ok') {
+                    my $result = 
+                      &Apache::lonnet::userfileupload($role.'_'.$img,'',
+                        'portfolio/'.$img,'','','',$configuname,$dom,'200','50');
+                    if ($result =~ m|(^/uploaded/.+)/([^/]+)$|) {
+                        my $urldir = $1;
+                        my $filename = $2; 
+                        my $allowresult = &Apache::lonnet::make_public_indefinitely($result);
+                        if ($allowresult eq 'ok') {
+                            &Apache::lonnet::make_public_indefinitely($urldir.'/tn-'.$filename);
+                            $confhash->{$role}{$img} = $result;
+                            $changes{$role}{$img} = 1;
+                        }
+                    }
+                } else {
+                    my $error = &mt("Upload of image [_1] for $role page(s) failed because a Domain Configuation user ([_2]) could not be created in domain: [_3].  Error was: [_4].",$img,$configuname,$dom,$configuserok);
+                   &Apache::lonnet::logthis($error);
+                   $errors .= '<li>'.$error.'</li>';
+                }
+            }
+        }
+        if (ref($domconfig) eq 'HASH') {
+            if (ref($domconfig->{$role}) eq 'HASH') {
+                foreach my $img (@images) {
+                    if ($domconfig->{$role}{$img} ne '') {
+                        if ($env{'form.'.$role.'_del_'.$img}) {
+                            $confhash->{$role}{$img} = '';
+                            $changes{$role}{$img} = 1;
+                        } else {
+                            $confhash->{$role}{$img} = $domconfig->{$role}{$img};
+                        }
+                    } else {
+                        if ($env{'form.'.$role.'_del_'.$img}) {
+                            $confhash->{$role}{$img} = '';
+                            $changes{$role}{$img} = 1;
+                        } 
+                    }
+                }  
+                if ($domconfig->{$role}{'font'} ne '') {
+                    if ($confhash->{$role}{'font'} ne $domconfig->{$role}{'font'}) {
+                        $changes{$role}{'font'} = 1;
+                    }
+                } else {
+                    if ($confhash->{$role}{'font'}) {
+                        $changes{$role}{'font'} = 1;
+                    }
+                }
+                foreach my $item (@bgs) {
+                    if ($domconfig->{$role}{$item} ne '') {
+                        if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) {
+                            $changes{$role}{'bgs'}{$item} = 1;
+                        } 
+                    } else {
+                        if ($confhash->{$role}{$item}) {
+                            $changes{$role}{'bgs'}{$item} = 1;
+                        }
+                    }
+                }
+                foreach my $item (@links) {
+                    if ($domconfig->{$role}{$item} ne '') {
+                        if ($confhash->{$role}{$item} ne $domconfig->{$role}{$item}) {
+                            $changes{$role}{'links'}{$item} = 1;
+                        }
+                    } else {
+                        if ($confhash->{$role}{$item}) {
+                            $changes{$role}{'links'}{$item} = 1;
+                        }
+                    }
+                }
+            } else {
+                &default_change_checker($role,\@images,\@links,\@bgs,
+                                        $confhash,\%changes); 
+            }
+        } else {
+            &default_change_checker($role,\@images,\@links,\@bgs,
+                                    $confhash,\%changes); 
+        }
+    }
+    return ($errors,%changes);
+}
+
+sub default_change_checker {
+    my ($role,$images,$links,$bgs,$confhash,$changes) = @_;
+    foreach my $item (@{$links}) {
+        if ($confhash->{$role}{$item}) {
+            $changes->{$role}{'links'}{$item} = 1;
+        }
+    }
+    foreach my $item (@{$bgs}) {
+        if ($confhash->{$role}{$item}) {
+            $changes->{$role}{'bgs'}{$item} = 1;
+        }
+    }
+    foreach my $img (@{$images}) {
+        if ($env{'form.'.$role.'_del_'.$img}) {
+            $confhash->{$role}{$img} = '';
+            $changes->{$role}{$img} = 1;
+        }
+    }
+    if ($confhash->{$role}{'font'}) {
+        $changes->{$role}{'font'} = 1;
+    }
+} 
+
+sub display_colorchgs {
+    my ($dom,$changes,$roles,$confhash) = @_;
+    my (%choices,$resulttext);
+    &Apache::lonnet::devalidate_domconfig_cache($dom);
+    if (!grep(/^login$/,@{$roles})) {
+        $resulttext = &mt('Changes made:').'<br />';
+    }
+    foreach my $role (@{$roles}) {
+        if ($role eq 'login') {
+            %choices = &login_choices();
+        } else {
+            %choices = &color_font_choices();
+        }
+        if (ref($changes->{$role}) eq 'HASH') {
+            if ($role ne 'login') {
+                $resulttext .= '<h4>'.&mt($role).'</h4>';
+            }
+            foreach my $key (sort(keys(%{$changes->{$role}}))) {
+                if ($role ne 'login') {
+                    $resulttext .= '<ul>';
+                }
+                if (ref($changes->{$role}{$key}) eq 'HASH') {
+                    if ($role ne 'login') {
+                        $resulttext .= '<li>'.&mt($choices{$key}).':<ul>';
+                    }
+                    foreach my $item (sort(keys(%{$changes->{$role}{$key}}))) {
+                        if ($confhash->{$role}{$item} eq '') {
+                            $resulttext .= '<li>'.&mt("$choices{$item} set to default").'</li>';
+                        } else {
+                            $resulttext .= '<li>'.&mt("$choices{$item} set to [_1]",$confhash->{$role}{$item}).'</li>';
+                        }
+                    }
+                    if ($role ne 'login') {
+                        $resulttext .= '</ul></li>';
+                    }
+                } else {
+                    if ($confhash->{$role}{$key} eq '') {
+                        $resulttext .= '<li>'.&mt("$choices{$key} set to default").'</li>';
+                    } else {
+                        $resulttext .= '<li>'.&mt("$choices{$key} set to [_1]",$confhash->{$role}{$key}).'</li>';
+                    }
+                }
+                if ($role ne 'login') {
+                    $resulttext .= '</ul>';
+                }
+            }
+        }
+    }
     return $resulttext;
 }
 
@@ -746,7 +1388,7 @@
                             $newvaluestr = join(', ',@newvalues);
                         } else {
                             $newvaluestr = &mt('none');
-                        }  
+                        }
                         if ($item eq 'default') {
                             $resulttext .= '<li>'.&mt("Updates for $othertitle set to: [_1]",$newvaluestr).'</li>';
                         } else {
Index: loncom/interface/loncommon.pm
diff -u loncom/interface/loncommon.pm:1.516 loncom/interface/loncommon.pm:1.517
--- loncom/interface/loncommon.pm:1.516	Tue Mar 20 11:36:14 2007
+++ loncom/interface/loncommon.pm	Tue Apr  3 14:47:23 2007
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.516 2007/03/20 15:36:14 albertel Exp $
+# $Id: loncommon.pm,v 1.517 2007/04/03 18:47:23 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -68,8 +68,12 @@
 use Apache::lonclonecourse();
 use LONCAPA qw(:DEFAULT :match);
 
+# ---------------------------------------------- Designs
+use vars qw(%defaultdesign);
+
 my $readit;
 
+
 ##
 ## Global Variables
 ##
@@ -82,10 +86,6 @@
 my %fe; my %fd; my %fm;
 my %category_extensions;
 
-# ---------------------------------------------- Designs
-
-my %designhash;
-
 # ---------------------------------------------- Thesaurus variables
 #
 # %Keywords:
@@ -151,30 +151,18 @@
         }
     }
 
-# -------------------------------------------------------------- domain designs
-
-    my $filename;
+# -------------------------------------------------------------- default domain designs
     my $designdir=$Apache::lonnet::perlvar{'lonTabDir'}.'/lonDomColors';
-    opendir(DIR,$designdir);
-    while ($filename=readdir(DIR)) {
-	if ($filename!~/\.tab$/) { next; }
-	my ($domain)=($filename=~/^($match_domain)\./);
-	{
-	    my $designfile = $designdir.'/'.$filename;
-	    if ( open (my $fh,"<$designfile") ) {
-		while (my $line = <$fh>) {
-		    next if ($line =~ /^\#/);
-		    chomp($line);
-		    my ($key,$val)=(split(/\=/,$line));
-		    if ($val) { $designhash{$domain.'.'.$key}=$val; }
-		}
-		close($fh);
-	    }
-	}
-
+    my $designfile = $designdir.'/default.tab';
+    if ( open (my $fh,"<$designfile") ) {
+        while (my $line = <$fh>) {
+            next if ($line =~ /^\#/);
+            chomp($line);
+            my ($key,$val)=(split(/\=/,$line));
+            if ($val) { $defaultdesign{$key}=$val; }
+        }
+        close($fh);
     }
-    closedir(DIR);
-
 
 # ------------------------------------------------------------- file categories
     {
@@ -3184,6 +3172,7 @@
     return $domain;
 }
 ###############################################
+
 =pod
 
 =item * &domainlogo()
@@ -3197,11 +3186,12 @@
 
 ###############################################
 sub domainlogo {
-    my $domain = &determinedomain(shift);    
-     # See if there is a logo
-    if (-e '/home/httpd/html/adm/lonDomLogos/'.$domain.'.gif') {
-	my $logo=&lonhttpdurl("/adm/lonDomLogos/$domain.gif");
-        return '<img src="'.$logo.'" alt="'.$domain.'" />';
+    my $domain = &determinedomain(shift);
+    my %designhash = &Apache::lonnet::get_domainconf($domain);    
+    # See if there is a logo
+    if ($designhash{$domain.'.login.domlogo'} ne '') {
+        return '<img src="'.$designhash{$domain.'.login.domlogo'}.
+               '" alt="'.$domain.'" />';
     } elsif (defined(&Apache::lonnet::domain($domain,'description'))) {
         return &Apache::lonnet::domain($domain,'description');
     } else {
@@ -3239,10 +3229,11 @@
 	return $env{'environment.color.'.$which};
     }
     $domain=&determinedomain($domain);
-    if (exists($designhash{$domain.'.'.$which})) {
-	return $designhash{$domain.'.'.$which};
+    my %domdesign = &Apache::lonnet::get_domainconf($domain);
+    if ($domdesign{$domain.'.'.$which} ne '') {
+	return $domdesign{$domain.'.'.$which};
     } else {
-        return $designhash{'default.'.$which};
+        return $defaultdesign{$which};
     }
 }
 
@@ -3462,8 +3453,11 @@
 # Top frame rendering, Remote is up
 #
 
-    my $upperleft='<img src="http://'.$ENV{'HTTP_HOST'}.':'.
-        $lonhttpdPort.$img.'" alt="'.$function.'" />';
+    my $imgsrc = $img;
+    if ($img =~ /^\/adm/) {
+        $imgsrc = 'http://'.$ENV{'HTTP_HOST'}.':'.$lonhttpdPort.$img;
+    }
+    my $upperleft='<img src="'.$imgsrc.'" alt="'.$function.'" />';
 
     # Explicit link to get inline menu
     my $menu= ($no_inline_link?''
Index: loncom/auth/lonlogin.pm
diff -u loncom/auth/lonlogin.pm:1.89 loncom/auth/lonlogin.pm:1.90
--- loncom/auth/lonlogin.pm:1.89	Wed Mar  7 20:58:48 2007
+++ loncom/auth/lonlogin.pm	Tue Apr  3 14:47:25 2007
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Login Screen
 #
-# $Id: lonlogin.pm,v 1.89 2007/03/08 01:58:48 albertel Exp $
+# $Id: lonlogin.pm,v 1.90 2007/04/03 18:47:25 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -133,6 +133,7 @@
     }
     my $role    = $r->dir_config('lonRole');
     my $loadlim = $r->dir_config('lonLoadLim');
+    my $servadm = $r->dir_config('lonAdmEMail');
     my $lonhost = $r->dir_config('lonHostID');
     my $tabdir  = $r->dir_config('lonTabDir');
     my $include = $r->dir_config('lonIncludes');
@@ -245,8 +246,7 @@
     }
 
 # ----------------------------------------------- Apparently we are in business
-
-    my $domainlogo=&Apache::loncommon::domainlogo($domain);
+    $servadm=~s/\,/\<br \/\>/g;
 
 # --------------------------------------------------- Print login screen header
     $r->print(<<ENDHEADER);
@@ -278,6 +278,11 @@
       ($fullgraph?&Apache::loncommon::designparm('login.sidebg',$domain):'#FFFFFF');
     my $logo=&Apache::loncommon::designparm('login.logo',$domain);
     my $img=&Apache::loncommon::designparm('login.img',$domain);
+    my $domainlogo=&Apache::loncommon::domainlogo($domain);
+    my $showadminmail=&Apache::loncommon::designparm('login.adminmail',                                                      $domain);
+    my $showcoursecat =
+        &Apache::loncommon::designparm('login.coursecatalog',$domain);
+
 
 # ----------------------------------------------------------------------- Texts
 
@@ -295,6 +300,7 @@
 		  'log' => 'Log in',
 		  'help' => 'Log-in Help',
 		  'serv' => 'Server',
+                  'servadm' => 'Server Administration',
                   'helpdesk' => 'Contact Helpdesk',
                   'forgotpw' => 'Forgot password?');
 # -------------------------------------------------- Change password field name
@@ -379,6 +385,10 @@
    <input type="hidden" name="localres" value="$env{'form.localres'}" />
   </form>
 ENDSERVERFORM
+    my $coursecatalog;
+    if (!($showcoursecat == 0)) {
+        $coursecatalog = &coursecatalog_link($lt{'catalog'});
+    }
     if ($fullgraph) { $r->print(<<ENDTOP);
   <!-- The LON-CAPA Header -->
   <tr>
@@ -415,11 +425,7 @@
      <tr>
       <td>&nbsp;</td>
       <td><a href="/adm/about.html"><b>$lt{'about'}</b></a></td>
-     </tr>
-     <tr>
-      <td>&nbsp;</td>
-      <td><a href="/adm/coursecatalog"><b>$lt{'catalog'}</b></a></td>
-     </tr>
+     </tr>$coursecatalog
      <tr>
       <td colspan="2">&nbsp;</td>
      </tr>
@@ -508,7 +514,8 @@
 ENDLOGIN
     if ($fullgraph) {
         my $helpdeskscript;
-        my $contactblock = &contactdisplay(\%lt,$version,$authdomain,\$helpdeskscript);
+        my $contactblock = &contactdisplay(\%lt,$servadm,$showadminmail,
+                                  $version,$authdomain,\$helpdeskscript);
 	$r->print(<<ENDDOCUMENT);
    </td>
 
@@ -604,13 +611,17 @@
 }
 
 sub contactdisplay {
-    my ($lt,$version,$authdomain,$helpdeskscript) = @_;
+    my ($lt,$servadm,$showadminmail,$version,$authdomain,$helpdeskscript) = @_;
     my $contactblock;
     my $showhelpdesk = 0;
     my $requestmail = $Apache::lonnet::perlvar{'lonSupportEMail'};
     if ($requestmail =~ m/^[^\@]+\@[^\@]+$/) {
         $showhelpdesk = 1;
     }
+    if ($servadm && $showadminmail) {
+        $contactblock .= '<b>&nbsp;&nbsp;&nbsp;'.$$lt{'servadm'}.':</b><br />'.
+                         '<tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'.$servadm.'</tt><br />&nbsp;<br />';
+    }
     if ($showhelpdesk) {
         $contactblock .= '<b>&nbsp;&nbsp;&nbsp;<a href="javascript:helpdesk()"><font size="+1">'.$lt->{'helpdesk'}.'</font></a></b><br />';
         my $thisurl = &escape('/adm/login');
@@ -652,5 +663,15 @@
     return;
 }
 
+sub coursecatalog_link {
+    my ($linkname) = @_;
+    return <<"END";
+     <tr>
+      <td>&nbsp;</td>
+      <td><a href="/adm/coursecatalog"><b>$linkname</b></a></td>
+     </tr>
+END
+}
+
 1;
 __END__
Index: loncom/lonnet/perl/lonnet.pm
diff -u loncom/lonnet/perl/lonnet.pm:1.859 loncom/lonnet/perl/lonnet.pm:1.860
--- loncom/lonnet/perl/lonnet.pm:1.859	Tue Apr  3 14:16:57 2007
+++ loncom/lonnet/perl/lonnet.pm	Tue Apr  3 14:47:29 2007
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # TCP networking package
 #
-# $Id: lonnet.pm,v 1.859 2007/04/03 18:16:57 albertel Exp $
+# $Id: lonnet.pm,v 1.860 2007/04/03 18:47:29 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -671,6 +671,61 @@
     return 'no_host';
 }
 
+# ---------------------- Get domain configuration for a domain
+sub get_domainconf {
+    my ($udom) = @_;
+    my $cachetime=1800;
+    my ($result,$cached)=&is_cached_new('domainconfig',$udom);
+    if (defined($cached)) { return %{$result}; }
+
+    if ($udom eq '') {
+        $udom = &Apache::loncommon::determinedomain();
+    }
+    my %domconfig = &get_dom('configuration',['login','rolecolors'],$udom);
+    my %designhash;
+    if (keys(%domconfig) > 0) {
+        if (ref($domconfig{'login'}) eq 'HASH') {
+            foreach my $key (keys(%{$domconfig{'login'}})) {
+                $designhash{$udom.'.login.'.$key}=$domconfig{'login'}{$key};
+            }
+        }
+        if (ref($domconfig{'rolecolors'}) eq 'HASH') {
+            foreach my $role (keys(%{$domconfig{'rolecolors'}})) {
+                if (ref($domconfig{'rolecolors'}{$role}) eq 'HASH') {
+                    foreach my $item (keys(%{$domconfig{'rolecolors'}{$role}})) {
+                        $designhash{$udom.'.'.$role.'.'.$item}=$domconfig{'rolecolors'}{$role}{$item};
+                    }
+                }
+            }
+        }
+    } else {
+        my $designdir=$perlvar{'lonTabDir'}.'/lonDomColors';
+        my $designfile =  $designdir.'/'.$udom.'.tab';
+        if (-e $designfile) {
+            if ( open (my $fh,"<$designfile") ) {
+                while (my $line = <$fh>) {
+                    next if ($line =~ /^\#/);
+                    chomp($line);
+                    my ($key,$val)=(split(/\=/,$line));
+                    if ($val) { $designhash{$udom.'.'.$key}=$val; }
+                }
+                close($fh);
+            }
+        }
+        if (-e '/home/httpd/html/adm/lonDomLogos/'.$udom.'.gif') {
+            $designhash{$udom.'.login.domlogo'} = 
+                &lonhttpdurl("/adm/lonDomLogos/$udom.gif"); 
+        }
+    }
+    &do_cache_new('domainconfig',$udom,\%designhash,$cachetime);
+    return %designhash;
+}
+
+sub devalidate_domconfig_cache {
+    my ($udom)=@_;
+    &devalidate_cache_new('domainconfig',$udom);
+}
+
 # ------------------------------------- Find the usernames behind a list of IDs
 
 sub idget {
@@ -734,15 +789,27 @@
 # ------------------------------------------- get items from domain db files   
 
 sub get_dom {
-    my ($namespace,$storearr,$udom)=@_;
+    my ($namespace,$storearr,$udom,$uhome)=@_;
     my $items='';
     foreach my $item (@$storearr) {
         $items.=&escape($item).'&';
     }
     $items=~s/\&$//;
-    if (!$udom) { $udom=$env{'user.domain'}; }
-    if (defined(&domain($udom,'primary'))) {
-        my $uhome=&domain($udom,'primary');
+    if (!$udom) {
+        $udom=$env{'user.domain'};
+        if (defined(&domain($udom,'primary'))) {
+            $uhome=&domain($udom,'primary');
+        } else {
+            $uhome eq '';
+        }
+    } else {
+        if (!$uhome) {
+            if (defined(&domain($udom,'primary'))) {
+                $uhome=&domain($udom,'primary');
+            }
+        }
+    }
+    if ($udom && $uhome && ($uhome ne 'no_host')) {
         my $rep=&reply("getdom:$udom:$namespace:$items",$uhome);
         my @pairs=split(/\&/,$rep);
         if ( $#pairs==0 && $pairs[0] =~ /^(con_lost|error|no_such_host)/i) {
@@ -756,17 +823,29 @@
         }
         return %returnhash;
     } else {
-        &logthis("get_dom failed - no primary domain server for $udom");
+        &logthis("get_dom failed - no homeserver and/or domain");
     }
 }
 
 # -------------------------------------------- put items in domain db files 
 
 sub put_dom {
-    my ($namespace,$storehash,$udom)=@_;
-    if (!$udom) { $udom=$env{'user.domain'}; }
-    if (defined(&domain($udom,'primary'))) {
-        my $uhome=&domain($udom,'primary');
+    my ($namespace,$storehash,$udom,$uhome)=@_;
+    if (!$udom) {
+        $udom=$env{'user.domain'};
+        if (defined(&domain($udom,'primary'))) {
+            $uhome=&domain($udom,'primary');
+        } else {
+            $uhome eq '';
+        }
+    } else {
+        if (!$uhome) {
+            if (defined(&domain($udom,'primary'))) {
+                $uhome=&domain($udom,'primary');
+            }
+        }
+    } 
+    if ($udom && $uhome && ($uhome ne 'no_host')) {
         my $items='';
         foreach my $item (keys(%$storehash)) {
             $items.=&escape($item).'='.&freeze_escape($$storehash{$item}).'&';
@@ -774,7 +853,7 @@
         $items=~s/\&$//;
         return &reply("putdom:$udom:$namespace:$items",$uhome);
     } else {
-        &logthis("put_dom failed - no primary domain server for $udom");
+        &logthis("put_dom failed - no homeserver and/or domain");
     }
 }
 
@@ -1521,13 +1600,16 @@
 #        $codebase - reference to hash for codebase of java objects
 #        $desuname - username for permanent storage of uploaded file
 #        $dsetudom - domain for permanaent storage of uploaded file
+#        $thumbwidth - width (pixels) of thumbnail to make for uploaded image 
+#        $thumbheight - height (pixels) of thumbnail to make for uploaded image
 # 
 # output: url of file in userspace, or error: <message> 
 #             or /adm/notfound.html if failure to upload occurse
 
 
 sub userfileupload {
-    my ($formname,$coursedoc,$subdir,$parser,$allfiles,$codebase,$destuname,$destudom)=@_;
+    my ($formname,$coursedoc,$subdir,$parser,$allfiles,$codebase,$destuname,
+        $destudom,$thumbwidth,$thumbheight)=@_;
     if (!defined($subdir)) { $subdir='unknown'; }
     my $fname=$env{'form.'.$formname.'.filename'};
     $fname=&clean_filename($fname);
@@ -1574,7 +1656,7 @@
         if ($env{'form.folder'} =~ m/^(default|supplemental)/) {
             return &finishuserfileupload($docuname,$docudom,
 					 $formname,$fname,$parser,$allfiles,
-					 $codebase);
+					 $codebase,$thumbwidth,$thumbheight);
         } else {
             $fname=$env{'form.folder'}.'/'.$fname;
             return &process_coursefile('uploaddoc',$docuname,$docudom,
@@ -1584,8 +1666,9 @@
     } elsif (defined($destuname)) {
         my $docuname=$destuname;
         my $docudom=$destudom;
-	return &finishuserfileupload($docuname,$docudom,$formname,
-				     $fname,$parser,$allfiles,$codebase);
+	return &finishuserfileupload($docuname,$docudom,$formname,$fname,
+				     $parser,$allfiles,$codebase,
+                                     $thumbwidth,$thumbheight);
         
     } else {
         my $docuname=$env{'user.name'};
@@ -1594,16 +1677,18 @@
             $docuname=$env{'course.'.$env{'request.course.id'}.'.num'};
             $docudom=$env{'course.'.$env{'request.course.id'}.'.domain'};
         }
-	return &finishuserfileupload($docuname,$docudom,$formname,
-				     $fname,$parser,$allfiles,$codebase);
+	return &finishuserfileupload($docuname,$docudom,$formname,$fname,
+				     $parser,$allfiles,$codebase,
+                                     $thumbwidth,$thumbheight);
     }
 }
 
 sub finishuserfileupload {
-    my ($docuname,$docudom,$formname,$fname,$parser,$allfiles,$codebase) = @_;
+    my ($docuname,$docudom,$formname,$fname,$parser,$allfiles,$codebase,
+        $thumbwidth,$thumbheight) = @_;
     my $path=$docudom.'/'.$docuname.'/';
     my $filepath=$perlvar{'lonDocRoot'};
-    my ($fnamepath,$file);
+    my ($fnamepath,$file,$fetchthumb);
     $file=$fname;
     if ($fname=~m|/|) {
         ($fnamepath,$file) = ($fname =~ m|^(.*)/([^/]+)$|);
@@ -1639,12 +1724,28 @@
 		     ' for embedded media: '.$parse_result); 
         }
     }
+    if (($thumbwidth =~ /^\d+$/) && ($thumbheight =~ /^\d+$/)) {
+        my $input = $filepath.'/'.$file;
+        my $output = $filepath.'/'.'tn-'.$file;
+        my $thumbsize = $thumbwidth.'x'.$thumbheight;
+        system("convert -sample $thumbsize $input $output");
+        if (-e $filepath.'/'.'tn-'.$file) {
+            $fetchthumb  = 1; 
+        }
+    }
  
 # Notify homeserver to grep it
 #
     my $docuhome=&homeserver($docuname,$docudom);
     my $fetchresult= &reply('fetchuserfile:'.$path.$file,$docuhome);
     if ($fetchresult eq 'ok') {
+        if ($fetchthumb) {
+            my $thumbresult= &reply('fetchuserfile:'.$path.'tn-'.$file,$docuhome);
+            if ($thumbresult ne 'ok') {
+                &logthis('Failed to transfer '.$path.'tn-'.$file.' to host '.
+                         $docuhome.': '.$thumbresult);
+            }
+        }
 #
 # Return the URL to it
         return '/uploaded/'.$path.$file;
@@ -8632,12 +8733,15 @@
 
 =item *
 
-get_dom($namespace,$storearr,$udomain) : returns hash with keys from array
-reference filled in from namespace found in domain level on primary domain server ($udomain is optional)
+get_dom($namespace,$storearr,$udom,$uhome) : returns hash with keys from
+array reference filled in from namespace found in domain level on either
+specified domain server ($uhome) or primary domain server ($udom and $uhome are optional).
 
 =item *
 
-put_dom($namespace,$storehash,$udomain) :  stores hash in namespace at domain level on primary domain server ($udomain is optional)
+put_dom($namespace,$storehash,$udom,$uhome) :  stores hash in namespace at 
+domain level either on specified domain server ($uhome) or primary domain 
+server ($udom and $uhome are optional)
 
 =back
 

--raeburn1175626050--