--- loncom/interface/lonsyllabus.pm 2006/10/23 20:25:45 1.56 +++ loncom/interface/lonsyllabus.pm 2015/06/09 21:22:57 1.138 @@ -1,7 +1,7 @@ # The LearningOnline Network # Syllabus # -# $Id: lonsyllabus.pm,v 1.56 2006/10/23 20:25:45 banghart Exp $ +# $Id: lonsyllabus.pm,v 1.138 2015/06/09 21:22:57 damieng Exp $ # # Copyright Michigan State University Board of Trustees # @@ -29,11 +29,13 @@ package Apache::lonsyllabus; use strict; +use Apache::lontemplate; use Apache::Constants qw(:common); use Apache::loncommon; use Apache::lonnet; use Apache::lontexconvert; use Apache::lonfeedback; +use Apache::lonhtmlgateway; use Apache::lonannounce; use Apache::lonlocal; use Apache::lonhtmlcommon; @@ -51,40 +53,147 @@ sub handler { my (undef,undef,$cdom,$cnum)=split(/\//,$r->uri); # ------------------------------------------------------------ Get query string &Apache::loncommon::get_unprocessed_cgi - ($ENV{'QUERY_STRING'},['forcestudent','register','forceedit','wrapperdisplay']); + ($ENV{'QUERY_STRING'},['register','forceedit','todocs', + 'folderpath','title','only_body']); # ----------------------------------------------------- Is this even a course? my $homeserver=&Apache::lonnet::homeserver($cnum,$cdom); if ($homeserver eq 'no_host') { &Apache::loncommon::content_type($r,'text/html'); $r->send_http_header; - &Apache::loncommon::simple_error_page($r,'No syllabus available', - 'No syllabus available'); + &Apache::loncommon::simple_error_page($r,'No syllabus available', + 'No syllabus available'); + return OK; + } elsif (!&Apache::lonnet::is_course($cdom,$cnum)) { + &Apache::loncommon::content_type($r,'text/html'); + $r->send_http_header; + &Apache::loncommon::simple_error_page($r,'No syllabus available', + 'The course/community for which the syllabus was requested does not exist.'); return OK; } # ------------------------------------- There is such a course, get environment my %courseenv=&Apache::lonnet::dump('environment',$cdom,$cnum); + my $crstype = &Apache::loncommon::course_type(); -# ------------------------------------------------------------ Print the screen +# --------------------------------------------------------------- Force Student + my ($forceedit,$forcestudent); + if ($env{'form.forceedit'}) { $forceedit=1; } + if (!$forceedit) { + $forcestudent=1; + } - my $rss_link = - &Apache::lonrss::rss_link('http://'.$ENV{'HTTP_HOST'}.'/public/'.$cdom.'/'.$cnum.'/Course_Announcements.rss'); +# --------------------------------------------------------------- Check Privileges + my $allowed = 0; + if ($env{'user.environment'}) { +# does this user have privileges to post, etc? + if ($env{'request.course.id'} + && $cdom eq $env{'course.'.$env{'request.course.id'}.'.domain'} + && $cnum eq $env{'course.'.$env{'request.course.id'}.'.num'}) { + $allowed=&Apache::lonnet::allowed('mdc',$env{'request.course.id'}); + if ($forcestudent or $target eq 'tex') { $allowed=0; } + } + } - if ($target eq 'tex') { - $r->print(&Apache::lonprintout::print_latex_header($env{'form.latex_type'})); - } # -------------------------------------------------- Let's see who handles this - my $externalsyllabus=$courseenv{'externalsyllabus'}; + my $external=$courseenv{'externalsyllabus'}; + my $uploaded=$courseenv{'uploadedsyllabus'}; + my $minimal=$courseenv{'minimalsyllabus'}; + + if (($minimal =~/\w/) || ($uploaded =~/\w/)) { + my ($item,$is_pdf); + if ($minimal =~/\w/) { + if ($external =~ m{\Q$minimal\E$}) { + undef($external); + } + $item = $minimal; + } elsif ($uploaded =~/\w/) { + if ($external =~ m{\Q$uploaded\E$}) { + undef($external); + } + $item = $uploaded; + if ($item =~ /\.pdf$/i) { + $is_pdf = 1; + } + } + unless ($allowed && $forceedit) { + my $file=&Apache::lonnet::filelocation("",$item); + if ($file =~ /\.(tex|x?html?)$/) { + my $filetype = $1; + my $filecontents=&Apache::lonnet::getfile($file); + if ($filecontents eq -1) { + $r->print(&mt('Syllabus file unavailable')); + } elsif ($filetype eq 'tex') { + if ($target eq 'tex') { + $r->print($filecontents); + } else { + my $result = &Apache::lontexconvert::converted(\$filecontents, + $env{'form.texengine'}); + my %args; + &get_breadcrumbs($cdom,$cnum,$crstype,\%args); + if ($env{'form.only_body'}) { + $args{'only_body'} = 1; + } + if ($env{'request.use_absolute'}) { + $args{'use_absolute'} = $env{'request.use_absolute'}; + } + $r->print(&Apache::loncommon::start_page("Syllabus",undef,\%args). + $result. + &Apache::loncommon::end_page()); + } + } else { + my %mystyle; + unless ($target eq 'tex') { + $target = 'web'; + } + &Apache::structuretags::reset_problem_globals(); + my $oldfile = $env{'request.filename'}; + $env{'request.filename'} = $item; + my $result = &Apache::lonxml::xmlparse($r,$target,$filecontents, + '',%mystyle); + &Apache::structuretags::reset_problem_globals(); + &Apache::lonhomework::finished_parsing(); + $env{'request.filename'} = $oldfile; + &Apache::lonxml::add_messages(\$result); + $r->print($result); + } + } else { + if ($target eq 'tex') { + $r->print(&Apache::lonprintout::print_latex_header($env{'form.latex_type'}). + ' \strut \\\\ \textbf{'.&mt('Syllabus').'} \strut \\\\ '. + &mt('Unsupported file type.').' \strut \\\\ '. + &mt('Print the syllabus directly from your web browser'). + '\end{document}'); + } else { + $r->print(&Apache::lonwrapper::wrapper($item,undef,$env{'request.use_absolute'}, + undef,$is_pdf,&mt('Syllabus'))); + } + } + return OK; + } + } elsif ($external=~/\w/) { + unless ($allowed && $forceedit) { + if ($target eq 'tex') { + $r->print(&Apache::lonprintout::print_latex_header($env{'form.latex_type'}). + ' \strut \\\\ \textbf{'.&mt('Syllabus').'} \strut \\\\ '.$external.' '. + ' \strut \\\\ '.&mt('Print the syllabus directly from your web browser'). + '\end{document}'); + } else { + my $is_ext = 1; + my $is_pdf; + if ($external =~ /\.pdf$/i) { + $is_pdf = 1; + } + $r->print(&Apache::lonwrapper::wrapper($external,undef,$env{'request.use_absolute'}, + $is_ext,$is_pdf,&mt('Syllabus'))); + } + return OK; + } + } + +# ------------------------------------------------------------ Print the screen - if ($externalsyllabus=~/\w/) { - - if ($env{'form.wrapperdisplay'} eq 'menu') { - $r->print(&Apache::lonwrapper::simple_menu()); - } else { - $r->print(&Apache::lonwrapper::wrapper("/public/$cdom/$cnum/syllabus?wrapperdisplay=menu", - $externalsyllabus)); - } - return OK; - } + if ($target eq 'tex') { + $r->print(&Apache::lonprintout::print_latex_header($env{'form.latex_type'})); + } # ------------------------------ The buck stops here: internal syllabus display # --------------------------------------------------------- The syllabus fields @@ -104,246 +213,1453 @@ sub handler { 'jjj_weblinks' => 'Web Links', 'kkk_textbook' => 'Textbook', 'lll_includeurl' => 'URLs To Include in Syllabus'); -# --------------------------------------------------------------- Force Student - my $forcestudent=''; - if ($env{'form.forcestudent'}) { $forcestudent='student'; }; - my $forceedit=''; - if ($env{'form.forceedit'}) { $forceedit='edit'; } - -# ----------------------------------------------------------------- Make header +# ---------------------------------------------------------- Load syllabus info + my %syllabus=&Apache::lonnet::dump('syllabus',$cdom,$cnum); + my ($output,%displayfields,%noshow); + +# This handler might be called anonymously ... +# ----------------------------------------------------- Only if not public call + if ($allowed) { + if (($env{'form.choice'} =~ /^(template|minimal|url|file)$/) || + ($env{'form.phase'} =~ /^(upload|check)_embedded$/)) { + my $earlyout; + ($earlyout,$uploaded,$external,$minimal,$output) = + &save_changes($cnum,$cdom,$uploaded,$external,$minimal, + \%syllabus,\%syllabusfields,\%courseenv); + if (($env{'form.choice'} eq 'minimal') && + ($minimal eq "/uploaded/$cdom/$cnum/portfolio/syllabus/loncapa.html")) { + delete($env{'form.symb'}); + delete($env{'request.symb'}); + $r->internal_redirect("$minimal?editmode=1&forceedit=1"); + return OK; + } + if ($earlyout) { + if ($target ne 'tex') { + &print_header($r,$cnum,$cdom,$crstype,$allowed,$forceedit, + \%syllabus,\%syllabusfields); + $r->print($output. + &Apache::loncommon::end_page()); + } + return OK; + } + } + } if ($target ne 'tex') { - my $start_page = - &Apache::loncommon::start_page("Syllabus", $rss_link, - {'function' => $forcestudent, - 'domain' => $cdom, - 'force_register' => - $env{'form.register'},}); + &print_header($r,$cnum,$cdom,$crstype,$allowed,$forceedit,\%syllabus, + \%syllabusfields); + $r->print($output); + } - $r->print($start_page.'

