'.
&mt('Field').' | '.&mt('Samples').' |
');
- %sone=&record_sep($$records[0]);
- if (defined($$records[1])) {%stwo=&record_sep($$records[1]);}
- if (defined($$records[2])) {%sthree=&record_sep($$records[2]);}
- #
- foreach (sort keys %sone) {
+
+ foreach my $key (sort(keys(%{ $samples->[0] }))) {
$r->print(' | ');
- if (defined($sone{$_})) { $r->print($sone{$_}."\n"); }
- if (defined($stwo{$_})) { $r->print($stwo{$_}."\n"); }
- if (defined($sthree{$_})) { $r->print($sthree{$_}."\n"); }
+ foreach my $line (0..2) {
+ if (defined($samples->[$line]{$key})) {
+ $r->print($samples->[$line]{$key}." \n");
+ }
+ }
$r->print(' |
');
$i++;
}
@@ -2730,8 +5752,12 @@ sub check_if_partid_hidden {
=pod
+=back
+
=head1 cgi-bin script and graphing routines
+=over 4
+
=item get_cgi_id
Inputs: none
@@ -2747,8 +5773,8 @@ the routine &Apache::lonnet::transfer_pr
############################################################
my $uniq=0;
sub get_cgi_id {
- $uniq=($uniq++)%100000;
- return (time.'_'.$uniq);
+ $uniq=($uniq+1)%100000;
+ return (time.'_'.$$.'_'.$uniq);
}
############################################################
@@ -2779,9 +5805,14 @@ If $Max is < any data point, the graph w
=item $colors: array ref holding the colors to be used for the data sets when
they are plotted. If undefined, default values will be used.
+=item $labels: array ref holding the labels to use on the x-axis for the bars.
+
=item @Values: An array of array references. Each array reference holds data
to be plotted in a stacked bar chart.
+=item If the final element of @Values is a hash reference the key/value
+pairs will be added to the graph definition.
+
=back
Returns:
@@ -2794,7 +5825,7 @@ information for the plot.
############################################################
############################################################
sub DrawBarGraph {
- my ($Title,$xlabel,$ylabel,$Max,$colors,@Values)=@_;
+ my ($Title,$xlabel,$ylabel,$Max,$colors,$labels,@Values)=@_;
#
if (! defined($colors)) {
$colors = ['#33ff00',
@@ -2802,13 +5833,28 @@ sub DrawBarGraph {
'#66ccff', '#ff9999', '#cccc33', '#660000', '#33cc66',
];
}
+ my $extra_settings = {};
+ if (ref($Values[-1]) eq 'HASH') {
+ $extra_settings = pop(@Values);
+ }
#
my $identifier = &get_cgi_id();
my $id = 'cgi.'.$identifier;
if (! @Values || ref($Values[0]) ne 'ARRAY') {
return '';
}
+ #
+ my @Labels;
+ if (defined($labels)) {
+ @Labels = @$labels;
+ } else {
+ for (my $i=0;$i<@{$Values[0]};$i++) {
+ push (@Labels,$i+1);
+ }
+ }
+ #
my $NumBars = scalar(@{$Values[0]});
+ if ($NumBars < scalar(@Labels)) { $NumBars = scalar(@Labels); }
my %ValuesHash;
my $NumSets=1;
foreach my $array (@Values) {
@@ -2818,7 +5864,15 @@ sub DrawBarGraph {
}
#
my ($height,$width,$xskip,$bar_width) = (200,120,1,15);
- if ($NumBars < 10) {
+ if ($NumBars < 3) {
+ $width = 120+$NumBars*32;
+ $xskip = 1;
+ $bar_width = 30;
+ } elsif ($NumBars < 5) {
+ $width = 120+$NumBars*20;
+ $xskip = 1;
+ $bar_width = 20;
+ } elsif ($NumBars < 10) {
$width = 120+$NumBars*15;
$xskip = 1;
$bar_width = 15;
@@ -2836,11 +5890,6 @@ sub DrawBarGraph {
$bar_width = 4;
}
#
- my @Labels;
- for (my $i=0;$i<@{$Values[0]};$i++) {
- push (@Labels,$i+1);
- }
- #
$Max = 1 if ($Max < 1);
if ( int($Max) < $Max ) {
$Max++;
@@ -2849,9 +5898,9 @@ sub DrawBarGraph {
$Title = '' if (! defined($Title));
$xlabel = '' if (! defined($xlabel));
$ylabel = '' if (! defined($ylabel));
- $ValuesHash{$id.'.title'} = &Apache::lonnet::escape($Title);
- $ValuesHash{$id.'.xlabel'} = &Apache::lonnet::escape($xlabel);
- $ValuesHash{$id.'.ylabel'} = &Apache::lonnet::escape($ylabel);
+ $ValuesHash{$id.'.title'} = &escape($Title);
+ $ValuesHash{$id.'.xlabel'} = &escape($xlabel);
+ $ValuesHash{$id.'.ylabel'} = &escape($ylabel);
$ValuesHash{$id.'.y_max_value'} = $Max;
$ValuesHash{$id.'.NumBars'} = $NumBars;
$ValuesHash{$id.'.NumSets'} = $NumSets;
@@ -2863,6 +5912,11 @@ sub DrawBarGraph {
$ValuesHash{$id.'.bar_width'} = $bar_width;
$ValuesHash{$id.'.labels'} = join(',',@Labels);
#
+ # Deal with other parameters
+ while (my ($key,$value) = each(%$extra_settings)) {
+ $ValuesHash{$id.'.'.$key} = $value;
+ }
+ #
&Apache::lonnet::appenv(%ValuesHash);
return '';
}
@@ -2897,7 +5951,7 @@ plotted in. If undefined, default value
=item $Xlabels: Array ref containing the labels to be used for the X-axis.
=item $Ydata: Array ref containing Array refs.
-Each of the contained arrays will be plotted as a seperate curve.
+Each of the contained arrays will be plotted as a separate curve.
=item %Values: hash indicating or overriding any default values which are
passed to graph.png.
@@ -2926,9 +5980,9 @@ sub DrawXYGraph {
$ylabel = '' if (! defined($ylabel));
my %ValuesHash =
(
- $id.'.title' => &Apache::lonnet::escape($Title),
- $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
- $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
+ $id.'.title' => &escape($Title),
+ $id.'.xlabel' => &escape($xlabel),
+ $id.'.ylabel' => &escape($ylabel),
$id.'.y_max_value'=> $Max,
$id.'.labels' => join(',',@$Xlabels),
$id.'.PlotType' => 'XY',
@@ -3023,9 +6077,9 @@ sub DrawXYYGraph {
$ylabel = '' if (! defined($ylabel));
my %ValuesHash =
(
- $id.'.title' => &Apache::lonnet::escape($Title),
- $id.'.xlabel' => &Apache::lonnet::escape($xlabel),
- $id.'.ylabel' => &Apache::lonnet::escape($ylabel),
+ $id.'.title' => &escape($Title),
+ $id.'.xlabel' => &escape($xlabel),
+ $id.'.ylabel' => &escape($ylabel),
$id.'.labels' => join(',',@$Xlabels),
$id.'.PlotType' => 'XY',
$id.'.NumSets' => 2,
@@ -3064,10 +6118,14 @@ sub DrawXYYGraph {
=pod
+=back
+
=head1 Statistics helper routines?
Bad place for them but what the hell.
+=over 4
+
=item &chartlink
Returns a link to the chart for a specific student.
@@ -3084,6 +6142,8 @@ Inputs:
=back
+=back
+
=cut
############################################################
@@ -3091,14 +6151,739 @@ Inputs:
sub chartlink {
my ($linktext, $sname, $sdomain) = @_;
my $link = ''.$linktext.'';
}
+#######################################################
+#######################################################
+
+=pod
+
+=head1 Course Environment Routines
+
+=over 4
+
+=item &restore_course_settings
+
+=item &store_course_settings
+
+Restores/Store indicated form parameters from the course environment.
+Will not overwrite existing values of the form parameters.
+
+Inputs:
+a scalar describing the data (e.g. 'chart', 'problem_analysis')
+
+a hash ref describing the data to be stored. For example:
+
+%Save_Parameters = ('Status' => 'scalar',
+ 'chartoutputmode' => 'scalar',
+ 'chartoutputdata' => 'scalar',
+ 'Section' => 'array',
+ 'Group' => 'array',
+ 'StudentData' => 'array',
+ 'Maps' => 'array');
+
+Returns: both routines return nothing
+
+=cut
+
+#######################################################
+#######################################################
+sub store_course_settings {
+ return &store_settings($env{'request.course.id'},@_);
+}
+
+sub store_settings {
+ # save to the environment
+ # appenv the same items, just to be safe
+ my $udom = $env{'user.domain'};
+ my $uname = $env{'user.name'};
+ my ($context,$prefix,$Settings) = @_;
+ my %SaveHash;
+ my %AppHash;
+ while (my ($setting,$type) = each(%$Settings)) {
+ my $basename = join('.','internal',$context,$prefix,$setting);
+ my $envname = 'environment.'.$basename;
+ if (exists($env{'form.'.$setting})) {
+ # Save this value away
+ if ($type eq 'scalar' &&
+ (! exists($env{$envname}) ||
+ $env{$envname} ne $env{'form.'.$setting})) {
+ $SaveHash{$basename} = $env{'form.'.$setting};
+ $AppHash{$envname} = $env{'form.'.$setting};
+ } elsif ($type eq 'array') {
+ my $stored_form;
+ if (ref($env{'form.'.$setting})) {
+ $stored_form = join(',',
+ map {
+ &escape($_);
+ } sort(@{$env{'form.'.$setting}}));
+ } else {
+ $stored_form =
+ &escape($env{'form.'.$setting});
+ }
+ # Determine if the array contents are the same.
+ if ($stored_form ne $env{$envname}) {
+ $SaveHash{$basename} = $stored_form;
+ $AppHash{$envname} = $stored_form;
+ }
+ }
+ }
+ }
+ my $put_result = &Apache::lonnet::put('environment',\%SaveHash,
+ $udom,$uname);
+ if ($put_result !~ /^(ok|delayed)/) {
+ &Apache::lonnet::logthis('unable to save form parameters, '.
+ 'got error:'.$put_result);
+ }
+ # Make sure these settings stick around in this session, too
+ &Apache::lonnet::appenv(%AppHash);
+ return;
+}
+
+sub restore_course_settings {
+ return &restore_settings($env{'request.course.id'},@_);
+}
+
+sub restore_settings {
+ my ($context,$prefix,$Settings) = @_;
+ while (my ($setting,$type) = each(%$Settings)) {
+ next if (exists($env{'form.'.$setting}));
+ my $envname = 'environment.internal.'.$context.'.'.$prefix.
+ '.'.$setting;
+ if (exists($env{$envname})) {
+ if ($type eq 'scalar') {
+ $env{'form.'.$setting} = $env{$envname};
+ } elsif ($type eq 'array') {
+ $env{'form.'.$setting} = [
+ map {
+ &unescape($_);
+ } split(',',$env{$envname})
+ ];
+ }
+ }
+ }
+}
+
+############################################################
+############################################################
+
+sub commit_customrole {
+ my ($udom,$uname,$url,$three,$four,$five,$start,$end) = @_;
+ my $output = &mt('Assigning custom role').' "'.$five.'" by '.$four.'@'.$three.' in '.$url.
+ ($start?', '.&mt('starting').' '.localtime($start):'').
+ ($end?', ending '.localtime($end):'').': '.
+ &Apache::lonnet::assigncustomrole(
+ $udom,$uname,$url,$three,$four,$five,$end,$start).
+ '
';
+ return $output;
+}
+
+sub commit_standardrole {
+ my ($udom,$uname,$url,$three,$start,$end,$one,$two,$sec) = @_;
+ my $output;
+ my $logmsg;
+ if ($three eq 'st') {
+ my $result = &commit_studentrole(\$logmsg,$udom,$uname,$url,$three,$start,$end,$one,$two,$sec);
+ if (($result =~ /^error/) || ($result eq 'not_in_class') || ($result eq 'unknown_course')) {
+ $output = "Error: $result\n";
+ } else {
+ $output = &mt('Assigning').' '.$three.' in '.$url.
+ ($start?', '.&mt('starting').' '.localtime($start):'').
+ ($end?', '.&mt('ending').' '.localtime($end):'').
+ ': '.$result.'
'.
+ &mt('Add to classlist').': ok
';
+ }
+ } else {
+ $output = &mt('Assigning').' '.$three.' in '.$url.
+ ($start?', '.&mt('starting').' '.localtime($start):'').
+ ($end?', '.&mt('ending').' '.localtime($end):'').': '.
+ &Apache::lonnet::assignrole(
+ $udom,$uname,$url,$three,$end,$start).
+ '
';
+ }
+ return $output;
+}
+
+sub commit_studentrole {
+ my ($logmsg,$udom,$uname,$url,$three,$start,$end,$one,$two,$sec) = @_;
+ my $linefeed = '
'."\n";
+ my $result;
+ if (defined($one) && defined($two)) {
+ my $cid=$one.'_'.$two;
+ my $oldsec=&Apache::lonnet::getsection($udom,$uname,$cid);
+ my $secchange = 0;
+ my $expire_role_result;
+ my $modify_section_result;
+ unless ($oldsec eq '-1') {
+ unless ($sec eq $oldsec) {
+ $secchange = 1;
+ my $uurl='/'.$cid;
+ $uurl=~s/\_/\//g;
+ if ($oldsec) {
+ $uurl.='/'.$oldsec;
+ }
+ $expire_role_result = &Apache::lonnet::assignrole($udom,$uname,$uurl,'st',time);
+ $result = $expire_role_result;
+ }
+ }
+ if (($expire_role_result eq 'ok') || ($secchange == 0)) {
+ $modify_section_result = &Apache::lonnet::modify_student_enrollment($udom,$uname,undef,undef,undef,undef,undef,$sec,$end,$start,'','',$cid);
+ if ($modify_section_result =~ /^ok/) {
+ if ($secchange == 1) {
+ $$logmsg .= "Section for $uname switched from old section: $oldsec to new section: $sec".$linefeed;
+ } elsif ($oldsec eq '-1') {
+ $$logmsg .= "New student role for $uname in section $sec in course $cid".$linefeed;
+ } else {
+ $$logmsg .= "Student $uname assigned to unchanged section $sec in course $cid".$linefeed;
+ }
+ } else {
+ $$logmsg .= "Error when attempting section change for $uname from old section $oldsec to new section: $sec in course $cid -error: $modify_section_result".$linefeed;
+ }
+ $result = $modify_section_result;
+ } elsif ($secchange == 1) {
+ $$logmsg .= "Error when attempting to expire role for $uname in old section $oldsec in course $cid -error: $expire_role_result".$linefeed;
+ }
+ } else {
+ $$logmsg .= "Incomplete course id defined. Addition of user $uname from domain $udom to course $one\_$two, section $sec not completed.$linefeed";
+ $result = "error: incomplete course id\n";
+ }
+ return $result;
+}
+
############################################################
############################################################
+sub construct_course {
+ my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname) = @_;
+ my $outcome;
+
+#
+# Open course
+#
+ my $crstype = lc($args->{'crstype'});
+ my %cenv=();
+ $$courseid=&Apache::lonnet::createcourse($args->{'course_domain'},
+ $args->{'cdescr'},
+ $args->{'curl'},
+ $args->{'course_home'},
+ $args->{'nonstandard'},
+ $args->{'crscode'},
+ $args->{'ccuname'}.':'.
+ $args->{'ccdomain'},
+ $args->{'crstype'});
+
+ # Note: The testing routines depend on this being output; see
+ # Utils::Course. This needs to at least be output as a comment
+ # 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);
+#
+# Check if created correctly
+#
+ ($$crsudom,$$crsunum)= &LONCAPA::split_courseid($$courseid);
+ my $crsuhome=&Apache::lonnet::homeserver($$crsunum,$$crsudom);
+ $outcome .= &mt('Created on').': '.$crsuhome.'
';
+#
+# Are we cloning?
+#
+ my $cloneid='';
+ if (($args->{'clonecourse'}) && ($args->{'clonedomain'})) {
+ $cloneid='/'.$args->{'clonedomain'}.'/'.$args->{'clonecourse'};
+ my ($clonecrsudom,$clonecrsunum)= &LONCAPA::split_courseid($cloneid);
+ my $clonehome=&Apache::lonnet::homeserver($clonecrsunum,$clonecrsudom);
+ if ($clonehome eq 'no_host') {
+ $outcome .=
+ '
'.&mt('Attempting to clone non-existing [_1]',$crstype).' '.$cloneid.'';
+ } else {
+ $outcome .=
+ '
'.&mt('Cloning [_1] from [_2]',$crstype,$clonehome).'';
+ my %oldcenv=&Apache::lonnet::dump('environment',$$crsudom,$$crsunum);
+# Copy all files
+ &Apache::lonclonecourse::copycoursefiles($cloneid,$$courseid);
+# Restore URL
+ $cenv{'url'}=$oldcenv{'url'};
+# Restore title
+ $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'});
+ }
+ }
+#
+# Set environment (will override cloned, if existing)
+#
+ my @sections = ();
+ my @xlists = ();
+ if ($args->{'crstype'}) {
+ $cenv{'type'}=$args->{'crstype'};
+ }
+ if ($args->{'crsid'}) {
+ $cenv{'courseid'}=$args->{'crsid'};
+ }
+ if ($args->{'crscode'}) {
+ $cenv{'internal.coursecode'}=$args->{'crscode'};
+ }
+ if ($args->{'crsquota'} ne '') {
+ $cenv{'internal.coursequota'}=$args->{'crsquota'};
+ } else {
+ $cenv{'internal.coursequota'}=$args->{'crsquota'} = 20;
+ }
+ if ($args->{'ccuname'}) {
+ $cenv{'internal.courseowner'} = $args->{'ccuname'}.
+ ':'.$args->{'ccdomain'};
+ } else {
+ $cenv{'internal.courseowner'} = $args->{'curruser'};
+ }
+
+ my @badclasses = (); # Used to accumulate sections/crosslistings that did not pass classlist access check for course owner.
+ if ($args->{'crssections'}) {
+ $cenv{'internal.sectionnums'} = '';
+ if ($args->{'crssections'} =~ m/,/) {
+ @sections = split/,/,$args->{'crssections'};
+ } else {
+ $sections[0] = $args->{'crssections'};
+ }
+ if (@sections > 0) {
+ foreach my $item (@sections) {
+ my ($sec,$gp) = split/:/,$item;
+ my $class = $args->{'crscode'}.$sec;
+ my $addcheck = &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$class,$cenv{'internal.courseowner'});
+ $cenv{'internal.sectionnums'} .= $item.',';
+ unless ($addcheck eq 'ok') {
+ push @badclasses, $class;
+ }
+ }
+ $cenv{'internal.sectionnums'} =~ s/,$//;
+ }
+ }
+# do not hide course coordinator from staff listing,
+# even if privileged
+ $cenv{'nothideprivileged'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
+# add crosslistings
+ if ($args->{'crsxlist'}) {
+ $cenv{'internal.crosslistings'}='';
+ if ($args->{'crsxlist'} =~ m/,/) {
+ @xlists = split/,/,$args->{'crsxlist'};
+ } else {
+ $xlists[0] = $args->{'crsxlist'};
+ }
+ if (@xlists > 0) {
+ foreach my $item (@xlists) {
+ my ($xl,$gp) = split/:/,$item;
+ my $addcheck = &Apache::lonnet::auto_new_course($$crsunum,$$crsudom,$xl,$cenv{'internal.courseowner'});
+ $cenv{'internal.crosslistings'} .= $item.',';
+ unless ($addcheck eq 'ok') {
+ push @badclasses, $xl;
+ }
+ }
+ $cenv{'internal.crosslistings'} =~ s/,$//;
+ }
+ }
+ if ($args->{'autoadds'}) {
+ $cenv{'internal.autoadds'}=$args->{'autoadds'};
+ }
+ if ($args->{'autodrops'}) {
+ $cenv{'internal.autodrops'}=$args->{'autodrops'};
+ }
+# check for notification of enrollment changes
+ my @notified = ();
+ if ($args->{'notify_owner'}) {
+ if ($args->{'ccuname'} ne '') {
+ push(@notified,$args->{'ccuname'}.':'.$args->{'ccdomain'});
+ }
+ }
+ if ($args->{'notify_dc'}) {
+ if ($uname ne '') {
+ push(@notified,$uname.'@'.$udom);
+ }
+ }
+ if (@notified > 0) {
+ my $notifylist;
+ if (@notified > 1) {
+ $notifylist = join(',',@notified);
+ } else {
+ $notifylist = $notified[0];
+ }
+ $cenv{'internal.notifylist'} = $notifylist;
+ }
+ if (@badclasses > 0) {
+ my %lt=&Apache::lonlocal::texthash(
+ 'tclb' => 'The courses listed below were included as sections or crosslistings affiliated with your new LON-CAPA course. However, if automated course roster updates are enabled for this class, these particular sections/crosslistings will not contribute towards enrollment, because the user identified as the course owner for this LON-CAPA course',
+ 'dnhr' => 'does not have rights to access enrollment in these classes',
+ 'adby' => 'as determined by the policies of your institution on access to official classlists'
+ );
+ $outcome .= ''.$lt{'tclb'}.' ('.$cenv{'internal.courseowner'}.') - '.$lt{'dnhr'}.' ('.$lt{'adby'}.').
'."\n";
+ foreach (@badclasses) {
+ $outcome .= "- $_
\n";
+ }
+ $outcome .= "
\n";
+ }
+ if ($args->{'no_end_date'}) {
+ $args->{'endaccess'} = 0;
+ }
+ $cenv{'internal.autostart'}=$args->{'enrollstart'};
+ $cenv{'internal.autoend'}=$args->{'enrollend'};
+ $cenv{'default_enrollment_start_date'}=$args->{'startaccess'};
+ $cenv{'default_enrollment_end_date'}=$args->{'endaccess'};
+ if ($args->{'showphotos'}) {
+ $cenv{'internal.showphotos'}=$args->{'showphotos'};
+ }
+ $cenv{'internal.authtype'} = $args->{'authtype'};
+ $cenv{'internal.autharg'} = $args->{'autharg'};
+ if ( ($cenv{'internal.authtype'} =~ /^krb/) && ($cenv{'internal.autoadds'} == 1)) {
+ if (! defined($cenv{'internal.autharg'}) || $cenv{'internal.autharg'} eq '') {
+ $outcome .= ''.
+ &mt('As you did not include the default Kerberos domain to be used for authentication in this class, the institutional data used by the automated enrollment process must include the Kerberos domain for each new student').'';
+ }
+ }
+ if (($args->{'ccdomain'}) && ($args->{'ccuname'})) {
+ if ($args->{'setpolicy'}) {
+ $cenv{'policy.email'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
+ }
+ if ($args->{'setcontent'}) {
+ $cenv{'question.email'}=$args->{'ccuname'}.':'.$args->{'ccdomain'};
+ }
+ }
+ if ($args->{'reshome'}) {
+ $cenv{'reshome'}=$args->{'reshome'}.'/';
+ $cenv{'reshome'}=~s/\/+$/\//;
+ }
+#
+# course has keyed access
+#
+ if ($args->{'setkeys'}) {
+ $cenv{'keyaccess'}='yes';
+ }
+# if specified, key authority is not course, but user
+# only active if keyaccess is yes
+ if ($args->{'keyauth'}) {
+ my ($user,$domain) = split(':',$args->{'keyauth'});
+ $user = &LONCAPA::clean_username($user);
+ $domain = &LONCAPA::clean_username($domain);
+ if ($user ne '' && $domain ne '') {
+ $cenv{'keyauth'}=$user.':'.$domain;
+ }
+ }
+
+ if ($args->{'disresdis'}) {
+ $cenv{'pch.roles.denied'}='st';
+ }
+ if ($args->{'disablechat'}) {
+ $cenv{'plc.roles.denied'}='st';
+ }
+
+ # Record we've not yet viewed the Course Initialization Helper for this
+ # course
+ $cenv{'course.helper.not.run'} = 1;
+ #
+ # Use new Randomseed
+ #
+ $cenv{'rndseed'}=&Apache::lonnet::latest_rnd_algorithm_id();;
+ $cenv{'receiptalg'}=&Apache::lonnet::latest_receipt_algorithm_id();;
+ #
+ # The encryption code and receipt prefix for this course
+ #
+ $cenv{'internal.encseed'}=$Apache::lonnet::perlvar{'lonReceipt'}.$$.time.int(rand(9999));
+ $cenv{'internal.encpref'}=100+int(9*rand(99));
+ #
+ # By default, use standard grading
+ if (!defined($cenv{'grading'})) { $cenv{'grading'} = 'standard'; }
+
+ $outcome .= ('
'.&mt('Setting environment').': '.
+ &Apache::lonnet::put('environment',\%cenv,$$crsudom,$$crsunum).'
');
+#
+# Open all assignments
+#
+ if ($args->{'openall'}) {
+ my $storeunder=$$crsudom.'_'.$$crsunum.'.0.opendate';
+ my %storecontent = ($storeunder => time,
+ $storeunder.'.type' => 'date_start');
+
+ $outcome .= &mt('Opening all assignments').': '.&Apache::lonnet::cput
+ ('resourcedata',\%storecontent,$$crsudom,$$crsunum).'
';
+ }
+#
+# Set first page
+#
+ unless (($args->{'nonstandard'}) || ($args->{'firstres'} eq 'blank')
+ || ($cloneid)) {
+ use LONCAPA::map;
+ $outcome .= &mt('Setting first resource').': ';
+
+ my $map = '/uploaded/'.$$crsudom.'/'.$$crsunum.'/default.sequence';
+ my ($errtext,$fatal)=&LONCAPA::map::mapread($map);
+
+ $outcome .= ($fatal?$errtext:'read ok').' - ';
+ my $title; my $url;
+ if ($args->{'firstres'} eq 'syl') {
+ $title='Syllabus';
+ $url='/public/'.$$crsudom.'/'.$$crsunum.'/syllabus';
+ } else {
+ $title='Navigate Contents';
+ $url='/adm/navmaps';
+ }
+
+ $LONCAPA::map::resources[1]=$title.':'.$url.':false:start:res';
+ (my $outtext,$errtext) = &LONCAPA::map::storemap($map,1);
+
+ if ($errtext) { $fatal=2; }
+ $outcome .= ($fatal?$errtext:'write ok').'
';
+ }
+ return $outcome;
+}
+
+############################################################
+############################################################
+
+sub course_type {
+ my ($cid) = @_;
+ if (!defined($cid)) {
+ $cid = $env{'request.course.id'};
+ }
+ if (defined($env{'course.'.$cid.'.type'})) {
+ return $env{'course.'.$cid.'.type'};
+ } else {
+ return 'Course';
+ }
+}
+
+sub group_term {
+ my $crstype = &course_type();
+ my %names = (
+ 'Course' => 'group',
+ 'Group' => 'team',
+ );
+ return $names{$crstype};
+}
+
+sub icon {
+ my ($file)=@_;
+ my $curfext = lc((split(/\./,$file))[-1]);
+ my $iconname=$Apache::lonnet::perlvar{'lonIconsURL'}.'/unknown.gif';
+ my $embstyle = &Apache::loncommon::fileembstyle($curfext);
+ if (!(!defined($embstyle) || $embstyle eq 'unk' || $embstyle eq 'hdn')) {
+ if (-e $Apache::lonnet::perlvar{'lonDocRoot'}.'/'.
+ $Apache::lonnet::perlvar{'lonIconsURL'}.'/'.
+ $curfext.".gif") {
+ $iconname=$Apache::lonnet::perlvar{'lonIconsURL'}.'/'.
+ $curfext.".gif";
+ }
+ }
+ return &lonhttpdurl($iconname);
+}
+
+sub lonhttpdurl {
+ my ($url)=@_;
+ my $lonhttpd_port=$Apache::lonnet::perlvar{'lonhttpdPort'};
+ if (!defined($lonhttpd_port)) { $lonhttpd_port='8080'; }
+ return 'http://'.$ENV{'SERVER_NAME'}.':'.$lonhttpd_port.$url;
+}
+
+sub connection_aborted {
+ my ($r)=@_;
+ $r->print(" ");$r->rflush();
+ my $c = $r->connection;
+ return $c->aborted();
+}
+
+# Escapes strings that may have embedded 's that will be put into
+# strings as 'strings'.
+sub escape_single {
+ my ($input) = @_;
+ $input =~ s/\\/\\\\/g; # Escape the \'s..(must be first)>
+ $input =~ s/\'/\\\'/g; # Esacpe the 's....
+ return $input;
+}
+
+# Same as escape_single, but escape's "'s This
+# can be used for "strings"
+sub escape_double {
+ my ($input) = @_;
+ $input =~ s/\\/\\\\/g; # Escape the /'s..(must be first)>
+ $input =~ s/\"/\\\"/g; # Esacpe the "s....
+ return $input;
+}
+
+# Escapes the last element of a full URL.
+sub escape_url {
+ my ($url) = @_;
+ my @urlslices = split(/\//, $url,-1);
+ my $lastitem = &escape(pop(@urlslices));
+ return join('/',@urlslices).'/'.$lastitem;
+}
+
+# -------------------------------------------------------- Initliaze user login
+sub init_user_environment {
+ my ($r, $username, $domain, $authhost, $form, $args) = @_;
+ my $lonids=$Apache::lonnet::perlvar{'lonIDsDir'};
+
+ my $public=($username eq 'public' && $domain eq 'public');
+
+# See if old ID present, if so, remove
+
+ my ($filename,$cookie,$userroles);
+ my $now=time;
+
+ if ($public) {
+ my $max_public=100;
+ my $oldest;
+ my $oldest_time=0;
+ for(my $next=1;$next<=$max_public;$next++) {
+ if (-e $lonids."/publicuser_$next.id") {
+ my $mtime=(stat($lonids."/publicuser_$next.id"))[9];
+ if ($mtime<$oldest_time || !$oldest_time) {
+ $oldest_time=$mtime;
+ $oldest=$next;
+ }
+ } else {
+ $cookie="publicuser_$next";
+ last;
+ }
+ }
+ if (!$cookie) { $cookie="publicuser_$oldest"; }
+ } else {
+ # if this isn't a robot, kill any existing non-robot sessions
+ if (!$args->{'robot'}) {
+ opendir(DIR,$lonids);
+ while ($filename=readdir(DIR)) {
+ if ($filename=~/^$username\_\d+\_$domain\_$authhost\.id$/) {
+ unlink($lonids.'/'.$filename);
+ }
+ }
+ closedir(DIR);
+ }
+# Give them a new cookie
+ my $id = ($args->{'robot'} ? 'robot'.$args->{'robot'}
+ : $now);
+ $cookie="$username\_$id\_$domain\_$authhost";
+
+# Initialize roles
+
+ $userroles=&Apache::lonnet::rolesinit($domain,$username,$authhost);
+ }
+# ------------------------------------ Check browser type and MathML capability
+
+ my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
+ $clientunicode,$clientos) = &decode_user_agent($r);
+
+# -------------------------------------- Any accessibility options to remember?
+ if (($form->{'interface'}) && ($form->{'remember'} eq 'true')) {
+ foreach my $option ('imagesuppress','appletsuppress',
+ 'embedsuppress','fontenhance','blackwhite') {
+ if ($form->{$option} eq 'true') {
+ &Apache::lonnet::put('environment',{$option => 'on'},
+ $domain,$username);
+ } else {
+ &Apache::lonnet::del('environment',[$option],
+ $domain,$username);
+ }
+ }
+ }
+# ------------------------------------------------------------- Get environment
+
+ my %userenv = &Apache::lonnet::dump('environment',$domain,$username);
+ my ($tmp) = keys(%userenv);
+ if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
+ # default remote control to off
+ if ($userenv{'remote'} ne 'on') { $userenv{'remote'} = 'off'; }
+ } else {
+ undef(%userenv);
+ }
+ if (($userenv{'interface'}) && (!$form->{'interface'})) {
+ $form->{'interface'}=$userenv{'interface'};
+ }
+ $env{'environment.remote'}=$userenv{'remote'};
+ if ($userenv{'texengine'} eq 'ttm') { $clientmathml=1; }
+
+# --------------- Do not trust query string to be put directly into environment
+ foreach my $option ('imagesuppress','appletsuppress',
+ 'embedsuppress','fontenhance','blackwhite',
+ 'interface','localpath','localres') {
+ $form->{$option}=~s/[\n\r\=]//gs;
+ }
+# --------------------------------------------------------- Write first profile
+
+ {
+ my %initial_env =
+ ("user.name" => $username,
+ "user.domain" => $domain,
+ "user.home" => $authhost,
+ "browser.type" => $clientbrowser,
+ "browser.version" => $clientversion,
+ "browser.mathml" => $clientmathml,
+ "browser.unicode" => $clientunicode,
+ "browser.os" => $clientos,
+ "server.domain" => $Apache::lonnet::perlvar{'lonDefDomain'},
+ "request.course.fn" => '',
+ "request.course.uri" => '',
+ "request.course.sec" => '',
+ "request.role" => 'cm',
+ "request.role.adv" => $env{'user.adv'},
+ "request.host" => $ENV{'REMOTE_ADDR'},);
+
+ if ($form->{'localpath'}) {
+ $initial_env{"browser.localpath"} = $form->{'localpath'};
+ $initial_env{"browser.localres"} = $form->{'localres'};
+ }
+
+ if ($public) {
+ $initial_env{"environment.remote"} = "off";
+ }
+ if ($form->{'interface'}) {
+ $form->{'interface'}=~s/\W//gs;
+ $initial_env{"browser.interface"} = $form->{'interface'};
+ $env{'browser.interface'}=$form->{'interface'};
+ foreach my $option ('imagesuppress','appletsuppress',
+ 'embedsuppress','fontenhance','blackwhite') {
+ if (($form->{$option} eq 'true') ||
+ ($userenv{$option} eq 'on')) {
+ $initial_env{"browser.$option"} = "on";
+ }
+ }
+ }
+
+ $env{'user.environment'} = "$lonids/$cookie.id";
+
+ if (tie(my %disk_env,'GDBM_File',"$lonids/$cookie.id",
+ &GDBM_WRCREAT(),0640)) {
+ &_add_to_env(\%disk_env,\%initial_env);
+ &_add_to_env(\%disk_env,\%userenv,'environment.');
+ &_add_to_env(\%disk_env,$userroles);
+ if (ref($args->{'extra_env'})) {
+ &_add_to_env(\%disk_env,$args->{'extra_env'});
+ }
+ untie(%disk_env);
+ } else {
+ &Apache::lonnet::logthis("WARNING: ".
+ 'Could not create environment storage in lonauth: '.$!.'');
+ return 'error: '.$!;
+ }
+ }
+ $env{'request.role'}='cm';
+ $env{'request.role.adv'}=$env{'user.adv'};
+ $env{'browser.type'}=$clientbrowser;
+
+ return $cookie;
+
+}
+
+sub _add_to_env {
+ my ($idf,$env_data,$prefix) = @_;
+ while (my ($key,$value) = each(%$env_data)) {
+ $idf->{$prefix.$key} = $value;
+ $env{$prefix.$key} = $value;
+ }
+}
+
+
=pod
=back
500 Internal Server Error
Internal Server Error
The server encountered an internal error or
misconfiguration and was unable to complete
your request.
Please contact the server administrator at
root@localhost to inform them of the time this error occurred,
and the actions you performed just before this error.
More information about this error may be available
in the server error log.