--- loncom/interface/loncommon.pm	2007/08/02 01:07:00	1.558
+++ loncom/interface/loncommon.pm	2007/09/10 23:03:38	1.581
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # a pile of common routines
 #
-# $Id: loncommon.pm,v 1.558 2007/08/02 01:07:00 albertel Exp $
+# $Id: loncommon.pm,v 1.581 2007/09/10 23:03:38 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -721,24 +721,20 @@ sub help_open_topic {
 
     my $template = "";
     my $link;
-
+    
     $topic=~s/\W/\_/g;
 
-    if (!$stayOnPage)
-    {
+    if (!$stayOnPage) {
 	$link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
-    }
-    else
-    {
+    } else {
 	$link = "/adm/help/${filename}.hlp";
     }
 
     # Add the text
-    if ($text ne "")
-    {
+    if ($text ne "") {
 	$template .= 
-  "<table bgcolor='#3333AA' cellspacing='1' cellpadding='1' border='0'><tr>".
-  "<td bgcolor='#5555FF'><a target=\"_top\" href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";
+            "<table bgcolor='#3333AA' cellspacing='1' cellpadding='1' border='0'><tr>".
+            "<td bgcolor='#5555FF'><a target=\"_top\" href=\"$link\"><font color='#FFFFFF' size='2'>$text</font></a>";
     }
 
     # Add the graphic
@@ -805,14 +801,10 @@ sub help_open_menu {
     my ($topic,$component_help,$faq,$bug,$stayOnPage,$width,$height,$text) 
 	= @_;    
     $stayOnPage = 0 if (not defined $stayOnPage);
-    # formerly only used pop-up help (stayOnPage = 0)
+    # only use pop-up help (stayOnPage == 0)
     # if environment.remote is on (using remote control UI)
-    # if ($env{'browser.interface'} eq 'textual' ||
-    #	$env{'environment.remote'} eq 'off' ) {
-    #   $stayOnPage=1;
-    #}
-    # Now making pop-up help the default even with remote control
-    if ($env{'browser.interface'} eq 'textual') {
+    if ($env{'browser.interface'} eq 'textual' ||
+    	$env{'environment.remote'} eq 'off' ) {
         $stayOnPage=1;
     }
     my $output;
@@ -834,15 +826,13 @@ sub help_open_menu {
 
 sub top_nav_help {
     my ($text) = @_;
-
     $text = &mt($text);
-
-    my $stayOnPage = 
+    my $stay_on_page = 
 	($env{'browser.interface'}  eq 'textual' ||
 	 $env{'environment.remote'} eq 'off' );
-    my $link=  ($stayOnPage) ? "javascript:helpMenu('display')"
+    my $link = ($stay_on_page) ? "javascript:helpMenu('display')"
 	                     : "javascript:helpMenu('open')";
-    my $banner_link = &update_help_link(undef,undef,undef,undef,$stayOnPage);
+    my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);
 
     my $title = &mt('Get help');
 
@@ -870,7 +860,7 @@ sub help_menu_js {
 					'js_ready'    => 1,
 					'add_entries' => {
 					    'border' => '0',
-					    'rows'   => "105,*",},});
+					    'rows'   => "110,*",},});
     my $end_page =
         &Apache::loncommon::end_page({'frameset' => 1,
 				      'js_ready' => 1,});
@@ -1084,6 +1074,63 @@ sub changable_area {
 
 =pod
 
+=item * resize_textarea_js
+
+emits the needed javascript to resize a textarea to be as big as possible
+
+creates a function resize_textrea that takes two IDs first should be
+the id of the element to resize, second should be the id of a div that
+surrounds everything that comes after the textarea, this routine needs
+to be attached to the <body> for the onload and onresize events.
+
+
+=cut
+
+sub resize_textarea_js {
+    return <<"RESIZE";
+    <script type="text/javascript">
+var Geometry = {};
+function init_geometry() {
+    if (Geometry.init) { return };
+    Geometry.init=1;
+    if (window.innerHeight) {
+	Geometry.getViewportHeight = function() { return window.innerHeight; };
+    }
+    else if (document.documentElement && document.documentElement.clientHeight) {
+	Geometry.getViewportHeight = 
+	    function() { return document.documentElement.clientHeight; };
+    }
+    else if (document.body.clientHeight) {
+	Geometry.getViewportHeight = 
+	    function() { return document.body.clientHeight; };
+    }
+}
+
+function resize_textarea(textarea_id,bottom_id) {
+    init_geometry();
+    var textarea        = document.getElementById(textarea_id);
+    //alert(textarea);
+
+    var textarea_top    = textarea.offsetTop;
+    var textarea_height = textarea.offsetHeight;
+    var bottom          = document.getElementById(bottom_id);
+    var bottom_top      = bottom.offsetTop;
+    var bottom_height   = bottom.offsetHeight;
+    var window_height   = Geometry.getViewportHeight();
+    var fudge           = 23; 
+    var new_height      = window_height-fudge-textarea_top-bottom_height;
+    if (new_height < 300) {
+	new_height = 300;
+    }
+    textarea.style.height=new_height+'px';
+}
+</script>
+RESIZE
+
+}
+
+=pod
+
 =back
  
 =head1 Excel and CSV file utility routines
@@ -1424,7 +1471,7 @@ sub select_level_form {
 
 =pod
 
-=item * select_dom_form($defdom,$name,$includeempty)
+=item * select_dom_form($defdom,$name,$includeempty,$showdomdesc)
 
 Returns a string containing a <select name='$name' size='1'> form to 
 allow a user to select the domain to preform an operation in.  
@@ -1433,18 +1480,28 @@ See loncreateuser.pm for an example invo
 If the $includeempty flag is set, it also includes an empty choice ("no domain
 selected");
 
+If the $showdomdesc flag is set, the domain name is followed by the domain description. 
+
 =cut
 
 #-------------------------------------------
 sub select_dom_form {
-    my ($defdom,$name,$includeempty) = @_;
+    my ($defdom,$name,$includeempty,$showdomdesc) = @_;
     my @domains = sort {lc($a) cmp lc($b)} (&Apache::lonnet::all_domains());
     if ($includeempty) { @domains=('',@domains); }
     my $selectdomain = "<select name=\"$name\" size=\"1\">\n";
     foreach my $dom (@domains) {
         $selectdomain.="<option value=\"$dom\" ".
-            ($dom eq $defdom ? 'selected="selected" ' : '').
-                ">$dom</option>\n";
+            ($dom eq $defdom ? 'selected="selected" ' : '').'>'.$dom;
+        if ($showdomdesc) {
+            if ($dom ne '') {
+                my $domdesc = &Apache::lonnet::domain($dom,'description');
+                if ($domdesc ne '') {
+                    $selectdomain .= ' ('.$domdesc.')';
+                }
+            } 
+        }
+        $selectdomain .= "</option>\n";
     }
     $selectdomain.="</select>";
     return $selectdomain;
@@ -2580,25 +2637,15 @@ sub get_previous_attempt {
 	for ($version=1;$version<=$returnhash{'version'};$version++) {
 	  $prevattempts.='</tr><tr bgcolor="#ffffe6"><td>Transaction '.$version.'</td>';
 	    foreach my $key (sort(keys(%lasthash))) {
-	       my $value;
-	       if ($key =~ /timestamp/) {
-		  $value=scalar(localtime($returnhash{$version.':'.$key}));
-	       } else {
-		  $value=$returnhash{$version.':'.$key};
-	       }
-	       $prevattempts.='<td>'.&unescape($value).'&nbsp;</td>';   
+		my $value = &format_previous_attempt_value($key,
+							   $returnhash{$version.':'.$key});
+		$prevattempts.='<td>'.$value.'&nbsp;</td>';   
 	    }
 	 }
       }
       $prevattempts.='</tr><tr bgcolor="#ffffe6"><td>Current</td>';
       foreach my $key (sort(keys(%lasthash))) {
-	my $value;
-	if ($key =~ /timestamp/) {
-	  $value=scalar(localtime($lasthash{$key}));
-	} else {
-	  $value=$lasthash{$key};
-	}
-	$value=&unescape($value);
+	my $value = &format_previous_attempt_value($key,$lasthash{$key});
 	if ($key =~/$regexp$/ && (defined &$gradesub)) {$value = &$gradesub($value)}
 	$prevattempts.='<td>'.$value.'&nbsp;</td>';
       }
@@ -2611,6 +2658,19 @@ sub get_previous_attempt {
   }
 }
 
+sub format_previous_attempt_value {
+    my ($key,$value) = @_;
+    if ($key =~ /timestamp/) {
+	$value = &Apache::lonlocal::locallocaltime($value);
+    } elsif (ref($value) eq 'ARRAY') {
+	$value = '('.join(', ', @{ $value }).')';
+    } else {
+	$value = &unescape($value);
+    }
+    return $value;
+}
+
+
 sub relative_to_absolute {
     my ($url,$output)=@_;
     my $parser=HTML::TokeParser->new(\$output);
@@ -3397,6 +3457,9 @@ Inputs:
 
 =item * $args, optional argument valid values are
             no_auto_mt_title -> prevents &mt()ing the title arg
+            inherit_jsmath -> when creating popup window in a page,
+                              should it have jsmath forced on by the
+                              current page
 
 =back
 
@@ -3445,15 +3508,12 @@ sub bodytag {
     if (!$realm) { $realm='&nbsp;'; }
 # Set messages
     my $messages=&domainlogo($domain);
-# Port for miniserver
-    my $lonhttpdPort=$Apache::lonnet::perlvar{'lonhttpdPort'};
-    if (!defined($lonhttpdPort)) { $lonhttpdPort='8080'; }
 
     my $extra_body_attr = &make_attr_string($forcereg,\%design);
 
 # construct main body tag
     my $bodytag = "<body $extra_body_attr>".
-	&Apache::lontexconvert::init_math_support();
+	&Apache::lontexconvert::init_math_support($args->{'inherit_jsmath'});
 
     if ($bodyonly) {
         return $bodytag;
@@ -3565,7 +3625,7 @@ ENDROLE
 
     my $imgsrc = $img;
     if ($img =~ /^\/adm/) {
-        $imgsrc = 'http://'.$ENV{'HTTP_HOST'}.':'.$lonhttpdPort.$img;
+        $imgsrc = &lonhttpdurl($img);
     }
     my $upperleft='<img src="'.$imgsrc.'" alt="'.$function.'" />';
 
@@ -4273,9 +4333,7 @@ table#LC_helpmenu_links a:hover {
   border: 1px solid #8888FF;
   background: #CCCCFF;
 }
-
 table.LC_pick_box {
-  width: 100%;
   border-collapse: separate;
   background: white;
   border: 1px solid black;
@@ -4288,6 +4346,14 @@ table.LC_pick_box td.LC_pick_box_title {
   width: 184px;
   padding: 8px;
 }
+table.LC_pick_box td.LC_pick_box_value {
+  text-align: left;
+  padding: 8px;
+}
+table.LC_pick_box td.LC_pick_box_select {
+  text-align: left;
+  padding: 8px;
+}
 table.LC_pick_box td.LC_pick_box_separator {
   padding: 0px;
   height: 1px;
@@ -4296,7 +4362,48 @@ table.LC_pick_box td.LC_pick_box_separat
 table.LC_pick_box td.LC_pick_box_submit {
   text-align: right;
 }
-
+table.LC_pick_box td.LC_evenrow_value {
+  text-align: left;
+  padding: 8px;
+  background-color: $data_table_light;
+}
+table.LC_pick_box td.LC_oddrow_value {
+  text-align: left;
+  padding: 8px;
+  background-color: $data_table_light;
+}
+table.LC_helpform_receipt {
+  width: 620px;
+  border-collapse: separate;
+  background: white;
+  border: 1px solid black;
+  border-spacing: 1px;
+}
+table.LC_helpform_receipt td.LC_pick_box_title {
+  background: $tabbg;
+  font-weight: bold;
+  text-align: right;
+  width: 184px;
+  padding: 8px;
+}
+table.LC_helpform_receipt td.LC_evenrow_value {
+  text-align: left;
+  padding: 8px;
+  background-color: $data_table_light;
+}
+table.LC_helpform_receipt td.LC_oddrow_value {
+  text-align: left;
+  padding: 8px;
+  background-color: $data_table_light;
+}
+table.LC_helpform_receipt td.LC_pick_box_separator {
+  padding: 0px;
+  height: 1px;
+  background: black;
+}
+span.LC_helpform_receipt_cat {
+  font-weight: bold;
+}
 table.LC_group_priv_box {
   background: white;
   border: 1px solid black;
@@ -4441,6 +4548,10 @@ span.LC_nobreak {
   white-space: nowrap;
 }
 
+span.LC_cusr_emph {
+  font-style: italic;
+}
+
 table.LC_docs_documents {
   background: #BBBBBB;
   border-width: 0px;
@@ -4711,6 +4822,10 @@ Inputs: $title - optional title for the
 
                   no_auto_mt_title -> prevent &mt()ing the title arg
 
+                  inherit_jsmath -> when creating popup window in a page,
+                                    should it have jsmath forced on by the
+                                    current page
+
 =cut
 
 sub start_page {
@@ -5535,11 +5650,11 @@ sub get_secgrprole_info {
 }
 
 sub user_picker {
-    my ($dom,$srch,$forcenewuser) = @_;
+    my ($dom,$srch,$forcenewuser,$caller) = @_;
     my $currdom = $dom;
     my %curr_selected = (
                         srchin => 'dom',
-                        srchby => 'uname',
+                        srchby => 'lastname',
                       );
     my $srchterm;
     if (ref($srch) eq 'HASH') {
@@ -5557,25 +5672,30 @@ sub user_picker {
         }
         $srchterm = $srch->{'srchterm'};
     }
-    use Data::Dumper;
-    &Apache::lonnet::logthis(&Dumper($srch));
     my %lt=&Apache::lonlocal::texthash(
-                    'usr'       => 'Search for',
-                    'or'        => 'or',
-                    'doma'      => 'domain',
+                    'usr'       => 'Search criteria',
+                    'doma'      => 'Domain/institution to search',
                     'uname'     => 'username',
                     'lastname'  => 'last name',
                     'lastfirst' => 'last name, first name',
                     'crs'       => 'in this course',
-                    'dom'       => 'in this domain', 
+                    'dom'       => 'in selected LON-CAPA domain', 
                     'alc'       => 'all LON-CAPA',
-                    'instd'     => 'in institutional directory',
+                    'instd'     => 'in institutional directory for selected domain',
                     'exact'     => 'is',
                     'contains'  => 'contains',
+                    'begins'    => 'begins with',
+                    'youm'      => "You must include some text to search for.",
+                    'thte'      => "The text you are searching for must contain at least two characters when using a 'begins' type search.",
+                    'thet'      => "The text you are searching for must contain at least three characters when using a 'contains' type search.",
+                    'yomc'      => "You must choose a domain when using an institutional directory search.",
+                    'ymcd'      => "You must choose a domain when using a domain search.",
+                    'whus'      => "When using searching by last,first you must include a comma as separator between last name and first name.",
+                    'whse'      => "When searching by last,first you must include at least one character in the first name.",
+                     'thfo'     => "The following need to be corrected before the search can be run:",
                                        );
-    my $domform = &select_dom_form($currdom,'srchdomain',1);
-
-    my $srchin;
+    my $domform = &select_dom_form($currdom,'srchdomain',1,1);
+    my $srchinsel = ' <select name="srchin">';
 
     my @srchins = ('crs','dom','alc','instd');
 
@@ -5585,21 +5705,18 @@ sub user_picker {
         #       has been completed.
         next if ($option eq 'alc');
         next if ($option eq 'crs' && !$env{'request.course.id'});
-        my $checked =($curr_selected{'srchin'} eq $option) ?'checked="checked"'
-	                                                   :'';
-	my $extra = ($option eq 'dom') ? $domform
-	                               : '';
-	$srchin.=<<ROW
- <tr>
-   <td>
-     <label><input type="radio" name="srchin" value="$option" $checked /> $lt{$option}</label> $extra
-   </td>
-</tr>
-ROW
+        if ($curr_selected{'srchin'} eq $option) {
+            $srchinsel .= ' 
+   <option value="'.$option.'" selected="selected">'.$lt{$option}.'</option>';
+        } else {
+            $srchinsel .= '
+   <option value="'.$option.'">'.$lt{$option}.'</option>';
+        }
     }
+    $srchinsel .= "\n  </select>\n";
 
     my $srchbysel =  ' <select name="srchby">';
-    foreach my $option ('uname','lastname','lastfirst') {
+    foreach my $option ('lastname','lastfirst','uname') {
         if ($curr_selected{'srchby'} eq $option) {
             $srchbysel .= '
    <option value="'.$option.'" selected="selected">'.$lt{$option}.'</option>';
@@ -5611,7 +5728,7 @@ ROW
     $srchbysel .= "\n  </select>\n";
 
     my $srchtypesel = ' <select name="srchtype">';
-    foreach my $option ('exact','contains') {
+    foreach my $option ('begins','contains','exact') {
         if ($curr_selected{'srchtype'} eq $option) {
             $srchtypesel .= '
    <option value="'.$option.'" selected="selected">'.$lt{$option}.'</option>';
@@ -5625,29 +5742,34 @@ ROW
     my ($newuserscript,$new_user_create);
 
     if ($forcenewuser) {
-	$new_user_create = '<p> <input type="submit" name="forcenew" value="'.&HTML::Entities::encode(&mt('Make new user "[_1]"',$srchterm),'<>&"').'" onclick="javascript:setSearch(\'1\');" /> </p>';
+        if (ref($srch) eq 'HASH') {
+            if ($srch->{'srchby'} eq 'uname' && $srch->{'srchtype'} eq 'exact' && $srch->{'srchin'} eq 'dom' && $srch->{'srchdomain'} eq $env{'request.role.domain'}) {
+	        $new_user_create = '<p> <input type="submit" name="forcenew" value="'.&HTML::Entities::encode(&mt('Make new user "[_1]"',$srchterm),'<>&"').'" onclick="javascript:setSearch(\'1\','.$caller.');" /> </p>';
+            }
+        }
+
         $newuserscript = <<"ENDSCRIPT";
 
-function setSearch(createnew) {
+function setSearch(createnew,callingForm) {
     if (createnew == 1) {
-        for (var i=0; i<document.crtuser.srchby.length; i++) {
-            if (document.crtuser.srchby.options[i].value == 'uname') {
-                document.crtuser.srchby.selectedIndex = i;
+        for (var i=0; i<callingForm.srchby.length; i++) {
+            if (callingForm.srchby.options[i].value == 'uname') {
+                callingForm.srchby.selectedIndex = i;
             }
         }
-        for (var i=0; i<document.crtuser.srchin.length; i++) {
-            if ( document.crtuser.srchin[i].value == 'dom') {
-		document.crtuser.srchin[i].checked = 1;
+        for (var i=0; i<callingForm.srchin.length; i++) {
+            if ( callingForm.srchin.options[i].value == 'dom') {
+		callingForm.srchin.selectedIndex = i;
             }
         }
-        for (var i=0; i<document.crtuser.srchtype.length; i++) {
-            if (document.crtuser.srchtype.options[i].value == 'exact') {
-                document.crtuser.srchtype.selectedIndex = i;
+        for (var i=0; i<callingForm.srchtype.length; i++) {
+            if (callingForm.srchtype.options[i].value == 'exact') {
+                callingForm.srchtype.selectedIndex = i;
             }
         }
-        for (var i=0; i<document.crtuser.srchdomain.length; i++) {
-            if (document.crtuser.srchdomain.options[i].value == '$env{'request.role.domain'}') {
-                document.crtuser.srchdomain.selectedIndex = i;
+        for (var i=0; i<callingForm.srchdomain.length; i++) {
+            if (callingForm.srchdomain.options[i].value == '$env{'request.role.domain'}') {
+                callingForm.srchdomain.selectedIndex = i;
             }
         }
     }
@@ -5658,61 +5780,69 @@ ENDSCRIPT
 
     my $output = <<"END_BLOCK";
 <script type="text/javascript">
-function validateEntry() {
+function validateEntry(callingForm) {
 
     var checkok = 1;
     var srchin;
-    for (var i=0; i<document.crtuser.srchin.length; i++) {
-	if ( document.crtuser.srchin[i].checked ) {
-	    srchin = document.crtuser.srchin[i].value;
+    for (var i=0; i<callingForm.srchin.length; i++) {
+	if ( callingForm.srchin[i].checked ) {
+	    srchin = callingForm.srchin[i].value;
 	}
     }
 
-    var srchtype = document.crtuser.srchtype.options[document.crtuser.srchtype.selectedIndex].value;
-    var srchby = document.crtuser.srchby.options[document.crtuser.srchby.selectedIndex].value;
-    var srchdomain = document.crtuser.srchdomain.options[document.crtuser.srchdomain.selectedIndex].value;
-    var srchterm =  document.crtuser.srchterm.value;
+    var srchtype = callingForm.srchtype.options[callingForm.srchtype.selectedIndex].value;
+    var srchby = callingForm.srchby.options[callingForm.srchby.selectedIndex].value;
+    var srchdomain = callingForm.srchdomain.options[callingForm.srchdomain.selectedIndex].value;
+    var srchterm =  callingForm.srchterm.value;
+    var srchin = callingForm.srchin.options[callingForm.srchin.selectedIndex].value;
     var msg = "";
 
     if (srchterm == "") {
         checkok = 0;
-        msg += "You must include some text to search for.\\n";
+        msg += "$lt{'youm'}\\n";
+    }
+
+    if (srchtype== 'begins') {
+        if (srchterm.length < 2) {
+            checkok = 0;
+            msg += "$lt{'thte'}\\n";
+        }
     }
 
     if (srchtype== 'contains') {
         if (srchterm.length < 3) {
             checkok = 0;
-            msg += "The text you are searching for must contain at least three characters when using a 'contained in' type search.\\n";
+            msg += "$lt{'thet'}\\n";
         }
     }
     if (srchin == 'instd') {
         if (srchdomain == '') {
             checkok = 0;
-            msg += "You must choose a domain when using an institutional directory search.\\n";
+            msg += "$lt{'yomc'}\\n";
         }
     }
     if (srchin == 'dom') {
         if (srchdomain == '') {
             checkok = 0;
-            msg += "You must choose a domain when using a domain search.\\n";
+            msg += "$lt{'ymcd'}\\n";
         }
     }
     if (srchby == 'lastfirst') {
         if (srchterm.indexOf(",") == -1) {
             checkok = 0;
-            msg += "When using searching by last,first you must include a comma as separator between last name and first name.\\n";
+            msg += "$lt{'whus'}\\n";
         }
         if (srchterm.indexOf(",") == srchterm.length -1) {
             checkok = 0;
-            msg += "When searching by last,first you must include at least one character in the first name.\\n";
+            msg += "$lt{'whse'}\\n";
         }
     }
     if (checkok == 0) {
-        alert("The following need to be corrected before the search can be run:\\n"+msg);
+        alert("$lt{'thfo'}\\n"+msg);
         return;
     }
     if (checkok == 1) {
-        document.crtuser.submit();
+        callingForm.submit();
     }
 }
 
@@ -5724,12 +5854,18 @@ $new_user_create
 
 <table>
  <tr>
-  <td> $srchbysel
-       $srchtypesel 
-       <input type="text" size="15" name="srchterm" value="$srchterm" />
+  <td>$lt{'doma'}:</td>
+  <td>$domform</td>
+  </td>
+ </tr>
+ <tr>
+  <td>$lt{'usr'}:</td>
+  <td>$srchbysel
+      $srchtypesel 
+      <input type="text" size="15" name="srchterm" value="$srchterm" />
+      $srchinsel 
   </td>
  </tr>
-$srchin
 </table>
 <br />
 END_BLOCK
@@ -5737,8 +5873,6 @@ END_BLOCK
     return $output;
 }
 
-
-
 =pod
 
 =back
@@ -5996,28 +6130,50 @@ sub record_sep {
             $i++;
         }
     } else {
-        my @allfields;
+        my $separator=',';
         if ($env{'form.upfiletype'} eq 'semisv') {
-            @allfields=split(/;/,$record,-1);
-        } else {
-            @allfields=split(/\,/,$record,-1);
+            $separator=';';
         }
         my $i=0;
-        my $j;
-        for ($j=0;$j<=$#allfields;$j++) {
-            my $field=$allfields[$j];
-            if ($field=~/^\s*(\"|\')/) {
-		my $delimiter=$1;
-                while (($field!~/$delimiter$/) && ($j<$#allfields)) {
-		    $j++;
-		    $field.=','.$allfields[$j];
-		}
-                $field=~s/^\s*$delimiter//;
-                $field=~s/$delimiter\s*$//;
-            }
-            $components{&takeleft($i)}=$field;
-	    $i++;
+# the character we are looking for to indicate the end of a quote or a record 
+        my $looking_for=$separator;
+# do not add the characters to the fields
+        my $ignore=0;
+# we just encountered a separator (or the beginning of the record)
+        my $just_found_separator=1;
+# store the field we are working on here
+        my $field='';
+# work our way through all characters in record
+        foreach my $character ($record=~/(.)/g) {
+            if ($character eq $looking_for) {
+               if ($character ne $separator) {
+# Found the end of a quote, again looking for separator
+                  $looking_for=$separator;
+                  $ignore=1;
+               } else {
+# Found a separator, store away what we got
+                  $components{&takeleft($i)}=$field;
+	          $i++;
+                  $just_found_separator=1;
+                  $ignore=0;
+                  $field='';
+               }
+               next;
+            }
+# single or double quotation marks after a separator indicate beginning of a quote
+# we are now looking for the end of the quote and need to ignore separators
+            if ((($character eq '"') || ($character eq "'")) && ($just_found_separator))  {
+               $looking_for=$character;
+               next;
+            }
+# ignore would be true after we reached the end of a quote
+            if ($ignore) { next; }
+            if (($just_found_separator) && ($character=~/\s/)) { next; }
+            $field.=$character;
+            $just_found_separator=0; 
         }
+# catch the very last entry, since we never encountered the separator
+        $components{&takeleft($i)}=$field;
     }
     return %components;
 }
@@ -6876,6 +7032,45 @@ sub commit_studentrole {
 ############################################################
 ############################################################
 
+sub check_clone {
+    my ($args,$linefeed) = @_;
+    my $cloneid='/'.$args->{'clonedomain'}.'/'.$args->{'clonecourse'};
+    my ($clonecrsudom,$clonecrsunum)= &LONCAPA::split_courseid($cloneid);
+    my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);
+    my $clonemsg;
+    my $can_clone = 0;
+
+    if ($clonehome eq 'no_host') {
+        $clonemsg = &mt('No new course created.').$linefeed.&mt('A new course could not be cloned from the specified original - [_1] - because it is a non-existent course.',$args->{'clonecourse'}.':'.$args->{'clonedomain'});     
+    } else {
+	my %clonedesc = &Apache::lonnet::coursedescription($cloneid,{'one_time' => 1});
+	if ($env{'request.role.domain'} eq $args->{'clonedomain'}) {
+	    $can_clone = 1;
+	} else {
+	    my %clonehash = &Apache::lonnet::get('environment',['cloners'],
+						 $args->{'clonedomain'},$args->{'clonecourse'});
+	    my @cloners = split(/,/,$clonehash{'cloners'});
+            if (grep(/^\*$/,@cloners)) {
+                $can_clone = 1;
+            } elsif (grep(/^\*\:\Q$args->{'ccdomain'}\E$/,@cloners)) {
+                $can_clone = 1;
+            } else {
+	        my %roleshash =
+		    &Apache::lonnet::get_my_roles($args->{'ccuname'},
+					 $args->{'ccdomain'},
+                                         'userroles',['active'],['cc'],
+					 [$args->{'clonedomain'}]);
+	        if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':cc'}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) {
+		    $can_clone = 1;
+	        } else {
+                    $clonemsg = &mt('No new course created.').$linefeed.&mt('The new course could not be cloned from the existing course because the new course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
+	        }
+	    }
+        }
+    }
+    return ($can_clone, $clonemsg, $cloneid, $clonehome);
+}
+
 sub construct_course {
     my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname,$context) = @_;
     my $outcome;
@@ -6883,6 +7078,25 @@ sub construct_course {
     if ($context eq 'auto') {
         $linefeed = "\n";
     }
+
+#
+# Are we cloning?
+#
+    my ($can_clone, $clonemsg, $cloneid, $clonehome);
+    if (($args->{'clonecourse'}) && ($args->{'clonedomain'})) {
+	($can_clone, $clonemsg, $cloneid, $clonehome) = &check_clone($args,$linefeed);
+	if ($context ne 'auto') {
+            if ($clonemsg ne '') {
+	        $clonemsg = '<span class="LC_error">'.$clonemsg.'</span>';
+            }
+	}
+	$outcome .= $clonemsg.$linefeed;
+
+        if (!$can_clone) {
+	    return (0,$outcome);
+	}
+    }
+
 #
 # Open course
 #
@@ -6903,81 +7117,39 @@ sub construct_course {
     # if anyone ever decides to not show this, and Utils::Course::new
     # will need to be suitably modified.
     $outcome .= &mt('New LON-CAPA [_1] ID: [_2]',$crstype,$$courseid).$linefeed;
-
 #
 # Check if created correctly
 #
     ($$crsudom,$$crsunum)= &LONCAPA::split_courseid($$courseid);
     my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom);
     $outcome .= &mt('Created on').': '.$crsuhome.$linefeed;
+
 #
-# Are we cloning?
-#
-    my $cloneid='';
-    if (($args->{'clonecourse'}) && ($args->{'clonedomain'})) {
-        my $can_clone = 0;
-	$cloneid='/'.$args->{'clonedomain'}.'/'.$args->{'clonecourse'};
-        my ($clonecrsudom,$clonecrsunum)= &LONCAPA::split_courseid($cloneid);
-	my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);
-        my $clonemsg;
-	if ($clonehome eq 'no_host') {
-            $clonemsg = &mt('Attempting to clone non-existing [_1]',$crstype);
-            if ($context eq 'auto') {
-                $outcome .= $clonemsg;
-            } else {
-	        $outcome .= '<font color="red">'.$clonemsg.'</font>';
-            }
-            $outcome .= $linefeed;
-	} else {
-            my %clonedesc = &Apache::lonnet::coursedescription($cloneid,{'one_time' => 1});
-            if ($env{'request.role.domain'} eq $args->{'form.clonedomain'}) {
-                $can_clone = 1;
-            } else {
-                my %clonehash = &Apache::lonnet::get('environment',['cloners'],
-                            $args->{'clonedomain'},$args->{'clonecourse'});
-                my @cloners = split(/,/,$clonehash{'cloners'});
-                my %roleshash =
-                    &Apache::lonnet::get_my_roles($args->{'ccuname'},
-                        $args->{'ccdomain'},'userroles',['active'],['cc'],
-                        [$args->{'clonedomain'}]);
-                if (($roleshash{$args->{'clonecourse'}.':'.$args->{'clonedomain'}.':cc'}) || (grep(/^\Q$args->{'ccuname'}\E:\Q$args->{'ccdomain'}\E$/,@cloners))) {
-                    $can_clone = 1;
-                } else {
-                    $clonemsg = &mt('The new course was not cloned from an existing course because the course owner ([_1]) does not have cloning rights in the existing course ([_2]).',$args->{'ccuname'}.':'.$args->{'ccdomain'},$clonedesc{'description'});
-                    if ($context eq 'auto') {
-                        $outcome .= $clonemsg;
-                    } else {
-                        $outcome .= '<font color="red">'.$clonemsg.'</font>';
-                    }
-                    $outcome .= $linefeed;
-                }
-            }
-        }
-        if ($can_clone) {
-	    $clonemsg = &mt('Cloning [_1] from [_2]',$crstype,$clonehome);
-            if ($context eq 'auto') {
-                $outcome = $clonemsg;
-            } else { 
-                $outcome .= '<font color="green">'.$clonemsg.'</font>';
-            }
-            $outcome .= $linefeed;
-	    my %oldcenv=&Apache::lonnet::dump('environment',$$crsudom,$$crsunum);
+# Do the cloning
+#   
+    if ($can_clone && $cloneid) {
+	$clonemsg = &mt('Cloning [_1] from [_2]',$crstype,$clonehome);
+	if ($context ne 'auto') {
+	    $clonemsg = '<span class="LC_success">'.$clonemsg.'</span>';
+	}
+	$outcome .= $clonemsg.$linefeed;
+	my %oldcenv=&Apache::lonnet::dump('environment',$$crsudom,$$crsunum);
 # Copy all files
-	    &Apache::lonclonecourse::copycoursefiles($cloneid,$$courseid);
+	&Apache::lonclonecourse::copycoursefiles($cloneid,$$courseid);
 # Restore URL
-	    $cenv{'url'}=$oldcenv{'url'};
+	$cenv{'url'}=$oldcenv{'url'};
 # Restore title
-	    $cenv{'description'}=$oldcenv{'description'};
+	$cenv{'description'}=$oldcenv{'description'};
 # restore grading mode
-	    if (defined($oldcenv{'grading'})) {
-		$cenv{'grading'}=$oldcenv{'grading'};
-	    }
-# Mark as cloned
-	    $cenv{'clonedfrom'}=$cloneid;
-	    delete($cenv{'default_enrollment_start_date'});
-	    delete($cenv{'default_enrollment_end_date'});
+	if (defined($oldcenv{'grading'})) {
+	    $cenv{'grading'}=$oldcenv{'grading'};
 	}
+# Mark as cloned
+	$cenv{'clonedfrom'}=$cloneid;
+	delete($cenv{'default_enrollment_start_date'});
+	delete($cenv{'default_enrollment_end_date'});
     }
+
 #
 # Set environment (will override cloned, if existing)
 #
@@ -7085,7 +7257,7 @@ sub construct_course {
                            ' ('.$lt{'adby'}.')';
         if ($context eq 'auto') {
             $outcome .= $badclass_msg.$linefeed;
-            $outcome .= '<font color="red">'.$badclass_msg.$linefeed.'<ul>'."\n";
+            $outcome .= '<div class="LC_warning">'.$badclass_msg.$linefeed.'<ul>'."\n";
             foreach my $item (@badclasses) {
                 if ($context eq 'auto') {
                     $outcome .= " - $item\n";
@@ -7096,7 +7268,7 @@ sub construct_course {
             if ($context eq 'auto') {
                 $outcome .= $linefeed;
             } else {
-                $outcome .= "</ul><br /><br /></font>\n";
+                $outcome .= "</ul><br /><br /></div>\n";
             }
         } 
     }
@@ -7118,7 +7290,7 @@ sub construct_course {
             if ($context eq 'auto') {
                 $outcome .= $krb_msg;
             } else {
-                $outcome .= '<font color="red" size="+1">'.$krb_msg.'</font>';
+                $outcome .= '<span class="LC_error">'.$krb_msg.'</span>';
             }
             $outcome .= $linefeed;
         }
@@ -7216,7 +7388,8 @@ sub construct_course {
 	if ($errtext) { $fatal=2; }
         $outcome .= ($fatal?$errtext:'write ok').$linefeed;
     }
-    return $outcome;
+
+    return (1,$outcome);
 }
 
 ############################################################
@@ -7259,10 +7432,27 @@ sub icon {
     return &lonhttpdurl($iconname);
 } 
 
-sub lonhttpdurl {
-    my ($url)=@_;
+sub lonhttpd_port {
     my $lonhttpd_port=$Apache::lonnet::perlvar{'lonhttpdPort'};
     if (!defined($lonhttpd_port)) { $lonhttpd_port='8080'; }
+    # IE doesn't like a secure page getting images from a non-secure
+    # port (when logging we haven't parsed the browser type so default
+    # back to secure
+    if ((!exists($env{'browser.type'}) || $env{'browser.type'} eq 'explorer')
+	&& $ENV{'SERVER_PORT'} == 443) {
+	return 443;
+    }
+    return $lonhttpd_port;
+
+}
+
+sub lonhttpdurl {
+    my ($url)=@_;
+
+    my $lonhttpd_port = &lonhttpd_port();
+    if ($lonhttpd_port == 443) {
+	return 'https://'.$ENV{'SERVER_NAME'}.$url;
+    }
     return 'http://'.$ENV{'SERVER_NAME'}.':'.$lonhttpd_port.$url;
 }