'.$courseenv{'description'}.'

'. - $Apache::lonnet::domaindescription{$cdom}.'

'); +# -------------------------------------------- Determine which fields are shown + + if ($syllabus{'uploaded.fields'}) { + if ($syllabus{'uploaded.fields'} eq 'none') { + foreach my $field (keys(%syllabusfields)) { + $displayfields{$field} = ' style="display:none;"'; + $noshow{$field} = 1; + } + } else { + my %included; + map { $included{$_} = 1; } split(/,/,$syllabus{'uploaded.fields'}); + foreach my $field (keys(%syllabusfields)) { + my ($prefix) = split(/_/,$field); + if ($included{$prefix}) { + $displayfields{$field} = ' style="display:block;"'; + } else { + $displayfields{$field} = ' style="display:none;"'; + $noshow{$field} = 1; + } + } + } + } else { + foreach my $field (keys(%syllabusfields)) { + if ($syllabus{$field} ne '') { + $displayfields{$field} = ' style="display:block;"'; + } else { + $displayfields{$field} = ' style="display:none;"'; + } + } + } + + if ($allowed) { +#---------------------------------- Print External URL Syllabus Info if editing + if ($target ne 'tex') { + my $protocol = $Apache::lonnet::protocol{$homeserver}; + $protocol = 'http' if ($protocol ne 'https'); + my $link = $protocol.'://'.&Apache::lonnet::hostname($homeserver).$r->uri; + $r->print('
' + .'' + .'' + .&mt('Public link (no log-in): [_1]',''.$link.'') + .' '.&Apache::loncommon::help_open_topic('Syllabus_ExtLink') + .'' + .'
'."\n"); + my $lonhost = $r->dir_config('lonHostID'); + $r->print(&chooser($external,$uploaded,$minimal,$cdom,$cnum,$lonhost, + \%syllabusfields,\%syllabus)); + } + } else { +#--------------------------------------------- Print last update unless editing + my $lastmod=$syllabus{'uploaded.lastmodified'}; + $lastmod=($lastmod?&Apache::lonlocal::locallocaltime($lastmod):&mt('never')); + my $who; + if ($syllabus{'uploaded.lastmodified'}) { + if (($env{'user.name'} ne 'public') && ($env{'user.domain'} ne 'public')) { + $who = &Apache::loncommon::aboutmewrapper( + &Apache::loncommon::plainname($syllabus{'uploaded.name'}, + $syllabus{'uploaded.domain'}),$syllabus{'uploaded.name'}, + $syllabus{'uploaded.domain'}); + } else { +# Public user? +# Only display name of user, but no link to personal information page + $who = &Apache::loncommon::plainname( + $syllabus{'uploaded.name'}, + $syllabus{'uploaded.domain'}); + } + } + if ($target ne 'tex') { + $r->print('
'.&mt('Last updated').': '. + $lastmod . ' '. + ($who ? &mt('by').' '.$who + : '' ) . + '
' ); + } else { + $r->print('\\\\ '.&mt('Last updated').': '.$lastmod.' '. + ($who? &mt('by').'\\\\ '. + &Apache::loncommon::plainname($syllabus{'uploaded.name'},$syllabus{'uploaded.domain'}) + :'') + .'\\\\'); + } + } + +#-------------------------------------------------------------- Print Headtitle + if ($target ne 'tex') { + my $display = 'block'; + if ($external || $uploaded || $minimal) { + $display = 'none'; + } + $r->print('
'. + '

'.$courseenv{'description'}.'

'); + if ($allowed) { + $r->print('
'. + '

'.&Apache::lonnet::domain($cdom,'description').'

'. + '
'); +# Print Help Text if editing at right side of screen + $r->print('
'. + &Apache::loncommon::help_open_topic('Uploaded_Templates_TextBoxes',&mt('Help with filling in text boxes')). + '

'); + } else { + $r->print('

'.&Apache::lonnet::domain($cdom,'description').'

'); + } + } else { + $r->print('\noindent{\large\textbf{'.$courseenv{'description'}.'}}\\\\\\\\\textbf{'. + &Apache::lonnet::domain($cdom,'description').'}\\\\'); + } +# -------------------------------------------------------- Get course personnel + my $hidepersonnel; + if (($syllabus{'uploaded.fields'}) && + (($syllabus{'uploaded.fields'} eq 'none') || + ($syllabus{'uploaded.fields'} !~ /000/))) { + $hidepersonnel = 1; + } + if ($target ne 'tex') { + if ($allowed) { + my $display = ' style="display:block;"'; + if ($hidepersonnel) { + $display = ' style="display:none;"'; + } + &Apache::lontemplate::print_start_template($r,&mt('Personnel'),'LC_Box', + 'box_000_showpeople',$display); + $r->print(&get_personnel($r,$target,$cdom,$cnum,$allowed,$crstype,\%syllabus)); + &Apache::lontemplate::print_end_template($r); + } else { + unless ($hidepersonnel) { + &Apache::lontemplate::print_start_template($r,&mt('Personnel'),'LC_Box'); + $r->print(&get_personnel($r,$target,$cdom,$cnum,$allowed,$crstype,\%syllabus)); + &Apache::lontemplate::print_end_template($r); + } + } } else { - $r->print('\noindent{\large\textbf{'.$courseenv{'description'}.'}}\\\\\\\\\textbf{'. - $Apache::lonnet::domaindescription{$cdom}.'}\\\\'); + unless ($hidepersonnel) { + $r->print(&get_personnel($r,$target,$cdom,$cnum,$allowed,$crstype,%syllabus)); + } } # -------------------------------------------------------------- Announcements? my $day = &Apache::lonannounce::showday(time,2, - &Apache::lonannounce::readcalendar($cdom.'_'.$cnum)); + &Apache::lonannounce::readcalendar($cdom.'_'.$cnum)); + my $hidefeeds; + if (($syllabus{'uploaded.fields'}) && + (($syllabus{'uploaded.fields'} eq 'none') || + ($syllabus{'uploaded.fields'} !~ /111/))) { + $hidefeeds = 1; + } if ($target ne 'tex') { - $r->print($day. &Apache::lonrss::advertisefeeds($cnum,$cdom,$forceedit)); + if ($allowed) { + my $display = ' style="display:block;"'; + if ($hidefeeds) { + $display = ' style="display:none;"'; + } + &Apache::lontemplate::print_start_template($r,&mt('RSS Feeds and Blogs'),'LC_Box', + 'box_111_showrssfeeds',$display); + my ($numfeeds,$hiddenfeeds,$rsslinktext); + my $feeds=&Apache::lonrss::advertisefeeds($cnum,$cdom,$forceedit,\$numfeeds, + \$hiddenfeeds); + if ($numfeeds) { + $r->print($feeds); + $rsslinktext = &mt('New RSS Feed or Blog'); + } else { + my $msg = '
'. + &mt("RSS Feeds and Blogs item is not included in a student's view of the syllabus."); + if ($hiddenfeeds) { + $r->print('

'. + &mt('All feeds currently hidden'). + $msg. + '

'); + } else { + $r->print('

'. + &mt('No current feeds'). + $msg. + '

'); + } + $rsslinktext = &mt('Manage Course RSS Feeds/Blogs'); + if ($crstype eq 'Community') { + $rsslinktext = &mt('Manage Community RSS Feeds/Blogs'); + } + } + my $editurl= &Apache::lonnet::absolute_url().'/adm/'.$cdom.'/'.$cnum.'/_rss.html'; + $r->print( ''.$rsslinktext.''); + &Apache::lontemplate::print_end_template($r); + } else { + unless ($hidefeeds) { + my $feeds = &Apache::lonrss::advertisefeeds($cnum,$cdom,$forceedit); + if ($feeds ne '') { + &Apache::lontemplate::print_start_template($r,&mt('RSS Feeds and Blogs'),'LC_Box'); + $r->print($feeds); + &Apache::lontemplate::print_end_template($r); + } + } + } } else { - $r->print(&Apache::lonxml::xmlparse($r,'tex',$day)); + $r->print(&Apache::lonxml::xmlparse($r,'tex',$day)); } +# ---------------------------------------------------------------- Get syllabus + if (($syllabus{'uploaded.lastmodified'}) || ($allowed)) { + my $url_include_handler = sub { + my ($r, $field, $message, $group, $data_ref, $fields_ref, $target, $allowed, $display) = @_; + my %data = %{$data_ref}; + my %fields = %{$fields_ref}; + my $urls=$message; + $message=''; + foreach my $filelink (split(/\n/,$urls)) { + my $output=''; + # embed style? + my ($curfext)=($filelink=~/\.([^\.]+)$/); + my $embstyle=&Apache::loncommon::fileembstyle($curfext); + if (($embstyle eq 'ssi') || ($curfext=~/\/$/)) {# make ssi call and remove everything but the body contents + $output=&Apache::lonnet::ssi_body($filelink); + } elsif ($embstyle eq 'img') {# embed as an image + $output=''; + } + if ($output ne '') { + if ($target ne 'tex') { + $message.='

'.$output.'

'; + } else { + $message.=' '.&Apache::lonxml::xmlparse($r,'tex','

'.$output.'

').' '; + } + } + } + if ($allowed) { + &Apache::lonfeedback::newline_to_br(\$urls); + &Apache::lontemplate::print_start_template($r,$fields{$field}. + &Apache::loncommon::help_open_topic('Syllabus_URLs'),'LC_Box', + 'box_'.$field,$display); + $r->print($urls); + $r->print("
"); + &Apache::lontemplate::print_textarea_template($r, $data{$field}, + $field, Apache::lontemplate->RICH_TEXT_ALWAYS_OFF); + &Apache::lontemplate::print_saveall_template($r); + $r->print("
"); + &Apache::lontemplate::print_end_template($r); -# -------------------------------------------------------- Get course personnel - my %coursepersonnel=&Apache::lonnet::get_course_adv_roles($cdom.'/'.$cnum); + } else { + $r->print($message); + } + }; + my %custom_hash = ( 'lll_includeurl' => $url_include_handler ); + &Apache::lontemplate::print_template_fields($r, \%syllabus, \%syllabusfields, + $target, $allowed, Apache::lontemplate->RICH_TEXT_DETECT_HTML, \%custom_hash, + undef,\%displayfields,\%noshow); + if ($allowed) { + $r->print('
'. + &Apache::lonhtmlcommon::htmlareaselectactive()); + } + } else { + if ($target ne 'tex') {$r->print('

');} else {$r->print('\par ');} + $r->print(&mt('No syllabus information provided.')); + if ($target ne 'tex') {$r->print('

');} + } if ($target ne 'tex') { - $r->print(''); + if ($env{'form.backto'} eq 'coursecatalog') { + $r->print(''. + &Apache::lonhtmlcommon::echo_form_input(['backto','courseid']). + ''); + } + $r->print(&Apache::loncommon::end_page()); + } else { + $r->print('\end{document}'); + } + return OK; +} + +sub print_header { + my ($r,$cnum,$cdom,$crstype,$allowed,$forceedit,$syllabus,$syllabusfields) = @_; + return unless ((ref($syllabus) eq 'HASH') || (ref($syllabusfields) eq 'HASH')); +# ----------------------------------------------------------------- Make header + my $rss_link = &Apache::lonrss::rss_link($cnum,$cdom); + my $js; + if ($env{'form.backto'} eq 'coursecatalog') { + $js .= <<"ENDSCRIPT"; + + + +ENDSCRIPT + } + if ($allowed && $forceedit) { + my $check_uncheck = &Apache::loncommon::check_uncheck_jscript(); + my @fieldnames = sort(keys(%{$syllabusfields})); + unshift(@fieldnames,'000_showpeople','111_showrssfeeds'); + my (@checked,@unchecked); + if ($syllabus->{'uploaded.fields'} eq 'none') { + my $lastidx = scalar(@fieldnames)-1; + @unchecked = (0..$lastidx); + } elsif ($syllabus->{'uploaded.fields'}) { + my %included; + map { $included{$_} = 1; } split(/,/,$syllabus->{'uploaded.fields'}); + for (my $i=0; $i<@fieldnames; $i++) { + my ($prefix) = split(/_/,$fieldnames[$i]); + if ($included{$prefix}) { + push(@checked,$i); + } else { + push(@unchecked,$i); + } + } + } else { + @checked = (0,1); + for (my $i=2; $i<@fieldnames; $i++) { + if ($syllabus->{$fieldnames[$i]}) { + push(@checked,$i); + } else { + push(@unchecked,$i); + } + } + } + my $fieldstr = "var fields = new Array('".join("','",@fieldnames)."');"; + my $checkedstr = "var include = new Array('".join("','",@checked)."');"; + my $uncheckedstr = "var exclude = new Array('".join("','",@unchecked)."');"; + my $invurl = &mt('Invalid URL'); + &js_escape(\$invurl); + my $urlregexp = <<'ENDREGEXP'; +/^([a-z]([a-z]|\d|\+|-|\.)*):(\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?((\[(|(v[\da-f]{1,}\.(([a-z]|\d|-|\.|_|~)|[!\$&'\(\)\*\+,;=]|:)+))\])|((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=])*)(:\d*)?)(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*|(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)|((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)){0})(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i +ENDREGEXP + + $js .= <<"ENDSCRIPT"; + + + +ENDSCRIPT + } + my $args = {'function' => undef, + 'domain' => $cdom}; + my $forcereg; + if ($env{'form.register'}) { + $forcereg = 1; + $args->{'force_register'} = $forcereg; + } + if ($env{'form.backto'} eq 'coursecatalog') { + &Apache::lonhtmlcommon::clear_breadcrumbs(); + my $brcrum = [{href=>"javascript:ToCatalog();", + text=>&mt('Course/Community Catalog'), + no_mt=>1} + ]; + if ($env{'form.coursenum'} ne '') { + push(@{$brcrum}, + {href=>"javascript:ToCatalog('details')", + text=>"Course details"}); + } + push(@{$brcrum}, + {href=>$r->uri, + text=>"Course syllabus"}); + $args->{'bread_crumbs'} = $brcrum; + } else { + &get_breadcrumbs($cdom,$cnum,$crstype,$args); + } + if ($allowed) { + my %loaditem = ( + onload => 'setTemplateBoxes();', + ); + $args->{'add_entries'} = \%loaditem; + } else { + if ($env{'request.use_absolute'}) { + $args->{'use_absolute'} = $env{'request.use_absolute'}; + } + } + if ($env{'form.only_body'}) { + $args->{'only_body'} = 1; + } + my $start_page = + &Apache::loncommon::start_page("Syllabus", $rss_link.$js,$args); + if ($start_page) { + $r->print($start_page); + } +} + +sub get_breadcrumbs{ + my ($cdom,$cnum,$crstype,$args) = @_; + return unless (ref($args) eq 'HASH'); + if ($env{'form.folderpath'} =~ /^supplemental/) { + my $title = $env{'form.title'}; + if ($title eq '') { + $title = &mt('Syllabus'); + } + my $brcrum = + &Apache::lonhtmlcommon::docs_breadcrumbs(undef,$crstype,undef,$title,1); + if (ref($brcrum) eq 'ARRAY') { + $args->{'bread_crumbs'} = $brcrum; + } + } else { + if ((&Apache::lonnet::is_on_map("public/$cdom/$cnum/syllabus")) + && (($env{'form.symb'}) || ($env{'form.register'}))) { + &Apache::lonhtmlcommon::clear_breadcrumbs(); + } else { + $args->{'bread_crumbs'} = [ + {'href' => "/public/$cdom/$cnum/syllabus", + 'text' => 'Syllabus'}, + ]; + } + } + return; +} + +sub chooser { + my ($external,$uploaded,$minimal,$cdom,$cnum,$lonhost,$fields,$values) = @_; + my %lt = &Apache::lonlocal::texthash( + 'type' => 'Syllabus Type', + 'url' => 'External URL', + 'file' => 'Uploaded file', + 'minimal' => 'Minimal template', + 'template' => 'Standard template', + 'templateboxes' => 'Choose template items ... ', + 'curr' => 'Current:', + 'rep' => 'Replace:', + 'upl' => 'Upload:', + 'pr' => 'Preview', + 'save' => 'Save', + 'sved' => 'Save and Edit', + 'chourl' => 'External URL', + 'chofile' => 'Uploaded syllabus file', + 'parse' => 'Upload embedded images/multimedia files if HTML file', + ); + my %checked = ( + file => '', + minimal => '', + url => '', + template => '', + ); + my %display = ( + file => 'none', + minimal => 'none', + url => 'none', + templatebox => 'none', + ); + my $check = ' checked="checked" '; + if ($uploaded) { + $checked{'file'} = $check; + $display{'file'} = 'block'; + } elsif ($external) { + $checked{'url'} = $check; + $display{'url'} = 'block'; + } elsif ($minimal) { + $checked{'minimal'} = $check; + $display{'minimal'} = 'block'; + } else { + $checked{'template'} = $check; + $checked{'templatebox'} = $check; + $display{'templatebox'} = 'block'; + } + + my $output = + ''."\n". + ''."\n". + '
'.$lt{'type'}.''; + foreach my $item ('minimal','template','url','file') { + $output .= '
'; + } + $output .= '
'."\n". + '
'."\n". + '
'.$lt{'chourl'}.''."\n". + ''.$lt{'pr'}.' '."\n". + ''."\n". + ' '."\n". + '
'."\n". + '
'."\n". + '
'.$lt{'minimal'}.''; + if ($minimal) { + my ($absurl,$filename,$depbutton) = &syllabus_file_info($minimal,$cnum,$cdom,$lonhost,'minimal'); + $output .= ''.$lt{'pr'}.''. + ''. + $depbutton; + } else { + $output .= &mt('Title of Syllabus Page:').' '. + ''."\n". + ' '."\n"; + } + $output .= '
'."\n". + '
'."\n". + '
'.$lt{'file'}.''; + if ($uploaded) { + my ($absurl,$filename,$depbutton) = &syllabus_file_info($uploaded,$cnum,$cdom,$lonhost,'file'); + $output .= ''.$lt{'curr'}.' '. + ''. + ''.$filename.''.$depbutton. + '

'.$lt{'rep'}; + } else { + $output .= $lt{'upl'}; + } + $output .= '
'."\n". + ''. + ''."\n". + ' '. + '
'. + ''. + '
'. + '
'.$lt{'templateboxes'}. + ' '. + (' 'x2). + ''. + ''. + &fields_check_uncheck($fields,$values). + '

'. + ''. + '
'; + $output .= '
'; + return $output; +} + +sub syllabus_file_info { + my ($item,$cnum,$cdom,$lonhost,$context) = @_; + my $protocol = $Apache::lonnet::protocol{$lonhost}; + $protocol = 'http' if ($protocol ne 'https'); + my $absurl = $protocol.'://'.&Apache::lonnet::hostname($lonhost).$item; + my ($filename) = ($item =~ m{([^/]+)$}); + my $file=&Apache::lonnet::filelocation("",$item); + my ($depbutton,$filetype,$editable); + if ($file =~ /\.(xhtml|xml|tex|html|htm)$/) { + $filetype=$1; + } + if ($filetype) { + unless ($filetype eq 'tex') { + $filetype='html'; + } + } + if ($filetype eq 'html') { + my $filecontents=&Apache::lonnet::getfile($file); + unless ($filecontents eq -1) { + my $mm = new File::MMagic; + my $mimetype = $mm->checktype_contents($filecontents); + if ($mimetype eq 'text/html') { + my (%codebase,%allfiles); + my $parse_result = &Apache::lonnet::extract_embedded_items($item,\%allfiles, + \%codebase,\$filecontents); + my $actionurl = "/public/$cdom/$cnum/syllabus"; + my ($ignore,$num,$numpathchanges,$existing,$mapping) = + &Apache::loncommon::ask_for_embedded_content($actionurl,undef,\%allfiles, + \%codebase, + {'context' => 'rewrites', + 'ignore_remote_references' => 1,}); + $editable = 1; + } + } + } + $depbutton = (' ' x 3). + &editfile_button($item,$context,$editable). + &editbutton_js(); + return ($absurl,$filename,$depbutton); +} + +sub fields_check_uncheck { + my ($fields,$values) = @_; + return unless ((ref($fields) eq 'HASH') && (ref($values) eq 'HASH')); + my $numinrow = 4; + my $table; + my @fieldnames = sort(keys(%{$fields})); + unshift(@fieldnames,'000_showpeople','111_showrssfeeds'); + my $numfields = scalar(@fieldnames); + my %included; + if (($values->{'uploaded.fields'}) && ($values->{'uploaded.fields'} ne 'none')) { + map { $included{$_} = 1; } split(/,/,$values->{'uploaded.fields'}); + } + for (my $i=0; $i<$numfields; $i++) { + my ($name,$checked); + if ($fieldnames[$i] eq '000_showpeople') { + $name = &mt('Personnel'); + } elsif ($fieldnames[$i] eq '111_showrssfeeds') { + $name = &mt('RSS Feeds and Blogs'); + } else { + $name = $fields->{$fieldnames[$i]}; + } + if ($values->{'uploaded.fields'}) { + unless ($values->{'uploaded.fields'} eq 'none') { + my ($prefix) = split(/_/,$fieldnames[$i]); + if ($included{$prefix}) { + $checked = ' checked="checked"'; + } + } + } else { + if ($fieldnames[$i] eq '000_showpeople') { + $checked = ' checked="checked"'; + } elsif ($fieldnames[$i] eq '111_showrssfeeds') { + $checked = ' checked="checked"'; + } else { + if ($values->{$fieldnames[$i]} ne '') { + $checked = ' checked="checked"'; + } + } + } + my $rem = $i%($numinrow); + if ($rem == 0) { + if (($i > 0) && ($i < $numfields)) { + $table .= ''; + } + if ($i < $numfields) { + $table .= ''; + } + } + if ($i == $numfields-1) { + my $rem = $numfields%($numinrow); + my $colsleft = $numinrow - $rem; + if ($colsleft > 1) { + $table .= ''; + } + } else { + $table .= ''."\n"; + } + if ($table ne '') { + my $rem = $numfields%($numinrow); + my $colsleft = $numinrow - $rem; + if ($colsleft > 1 ) { + $table .= ''; + } elsif ($colsleft == 1) { + $table .= ''; + } + $table = '
'; + } else { + $table .= ''; + } + $table .= + '  
'.$table.'
'; + } + return $table; +} + +sub get_personnel { + my ($r,$target,$cdom,$cnum,$allowed,$crstype,$syllabus) = @_; + my (%hiddenroles,%hiddenusers); + if (ref($syllabus) eq 'HASH') { + if (ref($syllabus->{'personnel'}) eq 'HASH') { + if ($syllabus->{'personnel'}{'hiderole'}) { + map { $hiddenroles{$_} = 1; } split(/,/,$syllabus->{'personnel'}{'hiderole'}); + } + if ($syllabus->{'personnel'}{'hideuser'}) { + map { $hiddenusers{$_} = 1; } split(/,/,$syllabus->{'personnel'}{'hideuser'}); + } + } + } + my $output; + my %coursepersonnel=&Apache::lonnet::get_course_adv_roles($cdom.'/'.$cnum,1); + if ($target ne 'tex') { + if ($allowed) { + $r->print(&Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(). + ''.&mt('Role hidden?').''.&mt('Role').''. + ''.&mt('Personnel (hidden if checked)').''. + &Apache::loncommon::end_data_table_header_row()); + } else { + $r->print(&Apache::lonhtmlcommon::start_pick_box()); + } + } else { + $r->print('\begin{tabular}{|p{0.45\textwidth}|p{0.45\textwidth}|}\hline'); + } + my @personnel=sort(keys(%coursepersonnel)); + my $lastpers=$personnel[$#personnel]; + foreach my $element (@personnel) { + unless ($allowed) { + next if ($hiddenroles{$element}) + } + my ($role,$sec); + if ($element =~ /:/) { + ($role,$sec) = split(/:/,$element); + } else { + $role = $element; + } + my $roletext = &Apache::lonnet::plaintext($role,$crstype); + if ($sec) { + $roletext .=' ('.&Apache::lonlocal::mt('Section [_1]',$sec).')'; + } + if ($target ne 'tex') { + if ($allowed) { + my $checked; + if ($hiddenroles{$element}) { + $checked = ' checked="checked"'; + } + $r->print(&Apache::loncommon::start_data_table_row(). + ''. + ''. + ''.$roletext.''); + } else { + $r->print(&Apache::lonhtmlcommon::row_title($roletext)); + } + } else { + $r->print(' '.&Apache::lonxml::xmlparse($r,'tex',$roletext).' & '); + } + my @coursepersonlist; + foreach my $user (split(/\,/,$coursepersonnel{$element})) { + my ($puname,$pudom)=split(/\:/,$user); + if ($target ne 'tex') { + my $courseperson = &Apache::loncommon::plainname($puname,$pudom); + my $checked; + if ($hiddenusers{$element.'&'.$puname.':'.$pudom}) { + $checked = ' checked="checked"'; + } + if ($allowed) { + my $item = ''.(' 'x2).' '; + push(@coursepersonlist,$item); + + } else { + next if ($hiddenusers{$element.'&'.$puname.':'.$pudom}); + if (($env{'user.name'} eq '') || ($env{'user.name'} eq 'public') || + ($env{'user.domain'} eq '') || ($env{'user.domain'} eq 'public')) { + push(@coursepersonlist,$courseperson); + } else { + push(@coursepersonlist,&Apache::loncommon::aboutmewrapper($courseperson, + $puname,$pudom)); + } + } + } else { + push(@coursepersonlist,&Apache::loncommon::plainname($puname, $pudom).' '); - } - } - if ($target ne 'tex') { - $r->print(''); - } else { - $r->print('\\\\ \hline'); - } + } + } + if ($allowed) { + $r->print(join('',@coursepersonlist)); + } else { + $r->print(join(', ',@coursepersonlist)); + } + if ($target ne 'tex') { + if ($allowed) { + $r->print(''.&Apache::loncommon::end_data_table_row()); + } else { + my $lastclose=$element eq $lastpers?1:0; + $r->print(&Apache::lonhtmlcommon::row_closure($lastclose)); + } + } else { + $r->print('\\\\ \hline'); + } } if ($target ne 'tex') { - $r->print(''); + if ($allowed) { + $r->print(&Apache::loncommon::end_data_table()); + } else { + $r->print(&Apache::lonhtmlcommon::end_pick_box()); + } } else { - $r->print('\end{tabular}\\\\'); + $r->print('\end{tabular}\\\\'); } -# ---------------------------------------------------------- Load syllabus info - my %syllabus=&Apache::lonnet::dump('syllabus',$cdom,$cnum); - my $allowed=0; - my $privileged=0; + return; +} -# This handler might be called anonymously ... -# ----------------------------------------------------- Only if not public call - if ($env{'user.environment'}) { -# does this user have privileges to post, etc? - if ($env{'request.course.id'} - && $cdom eq $env{'course.'.$env{'request.course.id'}.'.domain'} - && $cnum eq $env{'course.'.$env{'request.course.id'}.'.num'}) { - $allowed=&Apache::lonnet::allowed('mdc',$env{'request.course.id'}); - $privileged=$allowed; - if (($syllabus{'uploaded.lastmodified'}) && (!$forceedit)) { - $forcestudent='student'; - } - if ($forcestudent or $target eq 'tex') { $allowed=0; } - } - if ($allowed) { - $r->print('

'. -&Apache::loncommon::help_open_topic('Uploaded_Templates_TextBoxes','Help with filling in text boxes').'

'.&mt('This syllabus can be publicly viewed at') - .' http://'. - $Apache::lonnet::hostname{$homeserver}.$r->uri.''. - &Apache::loncommon::help_open_topic('Syllabus_ExtLink').'

'. - '

'.&mt('You can specify an external URL as Syllabus in the [_1].',''.&mt('Course Parameters').'').'

'. - '

'. -&mt('Show Public View').''. - &Apache::loncommon::help_open_topic('Uploaded_Templates_PublicView'). - '

'); - } elsif ($privileged) { - if ($target ne 'tex') { - $r->print('

'. - &mt('Edit').''); - } - } - if (($allowed) && ($env{'form.storesyl'})) { - foreach my $syl_field (keys(%syllabusfields)) { - my $field=$env{'form.'.$syl_field}; - chomp($field); - $field=~s/\s+$//s; - $field=~s/^\s+//s; - $field=~s/\$//s; - $field=&Apache::lonfeedback::clear_out_html($field,1); - $syllabus{$syl_field}=$field; - if ($syl_field eq 'lll_includeurl') { # clean up included URLs - my $field=''; - foreach my $value (split(/\n/,$syllabus{$syl_field})) { - my $url=$value; +sub save_changes { + my ($cnum,$cdom,$uploaded,$external,$minimal,$syllabus,$syllabusfields,$courseenv) = @_; + my ($earlyout,$output); + unless ((ref($syllabus) eq 'HASH') && (ref($syllabusfields) eq 'HASH') || + (ref($courseenv) eq 'HASH')) { + return ($earlyout,$uploaded,$external,$minimal,$output); + } + if (($env{'form.deleteuploaded_file'}) || ($env{'form.deleteuploaded_minimal'})) { + my %storehash; + if (($env{'form.choice'} eq 'file') && + ($env{'form.deleteuploaded_file'}) && ($uploaded =~ /\w/)) { + if ($courseenv->{'uploadedsyllabus'} =~ m{^\Q/uploaded/$cdom/$cnum/portfolio\E(/syllabus/.+)$}) { + my $filename = $1; + &update_access_permissions($cdom,$cnum,$filename); + } + &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.uploadedsyllabus'); + &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.externalsyllabus'); + $storehash{'uploadedsyllabus'} = ''; + $storehash{'externalsyllabus'} = ''; + my $putres = &Apache::lonnet::put('environment',\%storehash,$cdom,$cnum); + undef($uploaded); + undef($external); + } elsif (($env{'form.choice'} eq 'minimal') && + ($env{'form.deleteuploaded_minimal'}) && ($minimal =~ /\w/)) { + my $minimalurl = "/uploaded/$cdom/$cnum/portfolio/syllabus/loncapa.html"; + if ($courseenv->{'minimalsyllabus'} eq "$minimalurl") { + my $filecontents=&Apache::lonnet::getfile(&Apache::lonnet::filelocation("",$minimalurl)); + unless ($filecontents eq -1) { + $env{'form.output'} = $filecontents; + &Apache::lonnet::finishuserfileupload($cnum,$cdom,'output', + 'portfolio/syllabus/loncapa.html.bak'); + $minimalurl = &default_minimal_syllabus($cnum,$cdom); + } + } + &update_access_permissions($cdom,$cnum,'/syllabus/loncapa.html'); + &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.externalsyllabus'); + &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.minimalsyllabus'); + $storehash{'externalsyllabus'} = ''; + $storehash{'minimalsyllabus'} = ''; + my $putres = &Apache::lonnet::put('environment',\%storehash,$cdom,$cnum); + undef($external); + undef($minimal); + } + } elsif ($env{'form.choice'} eq 'template') { +#store what the user typed in to the template + my @shown = &Apache::loncommon::get_env_multiple('form.showfield'); + $syllabus->{'uploaded.fields'} = ''; + if (@shown == 0) { + $syllabus->{'uploaded.fields'} = 'none'; + } else { + foreach my $field (sort(@shown)) { + if (($field eq '000_showpeople') || + ($field eq '111_showrssfeeds') || + ($syllabusfields->{$field})) { + my ($prefix) = split(/_/,$field); + $syllabus->{'uploaded.fields'} .= $prefix.','; + } + if ($field eq '000_showpeople') { + my @hideusers = &Apache::loncommon::get_env_multiple('form.hideuser'); + my @hideroles = &Apache::loncommon::get_env_multiple('form.hiderole'); + my %coursepersonnel=&Apache::lonnet::get_course_adv_roles($cdom.'/'.$cnum,1); + my %personnel; + foreach my $key (keys(%coursepersonnel)) { + map { $personnel{$key}{$_} = 1; } split(/,/,$coursepersonnel{$key}); + } + %{$syllabus->{'personnel'}} = (); + $syllabus->{'personnel'}{'hideuser'} = ''; + $syllabus->{'personnel'}{'hiderole'} = ''; + foreach my $role (@hideroles) { + if (exists($personnel{$role})) { + $syllabus->{'personnel'}{'hiderole'} .= $role.','; + } + } + foreach my $item (@hideusers) { + my ($role,$user) = split(/\&/,$item); + if (ref($personnel{$role}) eq 'HASH') { + if ($personnel{$role}{$user}) { + $syllabus->{'personnel'}{'hideuser'} .= $item.','; + } + } + } + $syllabus->{'personnel'}{'hideuser'} =~ s/,$//; + $syllabus->{'personnel'}{'hiderole'} =~ s/,$//; + } + } + $syllabus->{'uploaded.fields'} =~ s/,$//; + } + foreach my $syl_field (keys(%{$syllabusfields})) { + my $field=$env{'form.'.$syl_field}; + chomp($field); + my $gateway = Apache::lonhtmlgateway->new(); + $field = $gateway->process_incoming_html($field,1); + #here it will be stored + $syllabus->{$syl_field}=$field; + if ($syl_field eq 'lll_includeurl') { # clean up included URLs + my $field=''; + foreach my $value (split(/\n/,$syllabus->{$syl_field})) { + my $url=$value; # get rid of leading and trailing spaces - $url=~s/^\s+//; - $url=~s/\s+$//; - if ($url=~m|^http://([^/]+)/(.+)$|) { - my $host = $1; - my $remainder=$2; + $url=~s/^\s+//; + $url=~s/\s+$//; + if ($url=~m|^https?\://([^/]+)/(.+)$|) { + my $host = $1; + my $remainder=$2; # remove the hostname from internal URLs - foreach my $possible_host (keys(%Apache::lonnet::hostname)) { - if ($possible_host =~ - /\Q$Apache::lonnet::hostname{$host}\E/i) { - $url=$remainder; - } - } - } + my $hostname = &Apache::lonnet::hostname($host); + my %all_hostnames = &Apache::lonnet::all_hostnames(); + foreach my $possible_host (keys(%all_hostnames)) { + if ($possible_host =~ /\Q$hostname\E/i) { + $url=$remainder; + } + } + } # norm internal URLs - unless ($url=~/^http\:/) { - $url=&Apache::lonnet::clutter($url); - } + unless ($url=~/^https?\:/) { + $url=&Apache::lonnet::clutter($url); + } # re-assemble field - if ($url) { - $field.=$url."\n"; - } - } - $syllabus{$syl_field}=$field; - } - } - $syllabus{'uploaded.domain'}=$env{'user.domain'}; - $syllabus{'uploaded.name'}=$env{'user.name'}; - $syllabus{'uploaded.lastmodified'}=time; - &Apache::lonnet::put('syllabus',\%syllabus,$cdom,$cnum); - } + if ($url) { + $field.=$url."\n"; + } + } + $syllabus->{$syl_field}=$field; + } + } + my $now = time; + $syllabus->{'uploaded.domain'}=$env{'user.domain'}; + $syllabus->{'uploaded.name'}=$env{'user.name'}; + $syllabus->{'uploaded.lastmodified'} = $now; + my $putres = &Apache::lonnet::put('syllabus',$syllabus,$cdom,$cnum); + if ($putres eq 'ok') { + ($uploaded,$minimal,$external) = + &update_syllabus_env($cdom,$cnum,$courseenv,$env{'form.choice'},$uploaded, + $minimal,$external); + $output = '

'. + &Apache::lonhtmlcommon::confirm_success(&mt('Template saved.')). + '
'; + } else { + $output = '
'. + &mt('An error occurred storing the template: [_1]',$putres). + '
'; + } + } elsif ($env{'form.choice'} eq 'url') { + if ($env{'form.externalsyllabus'} =~ m{^https?://}) { + if ($env{'form.externalsyllabus'} eq $external) { + $output = '
'. + &mt('External URL unchanged.'). + '
'; + ($uploaded,$minimal,$external) = + &update_syllabus_env($cdom,$cnum,$courseenv,$env{'form.choice'},$uploaded, + $minimal,$external); + } else { + $external=$env{'form.externalsyllabus'}; + $external =~ s/(`)//g; + my $putres = + &Apache::lonnet::put('environment',{externalsyllabus=>$external}, + $cdom,$cnum); + if ($putres eq 'ok') { + &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.externalsyllabus' => $external}); + $output = '
'. + &Apache::lonhtmlcommon::confirm_success(&mt('External URL saved.')). + '
'; + ($uploaded,$minimal,$external) = + &update_syllabus_env($cdom,$cnum,$courseenv,$env{'form.choice'},$uploaded, + $minimal,$external); + } else { + $output = '
'. + &mt('An error occurred storing the external URL: [_1]',$putres). + '
'; + } + } + } else { + $output = '
'. + &mt('External URL not saved -- invalid URL.'). + '
'; + } + } elsif (($env{'form.choice'} eq 'file') || ($env{'form.choice'} eq 'minimal')) { + # Process file upload - phase one - upload and parse primary file. + my ($upload_result,$uploadphase,$url,$needlink,$error,$errormsg); + if ($env{'form.choice'} eq 'file') { + if ($env{'form.syllabusfile.filename'}) { + my %allfiles = (); + my %codebase = (); + ($url,$needlink) = &process_upload(\$output,$cnum,$cdom, + \%allfiles,\%codebase); + } else { + $output = '
'. + &mt('No file uploaded'). + '
'; + } + } elsif ($env{'form.choice'} eq 'minimal') { + $url = "/uploaded/$cdom/$cnum/portfolio/syllabus/loncapa.html"; + my $filecontents=&Apache::lonnet::getfile(&Apache::lonnet::filelocation("",$url)); + if ($filecontents eq -1) { + $url = &default_minimal_syllabus($cnum,$cdom); + } + } + if ($url =~ m{^/uploaded/\Q$cdom\E/\Q$cnum\E.*/[^/]+$}) { + my $exturl = &home_http_host($cdom,$cnum); + if ($exturl) { + $exturl .= $url; + } + my %storehash; + if ($env{'form.choice'} eq 'minimal') { + $storehash{'minimalsyllabus'} = $url; + } else { + $storehash{'uploadedsyllabus'} = $url; + } + if ($exturl) { + $storehash{'externalsyllabus'} = $exturl; + if ($exturl =~ /\.(html?|txt|js|css)$/) { + $exturl .= '?inhibitmenu=yes'; + } + } else { + $storehash{'externalsyllabus'} = '', + } + my $putres = + &Apache::lonnet::put('environment',\%storehash,$cdom,$cnum); + if ($putres eq 'ok') { + &Apache::lonnet::make_public_indefinitely($url); + foreach my $key (keys(%storehash)) { + &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.'.$key => $storehash{$key}}); + } + if ($env{'form.choice'} eq 'minimal') { + $minimal = $url; + } else { + $uploaded = $url; + } + if ($needlink) { + $output .= &return_to_editor($cdom,$cnum); + $earlyout = 1; + } + ($uploaded,$minimal,$external) = + &update_syllabus_env($cdom,$cnum,$courseenv,$env{'form.choice'},$uploaded, + $minimal,$external); + } else { + $error = 1; + $errormsg = $putres; + } + } else { + $error = 1; + } + if ($error) { + $output = '
'; + if ($env{'form.choice'} eq 'minimal') { + $output = &mt('An error occurred creating the minimal template file [_1]',$errormsg); + } else { + $output = &mt('An error occurred storing the uploaded file [_1]',$errormsg); + } + $output .= '
'; + } + } elsif ($env{'form.phase'} eq 'upload_embedded') { + # Process file upload - phase two - upload embedded objects + my $uploadphase = 'check_embedded'; + my $primaryurl = &HTML::Entities::encode($env{'form.primaryurl'},'<>&"'); + my $state = &embedded_form_elems($uploadphase,$primaryurl); + my $url_root = '/uploaded/'.$cdom.'/'.$cnum; + my $actionurl = "/public/$cdom/$cnum/syllabus"; + my ($result,$flag,$numpathchgs) = + &Apache::loncommon::upload_embedded('syllabus','portfolio/syllabus', + $cnum,$cdom,'/userfiles',$url_root,undef,undef,undef,$state, + $actionurl); + unless ($numpathchgs) { + my $modres = + &Apache::loncommon::modify_html_refs('syllabus','portfolio/syllabus', + $cnum,$cdom, + '/userfiles',$env{'form.primaryurl'}); + $result .= $modres; + } + $output = $result.&return_to_editor($cdom,$cnum); + $earlyout = 1; + } elsif ($env{'form.phase'} eq 'check_embedded') { + # Process file upload - phase three - modify references in HTML file + my $uploadphase = 'modified_orightml'; + my $result = + &Apache::loncommon::modify_html_refs('syllabus','portfolio/syllabus', + $cnum,$cdom, + '/userfiles',$env{'form.primaryurl'}); + $output = $result.&return_to_editor($cdom,$cnum); + $earlyout = 1; } -# ---------------------------------------------------------------- Get syllabus - if (($syllabus{'uploaded.lastmodified'}) || ($allowed)) { - my $lastmod=$syllabus{'uploaded.lastmodified'}; - $lastmod=($lastmod?&Apache::lonlocal::locallocaltime($lastmod):&mt('never')); - my $who = &Apache::loncommon::aboutmewrapper( - &Apache::loncommon::plainname($syllabus{'uploaded.name'}, - $syllabus{'uploaded.domain'}),$syllabus{'uploaded.name'}, - $syllabus{'uploaded.domain'}); - if ($target ne 'tex') { - $r->print('
'.&mt('Last updated').':'. - $lastmod.''.&mt('by').' '.$who. - '

'); - } else { - $r->print('\\\\ '.&mt('Last updated').': '.$lastmod.' '.&mt('by').'\\\\ '. - &Apache::loncommon::plainname($syllabus{'uploaded.name'}, - $syllabus{'uploaded.domain'}).'\\\\'); - } - if ($allowed) { - $r->print(''. - ''); - } - my @htmlids=(); - foreach my $field (sort(keys(%syllabusfields))) { - if (($syllabus{$field}=~/\w/) || ($allowed)) { - my $message=$syllabus{$field}; - if ($field eq 'lll_includeurl') { # this is the "included" field - my $urls=$message; - $message=''; - foreach my $filelink (split(/\n/,$urls)) { - my $output=''; -# embed style? - my ($curfext)=($filelink=~/\.([^\.]+)$/); - my $embstyle=&Apache::loncommon::fileembstyle($curfext); - if (($embstyle eq 'ssi') || ($curfext=~/\/$/)) { -# make ssi call and remove everything but the body contents - $output=&Apache::lonnet::ssi_body($filelink); - } elsif ($embstyle eq 'img') { -# embed as an image - $output=''; - } - if ($target ne 'tex') { - $message.='

'.$output.'

'; - } else { - $message.=' '.&Apache::lonxml::xmlparse($r,'tex','

'.$output.'

').' '; - } - } - if ($allowed) { - $r->print('

'.$syllabusfields{$field}. - &Apache::loncommon::help_open_topic('Syllabus_URLs').'

'. - '

'.&mt('Show Public View').''. - &Apache::loncommon::help_open_topic('Uploaded_Templates_PublicView').'

'); - } else { - $r->print($message); - } - } else { - &Apache::lonfeedback::newline_to_br(\$message); - $message =~s|(https*://[^\s]+)|$1|g; - if ($allowed) { - $message=&Apache::lonspeller::markeduptext($message); - } - $message=&Apache::lontexconvert::msgtexconverted($message); - if ($target ne 'tex') { - $r->print('

'.$syllabusfields{$field}.'

'. - $message.'
'); - } else { - $r->print('\\\\\textbf{'.$syllabusfields{$field}.'}\\\\'. - &Apache::lonxml::xmlparse($r,'tex',$message).'\\\\'); - } - push(@htmlids,$field); - } - if ($allowed) { - $r->print('
'); - } - } - } - if ($allowed) { - $r->print(''. - &Apache::lonhtmlcommon::htmlareaselectactive(@htmlids)); - } - if ($target ne 'tex') {$r->print('

');} else {$r->print('\\\\');} - } else { - if ($target ne 'tex') {$r->print('

');} else {$r->print('\par ');} - $r->print('No syllabus information provided.'); - if ($target ne 'tex') {$r->print('

');} + return ($earlyout,$uploaded,$external,$minimal,$output); +} + +sub default_minimal_syllabus { + my ($cnum,$cdom) = @_; + my $title; + if ($env{'form.syllabustitle'}) { + $title = $env{'form.syllabustitle'}; + $title =~ s{`}{}g; + $title=~s/^\s+//; + $title=~s/\s+$//; } - if ($target ne 'tex') { - $r->print(&Apache::loncommon::end_page()); + if ($title eq '') { + $title = &mt('Syllabus'); + } + my $initialtext = &mt('Replace with your own content.'); + my $newhtml = < + +$title + + +

$title

+$initialtext + + +END + $env{'form.output'}=$newhtml; + return &Apache::lonnet::finishuserfileupload($cnum,$cdom,'output', + 'portfolio/syllabus/loncapa.html'); +} + +sub update_syllabus_env { + my ($cdom,$cnum,$courseenv,$saved,$uploaded,$minimal,$external) = @_; + return ($uploaded,$minimal,$external) unless(ref($courseenv) eq 'HASH'); + my $now = time; + my (@envkeys,%storehash); + if ($saved eq 'template') { + if ($uploaded || $env{'course.'.$env{'request.course.id'}.'.uploadedsyllabus'}) { + push(@envkeys,'uploaded'); + } + if ($minimal || $env{'course.'.$env{'request.course.id'}.'.minimalsyllabus'}) { + push(@envkeys,'minimal'); + } + if ($external || $env{'course.'.$env{'request.course.id'}.'.externalsyllabus'}) { + push(@envkeys,'external'); + } + $storehash{'updatedsyllabus'} = $now; + &Apache::lonnet::appenv({'course.'.$env{'request.course.id'}.'.updatedsyllabus' => $now +}); + } elsif ($saved eq 'url') { + my $prefix = &home_http_host($cdom,$cnum); + if ($external =~ m{^\Q$prefix/uploaded/$cdom/$cnum/portfolio/syllabus/\E(.+)$}) { + my $file = $1; + if ($file eq 'loncapa.html') { + if ($uploaded || $env{'course.'.$env{'request.course.id'}.'.uploadedsyllabus'}) { + push(@envkeys,'uploaded'); + } + } elsif ($minimal || $env{'course.'.$env{'request.course.id'}.'.minimalsyllabus'}) { + push(@envkeys,'minimal'); + } + } else { + if ($uploaded || $env{'course.'.$env{'request.course.id'}.'.uploadedsyllabus'}) { + push(@envkeys,'uploaded'); + } + if ($minimal || $env{'course.'.$env{'request.course.id'}.'.minimalsyllabus'}) { + push(@envkeys,'minimal'); + } + } + } elsif ($saved eq 'file') { + if ($minimal || $env{'course.'.$env{'request.course.id'}.'.minimalsyllabus'}) { + push(@envkeys,'minimal'); + } + } elsif ($saved eq 'minimal') { + if ($uploaded || $env{'course.'.$env{'request.course.id'}.'.uploadedsyllabus'}) { + push(@envkeys,'uploaded'); + } + } + if (@envkeys > 0) { + foreach my $item (@envkeys) { + my $key = $item.'syllabus'; + if ($courseenv->{$key} ne '') { + &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.'.$key); + if ($item eq 'minimal') { + &update_access_permissions($cdom,$cnum,'/syllabus/loncapa.html'); + } elsif ($item eq 'uploaded') { + if ($courseenv->{$key} =~ m{^\Q/uploaded/$cdom/$cnum/portfolio\E(/syllabus/.+)$}) { + my $filename = $1; + &update_access_permissions($cdom,$cnum,$filename); + } + } + $storehash{$key} = ''; + } elsif ($env{'course.'.$env{'request.course.id'}.'.'.$key} ne '') { + &Apache::lonnet::delenv('course.'.$env{'request.course.id'}.'.'.$key); + } + if ($item eq 'uploaded') { + undef($uploaded); + } + if ($item eq 'external') { + undef($external); + } + if ($item eq 'minimal') { + undef($minimal); + } + } + } + if (keys(%storehash) > 0) { + &Apache::lonnet::put('environment',\%storehash,$cdom,$cnum); + } + return ($uploaded,$minimal,$external); +} + +sub update_access_permissions { + my ($cdom,$cnum,$file_name) = @_; + my $current_permissions = &Apache::lonnet::get_portfile_permissions($cdom,$cnum); + my %access_controls = + &Apache::lonnet::get_access_controls($current_permissions,'',$file_name); + if (keys(%access_controls) > 0) { + my %changes; + foreach my $key (keys(%{$access_controls{$file_name}})) { + $changes{'delete'}{$key} = 1; + } + if (keys(%changes) > 0) { + my ($outcome,$deloutcome,$new_values,$translation) = + &Apache::lonnet::modify_access_controls($file_name,\%changes, + $cdom,$cnum); + } + } + return; +} + +sub home_http_host { + my ($cdom,$cnum) = @_; + my $home=&Apache::lonnet::homeserver($cnum,$cdom); + if ($home ne 'no_host') { + my $protocol = $Apache::lonnet::protocol{$home}; + $protocol = 'http' if ($protocol ne 'https'); + return $protocol.'://'.&Apache::lonnet::hostname($home); + } + return; +} + +sub process_upload { + my ($upload_output,$cnum,$cdom,$allfiles,$codebase) = @_; + my ($parseaction,$showupload,$mimetype); + my $dest = 'portfolio/syllabus'; + if ($env{'form.parserflag'}) { + $parseaction = 'parse'; + } + my $url=&Apache::lonnet::userfileupload('syllabusfile','syllabus',$dest, + $parseaction,$allfiles, + $codebase,undef,undef,undef,undef, + undef,undef,\$mimetype); + if ($url =~ m{^/uploaded/\Q$cdom\E/\Q$cnum\E.*/([^/]+)$}) { + my $stored = $1; + $showupload = '

'.&mt('Uploaded [_1]', + ''.$stored.''). + '

'; } else { - $r->print('\end{document}'); + my ($filename) = ($env{'form.syllabusfile.filename'} =~ m{([^/]+)$}); + $$upload_output = '
'. + &mt('Unable to save file [_1].', + ''.$filename.''). + '
'; + return (); } - return OK; -} + my $needlink; + if (($parseaction eq 'parse') && ($mimetype eq 'text/html')) { + $$upload_output = $showupload; + my $total_embedded = scalar(keys(%{$allfiles})); + if ($total_embedded > 0) { + my $uploadphase = 'upload_embedded'; + my $primaryurl = &HTML::Entities::encode($url,'<>&"'); + my $state = &embedded_form_elems($uploadphase,$primaryurl); + my $actionurl = "/public/$cdom/$cnum/syllabus"; + my ($embedded,$num,$numpathchanges,$existing); + ($embedded,$num,$numpathchanges,$existing) = + &Apache::loncommon::ask_for_embedded_content($actionurl,$state, + $allfiles,$codebase, + {'error_on_invalid_names' => 1, + 'ignore_remote_references' => 1,}); + if ($embedded) { + $needlink = 1; + if ($num) { + $$upload_output .= + '

'.&mt('This file contains embedded multimedia objects, which need to be uploaded.').'

'.$embedded; + } elsif ($numpathchanges) { + $$upload_output .= $embedded; + } else { + $$upload_output .= $embedded; + &Apache::loncommon::modify_html_refs('syllabus','portfolio/syllabus', + $cnum,$cdom,'/userfiles',$url); + } + } else { + $$upload_output .= &mt('Embedded item(s) already present, so no additional upload(s) required').'
'; + &Apache::loncommon::modify_html_refs('syllabus','portfolio/syllabus', + $cnum,$cdom,'/userfiles',$url); + + } + } else { + $$upload_output .= &mt('No embedded items identified').'
'; + } + $$upload_output = '
'.$$upload_output.'
'; + } + return ($url,$needlink); +} + +sub embedded_form_elems { + my ($phase,$primaryurl) = @_; + return < + + + +STATE +} + +sub return_to_editor { + my ($cdom,$cnum) = @_; + my $actionurl = "/public/$cdom/$cnum/syllabus"; + return '

'. + ''."\n". + ''.&mt('Return to Editor'). + '

'; +} + +sub editfile_button { + my ($url,$context,$editable) = @_; + my $edittext=&mt('Edit'); + my $deltext=&mt('Delete'); + my $output; + if ($editable) { + $output = ' + +    '; + } + $output .= ' + + + '; + return $output; +} + +sub editbutton_js { + my %js_lt = &Apache::lonlocal::texthash( + min => 'Are you sure you want to delete the contents of the syllabus template?', + file => 'Are you sure you want to delete the uploaded syllabus file?', + noundo => 'This action cannot be reversed.' + ); + &js_escape(\%js_lt); + return < + // + +ENDJS +} 1; __END__ 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.