Diff for /loncom/interface/loncommon.pm between versions 1.1075.2.36 and 1.1075.2.85

version 1.1075.2.36, 2013/05/12 03:36:46 version 1.1075.2.85, 2014/12/21 17:29:44
Line 69  use Apache::lontexconvert(); Line 69  use Apache::lontexconvert();
 use Apache::lonclonecourse();  use Apache::lonclonecourse();
 use Apache::lonuserutils();  use Apache::lonuserutils();
 use Apache::lonuserstate();  use Apache::lonuserstate();
   use Apache::courseclassifier();
 use LONCAPA qw(:DEFAULT :match);  use LONCAPA qw(:DEFAULT :match);
 use DateTime::TimeZone;  use DateTime::TimeZone;
 use DateTime::Locale::Catalog;  use DateTime::Locale::Catalog;
 use Authen::Captcha;  use Authen::Captcha;
 use Captcha::reCAPTCHA;  use Captcha::reCAPTCHA;
   use Crypt::DES;
   use DynaLoader; # for Crypt::DES version
   
 # ---------------------------------------------- Designs  # ---------------------------------------------- Designs
 use vars qw(%defaultdesign);  use vars qw(%defaultdesign);
Line 1234  sub help_open_topic { Line 1237  sub help_open_topic {
     $topic=~s/\W/\_/g;      $topic=~s/\W/\_/g;
   
     if (!$stayOnPage) {      if (!$stayOnPage) {
  $link = "javascript:openMyModal('/adm/help/${filename}.hlp',$width,$height,'yes');";          if ($env{'browser.mobile'}) {
       $link = "javascript:openMyModal('/adm/help/${filename}.hlp',$width,$height,'yes');";
           } else {
               $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";
           }
     } elsif ($stayOnPage eq 'popup') {      } elsif ($stayOnPage eq 'popup') {
         $link = "javascript:void(open('/adm/help/${filename}.hlp', 'Help_for_$topic', 'menubar=0,toolbar=1,scrollbars=1,width=$width,height=$height,resizable=yes'))";          $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 {
Line 1285  sub helpLatexCheatsheet { Line 1292  sub helpLatexCheatsheet {
     unless ($not_author) {      unless ($not_author) {
         $out .= ' <span>'          $out .= ' <span>'
        .&help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),$stayOnPage,undef,600)         .&help_open_topic('Authoring_Output_Tags',&mt('Output Tags'),$stayOnPage,undef,600)
        .'</span>';         .'</span> <span>'
                  .&help_open_topic('Authoring_Multilingual_Problems',&mt('Languages'),$stayOnPage,undef,600)
                  .'</span>';
     }      }
     $out .= '</span>'; # End cheatsheet      $out .= '</span>'; # End cheatsheet
     return $out;      return $out;
Line 1348  sub help_open_menu { Line 1357  sub help_open_menu {
 sub top_nav_help {  sub top_nav_help {
     my ($text) = @_;      my ($text) = @_;
     $text = &mt($text);      $text = &mt($text);
     my $stay_on_page = 1;      my $stay_on_page;
       unless ($env{'environment.remote'} eq 'on') {
     my $link = ($stay_on_page) ? "javascript:helpMenu('display')"          $stay_on_page = 1;
                      : "javascript:helpMenu('open')";      }
     my $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);      my ($link,$banner_link);
       unless ($env{'request.noversionuri'} =~ m{^/adm/helpmenu}) {
           $link = ($stay_on_page) ? "javascript:helpMenu('display')"
                            : "javascript:helpMenu('open')";
           $banner_link = &update_help_link(undef,undef,undef,undef,$stay_on_page);
       }
     my $title = &mt('Get help');      my $title = &mt('Get help');
       if ($link) {
     return <<"END";          return <<"END";
 $banner_link  $banner_link
  <a href="$link" title="$title">$text</a>  <a href="$link" title="$title">$text</a>
 END  END
       } else {
           return '&nbsp;'.$text.'&nbsp;';
       }
 }  }
   
 sub help_menu_js {  sub help_menu_js {
     my ($text) = @_;      my ($httphost) = @_;
     my $stayOnPage = 1;      my $stayOnPage = 1;
     my $width = 620;      my $width = 620;
     my $height = 600;      my $height = 600;
     my $helptopic=&general_help();      my $helptopic=&general_help();
     my $details_link = '/adm/help/'.$helptopic.'.hlp';      my $details_link = $httphost.'/adm/help/'.$helptopic.'.hlp';
     my $nothing=&Apache::lonhtmlcommon::javascript_nothing();      my $nothing=&Apache::lonhtmlcommon::javascript_nothing();
     my $start_page =      my $start_page =
         &Apache::loncommon::start_page('Help Menu', undef,          &Apache::loncommon::start_page('Help Menu', undef,
        {'frameset'    => 1,         {'frameset'    => 1,
  'js_ready'    => 1,   'js_ready'    => 1,
                                           'use_absolute' => $httphost, 
  'add_entries' => {   'add_entries' => {
     'border' => '0',      'border' => '0',
     'rows'   => "110,*",},});      'rows'   => "110,*",},});
Line 1405  function helpMenu(target) { Line 1422  function helpMenu(target) {
     return;      return;
 }  }
 function writeHelp(caller) {  function writeHelp(caller) {
     caller.document.writeln('$start_page\\n<frame name="bannerframe" src="'+banner_link+'" />\\n<frame name="bodyframe" src="$details_link" />\\n$end_page')      caller.document.writeln('$start_page\\n<frame name="bannerframe" src="'+banner_link+'" marginwidth="0" marginheight="0" frameborder="0">\\n');
     caller.document.close()      caller.document.writeln('<frame name="bodyframe" src="$details_link" marginwidth="0" marginheight="0" frameborder="0">\\n$end_page');
     caller.focus()      caller.document.close();
       caller.focus();
 }  }
 // END LON-CAPA Internal -->  // END LON-CAPA Internal -->
 // ]]>  // ]]>
Line 1719  RESIZE Line 1737  RESIZE
   
 =head1 Excel and CSV file utility routines  =head1 Excel and CSV file utility routines
   
 =over 4  
   
 =cut  =cut
   
 ###############################################################  ###############################################################
Line 1728  RESIZE Line 1744  RESIZE
   
 =pod  =pod
   
   =over 4
   
 =item * &csv_translate($text)   =item * &csv_translate($text) 
   
 Translate $text to allow it to be output as a 'comma separated values'   Translate $text to allow it to be output as a 'comma separated values' 
Line 2161  sub select_level_form { Line 2179  sub select_level_form {
   
 =pod  =pod
   
 =item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoma,$excdoms)  =item * &select_dom_form($defdom,$name,$includeempty,$showdomdesc,$onchange,$incdoms,$excdoms)
   
 Returns a string containing a <select name='$name' size='1'> form to   Returns a string containing a <select name='$name' size='1'> form to 
 allow a user to select the domain to preform an operation in.    allow a user to select the domain to preform an operation in.  
Line 2319  Outputs: Line 2337  Outputs:
   
 =item * $clientos  =item * $clientos
   
   =item * $clientmobile
   
   =item * $clientinfo
   
   =item * $clientosversion
   
 =back  =back
   
 =back   =back 
Line 2337  sub decode_user_agent { Line 2361  sub decode_user_agent {
     my $clientversion='0';      my $clientversion='0';
     my $clientmathml='';      my $clientmathml='';
     my $clientunicode='0';      my $clientunicode='0';
       my $clientmobile=0;
       my $clientosversion='';
     for (my $i=0;$i<=$#browsertype;$i++) {      for (my $i=0;$i<=$#browsertype;$i++) {
         my ($bname,$match,$notmatch,$vreg,$minv,$univ)=split(/\:/,$browsertype[$i]);          my ($bname,$match,$notmatch,$vreg,$minv,$univ)=split(/\%/,$browsertype[$i]);
  if (($httpbrowser=~/$match/i)  && ($httpbrowser!~/$notmatch/i)) {   if (($httpbrowser=~/$match/i)  && ($httpbrowser!~/$notmatch/i)) {
     $clientbrowser=$bname;      $clientbrowser=$bname;
             $httpbrowser=~/$vreg/i;              $httpbrowser=~/$vreg/i;
Line 2348  sub decode_user_agent { Line 2374  sub decode_user_agent {
  }   }
     }      }
     my $clientos='unknown';      my $clientos='unknown';
       my $clientinfo;
     if (($httpbrowser=~/linux/i) ||      if (($httpbrowser=~/linux/i) ||
         ($httpbrowser=~/unix/i) ||          ($httpbrowser=~/unix/i) ||
         ($httpbrowser=~/ux/i) ||          ($httpbrowser=~/ux/i) ||
Line 2357  sub decode_user_agent { Line 2384  sub decode_user_agent {
     if ($httpbrowser=~/next/i) { $clientos='next'; }      if ($httpbrowser=~/next/i) { $clientos='next'; }
     if (($httpbrowser=~/mac/i) ||      if (($httpbrowser=~/mac/i) ||
         ($httpbrowser=~/powerpc/i)) { $clientos='mac'; }          ($httpbrowser=~/powerpc/i)) { $clientos='mac'; }
     if ($httpbrowser=~/win/i) { $clientos='win'; }      if ($httpbrowser=~/win/i) {
           $clientos='win';
           if ($httpbrowser =~/Windows\s+NT\s+(\d+\.\d+)/i) {
               $clientosversion = $1;
           }
       }
     if ($httpbrowser=~/embed/i) { $clientos='pda'; }      if ($httpbrowser=~/embed/i) { $clientos='pda'; }
       if ($httpbrowser=~/(Android|iPod|iPad|iPhone|webOS|Blackberry|Windows Phone|Opera m(?:ob|in)|Fennec)/i) {
           $clientmobile=lc($1);
       }
       if ($httpbrowser=~ m{Firefox/(\d+\.\d+)}) {
           $clientinfo = 'firefox-'.$1;
       } elsif ($httpbrowser=~ m{chromeframe/(\d+\.\d+)\.}) {
           $clientinfo = 'chromeframe-'.$1;
       }
     return ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,      return ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,
             $clientunicode,$clientos,);              $clientunicode,$clientos,$clientmobile,$clientinfo,
               $clientosversion);
 }  }
   
 ###############################################################  ###############################################################
Line 3220  sub screenname { Line 3261  sub screenname {
 # ------------------------------------------------------------- Confirm Wrapper  # ------------------------------------------------------------- Confirm Wrapper
 =pod  =pod
   
 =item confirmwrapper  =item * &confirmwrapper($message)
   
 Wrap messages about completion of operation in box  Wrap messages about completion of operation in box
   
Line 4204  sub findallcourses { Line 4245  sub findallcourses {
 ###############################################  ###############################################
   
 sub blockcheck {  sub blockcheck {
     my ($setters,$activity,$uname,$udom,$url) = @_;      my ($setters,$activity,$uname,$udom,$url,$is_course) = @_;
   
     if (!defined($udom)) {      if (defined($udom) && defined($uname)) {
           # If uname and udom are for a course, check for blocks in the course.
           if (($is_course) || (&Apache::lonnet::is_course($udom,$uname))) {
               my ($startblock,$endblock,$triggerblock) =
                   &get_blocks($setters,$activity,$udom,$uname,$url);
               return ($startblock,$endblock,$triggerblock);
           }
       } else {
         $udom = $env{'user.domain'};          $udom = $env{'user.domain'};
     }  
     if (!defined($uname)) {  
         $uname = $env{'user.name'};          $uname = $env{'user.name'};
     }      }
   
     # If uname and udom are for a course, check for blocks in the course.  
   
     if (&Apache::lonnet::is_course($udom,$uname)) {  
         my ($startblock,$endblock,$triggerblock) =   
             &get_blocks($setters,$activity,$udom,$uname,$url);  
         return ($startblock,$endblock,$triggerblock);  
     }  
   
     my $startblock = 0;      my $startblock = 0;
     my $endblock = 0;      my $endblock = 0;
     my $triggerblock = '';      my $triggerblock = '';
Line 4230  sub blockcheck { Line 4268  sub blockcheck {
     # boards, chat or groups, check for blocking in current course only.      # boards, chat or groups, check for blocking in current course only.
   
     if (($activity eq 'boards' || $activity eq 'chat' ||      if (($activity eq 'boards' || $activity eq 'chat' ||
          $activity eq 'groups') && ($env{'request.course.id'})) {           $activity eq 'groups' || $activity eq 'printout') &&
           ($env{'request.course.id'})) {
         foreach my $key (keys(%live_courses)) {          foreach my $key (keys(%live_courses)) {
             if ($key ne $env{'request.course.id'}) {              if ($key ne $env{'request.course.id'}) {
                 delete($live_courses{$key});                  delete($live_courses{$key});
Line 4494  sub parse_block_record { Line 4533  sub parse_block_record {
 }  }
   
 sub blocking_status {  sub blocking_status {
     my ($activity,$uname,$udom,$url) = @_;      my ($activity,$uname,$udom,$url,$is_course) = @_;
     my %setters;      my %setters;
   
 # check for active blocking  # check for active blocking
     my ($startblock,$endblock,$triggerblock) =       my ($startblock,$endblock,$triggerblock) = 
         &blockcheck(\%setters,$activity,$uname,$udom,$url);          &blockcheck(\%setters,$activity,$uname,$udom,$url,$is_course);
     my $blocked = 0;      my $blocked = 0;
     if ($startblock && $endblock) {      if ($startblock && $endblock) {
         $blocked = 1;          $blocked = 1;
Line 4838  sub designparm { Line 4877  sub designparm {
   
 Inputs: $url (usually will be undef).  Inputs: $url (usually will be undef).
   
 Returns: Path to Construction Space containing the resource or   Returns: Path to Authoring Space containing the resource or 
          directory being viewed (or for which action is being taken).            directory being viewed (or for which action is being taken). 
          If $url is provided, and begins /priv/<domain>/<uname>           If $url is provided, and begins /priv/<domain>/<uname>
          the path will be that portion of the $context argument.           the path will be that portion of the $context argument.
Line 4901  Input: (optional) filename from which br Line 4940  Input: (optional) filename from which br
        is appropriate for use in building the breadcrumb trail.         is appropriate for use in building the breadcrumb trail.
   
 Returns: HTML div with CSTR path and recent box  Returns: HTML div with CSTR path and recent box
          To be included on Construction Space pages           To be included on Authoring Space pages
   
 =cut  =cut
   
Line 4932  sub CSTR_pageheader { Line 4971  sub CSTR_pageheader {
     my $output =      my $output =
          '<div>'           '<div>'
         .&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it?          .&Apache::loncommon::help_open_menu('','',3,'Authoring') #FIXME: Broken? Where is it?
         .'<b>'.&mt('Construction Space:').'</b> '          .'<b>'.&mt('Authoring Space:').'</b> '
         .'<form name="dirs" method="post" action="'.$formaction          .'<form name="dirs" method="post" action="'.$formaction
         .'" target="_top">' #FIXME lonpubdir: target="_parent"          .'" target="_top">' #FIXME lonpubdir: target="_parent"
         .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv/'.$udom,undef,undef);          .&Apache::lonhtmlcommon::crumbs($uname.'/'.$parentpath,'_top','/priv/'.$udom,undef,undef);
Line 5023  sub bodytag { Line 5062  sub bodytag {
         $public = 1;          $public = 1;
     }      }
     if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }      if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
       my $httphost = $args->{'use_absolute'};
   
     $function = &get_users_function() if (!$function);      $function = &get_users_function() if (!$function);
     my $img =    &designparm($function.'.img',$domain);      my $img =    &designparm($function.'.img',$domain);
Line 5038  sub bodytag { Line 5078  sub bodytag {
     @design{keys(%$addentries)} = @$addentries{keys(%$addentries)};       @design{keys(%$addentries)} = @$addentries{keys(%$addentries)}; 
   
  # role and realm   # role and realm
     my ($role,$realm) = split(/\./,$env{'request.role'},2);      my ($role,$realm) = split(m{\./},$env{'request.role'},2);
       if ($realm) {
           $realm = '/'.$realm;
       }
     if ($role  eq 'ca') {      if ($role  eq 'ca') {
         my ($rdom,$rname) = ($realm =~ m{^/($match_domain)/($match_username)$});          my ($rdom,$rname) = ($realm =~ m{^/($match_domain)/($match_username)$});
         $realm = &plainname($rname,$rdom);          $realm = &plainname($rname,$rdom);
Line 5064  sub bodytag { Line 5107  sub bodytag {
     my $bodytag = "<body $extra_body_attr>".      my $bodytag = "<body $extra_body_attr>".
  &Apache::lontexconvert::init_math_support($args->{'inherit_jsmath'});   &Apache::lontexconvert::init_math_support($args->{'inherit_jsmath'});
   
     if ($bodyonly) {      &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);
   
       if (($bodyonly) || ($no_nav_bar) || ($env{'form.inhibitmenu'} eq 'yes')) {
         return $bodytag;          return $bodytag;
     }       }
   
     my $name = &plainname($env{'user.name'},$env{'user.domain'});  
     if ($public) {      if ($public) {
  undef($role);   undef($role);
     } else {  
  $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'},  
                                 undef,'LC_menubuttons_link');  
     }      }
           
     my $titleinfo = '<h1>'.$title.'</h1>';      my $titleinfo = '<h1>'.$title.'</h1>';
Line 5089  sub bodytag { Line 5130  sub bodytag {
     }      }
   
     $role = '<span class="LC_nobreak">('.$role.')</span>' if $role;      $role = '<span class="LC_nobreak">('.$role.')</span>' if $role;
     &get_unprocessed_cgi($ENV{'QUERY_STRING'}, ['inhibitmenu']);  
   
     if ($no_nav_bar || $env{'form.inhibitmenu'} eq 'yes') {   
         return $bodytag;   
     }  
   
     if ($env{'request.state'} eq 'construct') { $forcereg=1; }      if ($env{'request.state'} eq 'construct') { $forcereg=1; }
   
   
   
     my $funclist;      my $funclist;
     if (($env{'environment.remote'} eq 'on') && ($env{'request.state'} ne 'construct')) {      if (($env{'environment.remote'} eq 'on') && ($env{'request.state'} ne 'construct')) {
         $bodytag .= Apache::lonhtmlcommon::scripttag(Apache::lonmenu::utilityfunctions(), 'start')."\n".          $bodytag .= Apache::lonhtmlcommon::scripttag(Apache::lonmenu::utilityfunctions($httphost), 'start')."\n".
                     Apache::lonmenu::serverform();                      Apache::lonmenu::serverform();
         my $forbodytag;          my $forbodytag;
         &Apache::lonmenu::prepare_functions($env{'request.noversionuri'},          &Apache::lonmenu::prepare_functions($env{'request.noversionuri'},
Line 5115  sub bodytag { Line 5153  sub bodytag {
         #        $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls          #        $titleinfo = &CSTR_pageheader(); #FIXME: Will be removed once all scripts have their own calls
         #    }          #    }
   
           $bodytag .= Apache::lonhtmlcommon::scripttag(
               Apache::lonmenu::utilityfunctions($httphost), 'start');
   
           my ($left,$right) = Apache::lonmenu::primary_menu();
   
         if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {          if ($env{'request.noversionuri'} =~ m{^/res/adm/pages/}) {
             if ($dc_info) {              if ($dc_info) {
                  $dc_info = qq|<span class="LC_cusr_subheading">$dc_info</span>|;                   $dc_info = qq|<span class="LC_cusr_subheading">$dc_info</span>|;
             }              }
             $bodytag .= qq|<div id="LC_nav_bar">$name $role<br />              $bodytag .= qq|<div id="LC_nav_bar">$left $role<br />
                            <em>$realm</em> $dc_info</div>|;                             <em>$realm</em> $dc_info</div>|;
             return $bodytag;              return $bodytag;
         }          }
   
         unless ($env{'request.symb'} =~ m/\.page___\d+___/) {          unless ($env{'request.symb'} =~ m/\.page___\d+___/) {
             $bodytag .= qq|<div id="LC_nav_bar">$name $role</div>|;              $bodytag .= qq|<div id="LC_nav_bar">$left $role</div>|;
         }          }
   
         $bodytag .= Apache::lonhtmlcommon::scripttag(          $bodytag .= $right;
             Apache::lonmenu::utilityfunctions(), 'start');  
   
         $bodytag .= Apache::lonmenu::primary_menu();  
   
         if ($dc_info) {          if ($dc_info) {
             $dc_info = &dc_courseid_toggle($dc_info);              $dc_info = &dc_courseid_toggle($dc_info);
         }          }
         $bodytag .= qq|<div id="LC_realm">$realm $dc_info</div>|;          $bodytag .= qq|<div id="LC_realm">$realm $dc_info</div>|;
   
           #if directed to not display the secondary menu, don't.
           if ($args->{'no_secondary_menu'}) {
               return $bodytag;
           }
         #don't show menus for public users          #don't show menus for public users
         if (!$public){          if (!$public){
             $bodytag .= Apache::lonmenu::secondary_menu();              $bodytag .= Apache::lonmenu::secondary_menu($httphost);
             $bodytag .= Apache::lonmenu::serverform();              $bodytag .= Apache::lonmenu::serverform();
             $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');              $bodytag .= Apache::lonhtmlcommon::scripttag('', 'end');
             if ($env{'request.state'} eq 'construct') {              if ($env{'request.state'} eq 'construct') {
Line 5181  sub bodytag { Line 5223  sub bodytag {
     }      }
     my $upperleft='<img src="'.$imgsrc.'" alt="'.$function.'" />';      my $upperleft='<img src="'.$imgsrc.'" alt="'.$function.'" />';
   
       my $help=($no_inline_link?''
                 :&Apache::loncommon::top_nav_help('Help'));
   
     # Explicit link to get inline menu      # Explicit link to get inline menu
     my $menu= ($no_inline_link?''      my $menu= ($no_inline_link?''
                :'<a href="/adm/remote?action=collapse" target="_top">'.&mt('Switch to Inline Menu Mode').'</a>');                 :'<a href="/adm/remote?action=collapse" target="_top">'.&mt('Switch to Inline Menu Mode').'</a>');
Line 5189  sub bodytag { Line 5234  sub bodytag {
         $dc_info = qq|<span class="LC_cusr_subheading">($dc_info)</span>|;          $dc_info = qq|<span class="LC_cusr_subheading">($dc_info)</span>|;
     }      }
   
       my $name = &plainname($env{'user.name'},$env{'user.domain'});
       unless ($public) {
           $name = &aboutmewrapper($name,$env{'user.name'},$env{'user.domain'},
                                   undef,'LC_menubuttons_link');
       }
   
     unless ($env{'form.inhibitmenu'}) {      unless ($env{'form.inhibitmenu'}) {
         $bodytag .= qq|<div id="LC_nav_bar">$name $role</div>          $bodytag .= qq|<div id="LC_nav_bar">$name $role</div>
                        <ol class="LC_primary_menu LC_right">                         <ol class="LC_primary_menu LC_floatright LC_right">
                          <li>$help</li>
                        <li>$menu</li>                         <li>$menu</li>
                        </ol><div id="LC_realm"> $realm $dc_info</div>|;                         </ol><div id="LC_realm"> $realm $dc_info</div>|;
     }      }
Line 5199  sub bodytag { Line 5251  sub bodytag {
         if (!$public){          if (!$public){
             if ($env{'request.state'} eq 'construct') {              if ($env{'request.state'} eq 'construct') {
                 $funclist = &Apache::lonhtmlcommon::scripttag(                  $funclist = &Apache::lonhtmlcommon::scripttag(
                                 &Apache::lonmenu::utilityfunctions(), 'start').                                  &Apache::lonmenu::utilityfunctions($httphost), 'start').
                             &Apache::lonhtmlcommon::scripttag('','end').                              &Apache::lonhtmlcommon::scripttag('','end').
                             &Apache::lonmenu::innerregister($forcereg,                              &Apache::lonmenu::innerregister($forcereg,
                                                             $args->{'bread_crumbs'});                                                              $args->{'bread_crumbs'});
Line 5250  sub make_attr_string { Line 5302  sub make_attr_string {
     }      }
   
     my $attr_string;      my $attr_string;
     foreach my $attr (keys(%$attr_ref)) {      foreach my $attr (sort(keys(%$attr_ref))) {
  $attr_string .= " $attr=\"".$attr_ref->{$attr}.'" ';   $attr_string .= " $attr=\"".$attr_ref->{$attr}.'" ';
     }      }
     return $attr_string;      return $attr_string;
Line 5381  form, .inline { Line 5433  form, .inline {
   vertical-align:middle;    vertical-align:middle;
 }  }
   
   .LC_floatleft {
     float: left;
   }
   
   .LC_floatright {
     float: right;
   }
   
 .LC_400Box {  .LC_400Box {
   width:400px;    width:400px;
 }  }
Line 6456  div.LC_edit_problem_saves { Line 6516  div.LC_edit_problem_saves {
   white-space: nowrap;    white-space: nowrap;
 }  }
   
   .LC_edit_problem_latexhelper{
       text-align: right;
   }
   
   #LC_edit_problem_colorful div{
       margin-left: 40px;
   }
   
 img.stift {  img.stift {
   border-width: 0;    border-width: 0;
   vertical-align: middle;    vertical-align: middle;
Line 6470  div.LC_createcourse { Line 6538  div.LC_createcourse {
 }  }
   
 .LC_dccid {  .LC_dccid {
     float: right;
   margin: 0.2em 0 0 0;    margin: 0.2em 0 0 0;
   padding: 0;    padding: 0;
   font-size: 90%;    font-size: 90%;
Line 6567  fieldset > legend { Line 6636  fieldset > legend {
 }  }
   
 ol.LC_primary_menu {  ol.LC_primary_menu {
   float: right;  
   margin: 0;    margin: 0;
   padding: 0;    padding: 0;
   background-color: $pgbg_or_bgcolor;    background-color: $pgbg_or_bgcolor;
Line 7222  sub headtag { Line 7290  sub headtag {
     my $function = $args->{'function'} || &get_users_function();      my $function = $args->{'function'} || &get_users_function();
     my $domain   = $args->{'domain'}   || &determinedomain();      my $domain   = $args->{'domain'}   || &determinedomain();
     my $bgcolor  = $args->{'bgcolor'}  || &designparm($function.'.pgbg',$domain);      my $bgcolor  = $args->{'bgcolor'}  || &designparm($function.'.pgbg',$domain);
       my $httphost = $args->{'use_absolute'};
     my $url = join(':',$env{'user.name'},$env{'user.domain'},      my $url = join(':',$env{'user.name'},$env{'user.domain'},
    $Apache::lonnet::perlvar{'lonVersion'},     $Apache::lonnet::perlvar{'lonVersion'},
    #time(),     #time(),
Line 7232  sub headtag { Line 7301  sub headtag {
   
     my $result =      my $result =
  '<head>'.   '<head>'.
  &font_settings();   &font_settings($args);
   
     my $inhibitprint = &print_suppression();      my $inhibitprint;
       if ($args->{'print_suppress'}) {
           $inhibitprint = &print_suppression();
       }
   
     if (!$args->{'frameset'}) {      if (!$args->{'frameset'}) {
  $result .= &Apache::lonhtmlcommon::htmlareaheaders();   $result .= &Apache::lonhtmlcommon::htmlareaheaders();
Line 7245  sub headtag { Line 7317  sub headtag {
     if (!$args->{'no_nav_bar'}       if (!$args->{'no_nav_bar'} 
  && !$args->{'only_body'}   && !$args->{'only_body'}
  && !$args->{'frameset'}) {   && !$args->{'frameset'}) {
  $result .= &help_menu_js();   $result .= &help_menu_js($httphost);
         $result.=&modal_window();          $result.=&modal_window();
         $result.=&togglebox_script();          $result.=&togglebox_script();
         $result.=&wishlist_window();          $result.=&wishlist_window();
Line 7280  ADDMETA Line 7352  ADDMETA
     }      }
     if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }      if (!$args->{'no_auto_mt_title'}) { $title = &mt($title); }
     $result .= '<title> LON-CAPA '.$title.'</title>'      $result .= '<title> LON-CAPA '.$title.'</title>'
  .'<link rel="stylesheet" type="text/css" href="'.$url.'" />'   .'<link rel="stylesheet" type="text/css" href="'.$url.'"';
       if (!$args->{'frameset'}) {
           $result .= ' /';
       }
       $result .= '>'
         .$inhibitprint          .$inhibitprint
  .$head_extra;   .$head_extra;
       if ($env{'browser.mobile'}) {
           $result .= '
   <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
   <meta name="apple-mobile-web-app-capable" content="yes" />';
       }
     return $result.'</head>';      return $result.'</head>';
 }  }
   
Line 7292  ADDMETA Line 7373  ADDMETA
   
 Returns neccessary <meta> to set the proper encoding  Returns neccessary <meta> to set the proper encoding
   
 Inputs: none  Inputs: optional reference to HASH -- $args passed to &headtag()
   
 =cut  =cut
   
 sub font_settings {  sub font_settings {
       my ($args) = @_;
     my $headerstring='';      my $headerstring='';
     if (!$env{'browser.mathml'} && $env{'browser.unicode'}) {      if ((!$env{'browser.mathml'} && $env{'browser.unicode'}) ||
           ((ref($args) eq 'HASH') && ($args->{'browser.unicode'}))) {
  $headerstring.=   $headerstring.=
     '<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />';      '<meta http-equiv="Content-Type" content="text/html; charset=utf-8"';
           if (!$args->{'frameset'}) {
               $headerstring.= ' /';
           }
           $headerstring .= '>'."\n";
     }      }
     return $headerstring;      return $headerstring;
 }  }
Line 7345  sub print_suppression { Line 7432  sub print_suppression {
         }          }
         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};          my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};          my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
         my $blocked = &blocking_status('printout',$cnum,$cdom);          my $blocked = &blocking_status('printout',$cnum,$cdom,undef,1);
         if ($blocked) {          if ($blocked) {
             my $checkrole = "cm./$cdom/$cnum";              my $checkrole = "cm./$cdom/$cnum";
             if ($env{'request.course.sec'} ne '') {              if ($env{'request.course.sec'} ne '') {
Line 7392  Inputs: none Line 7479  Inputs: none
 =cut  =cut
   
 sub xml_begin {  sub xml_begin {
       my ($is_frameset) = @_;
     my $output='';      my $output='';
   
     if ($env{'browser.mathml'}) {      if ($env{'browser.mathml'}) {
Line 7403  sub xml_begin { Line 7491  sub xml_begin {
     .'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">'      .'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd">'
             .'<html xmlns:math="http://www.w3.org/1998/Math/MathML" '               .'<html xmlns:math="http://www.w3.org/1998/Math/MathML" ' 
     .'xmlns="http://www.w3.org/1999/xhtml">';      .'xmlns="http://www.w3.org/1999/xhtml">';
       } elsif ($is_frameset) {
           $output='<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">'."\n".
                   '<html>'."\n";
     } else {      } else {
  $output='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'   $output='<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">'."\n".
            .'<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';                  '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">'."\n";
     }      }
     return $output;      return $output;
 }  }
Line 7474  sub start_page { Line 7565  sub start_page {
     my ($result,@advtools);      my ($result,@advtools);
   
     if (! exists($args->{'skip_phases'}{'head'}) ) {      if (! exists($args->{'skip_phases'}{'head'}) ) {
         $result .= &xml_begin() . &headtag($title, $head_extra, $args);          $result .= &xml_begin($args->{'frameset'}) . &headtag($title, $head_extra, $args);
     }      }
           
     if (! exists($args->{'skip_phases'}{'body'}) ) {      if (! exists($args->{'skip_phases'}{'body'}) ) {
Line 7580  function set_wishlistlink(title, path) { Line 7671  function set_wishlistlink(title, path) {
         title = document.title;          title = document.title;
         title = title.replace(/^LON-CAPA /,'');          title = title.replace(/^LON-CAPA /,'');
     }      }
       title = encodeURIComponent(title);
       title = title.replace("'","\\\'");
     if (!path) {      if (!path) {
         path = location.pathname;          path = location.pathname;
     }      }
       path = encodeURIComponent(path);
       path = path.replace("'","\\\'");
     Win = window.open('/adm/wishlist?mode=newLink&setTitle='+title+'&setPath='+path,      Win = window.open('/adm/wishlist?mode=newLink&setTitle='+title+'&setPath='+path,
                       'wishlistNewLink','width=560,height=350,scrollbars=0');                        'wishlistNewLink','width=560,height=350,scrollbars=0');
 }  }
Line 7623  var modalWindow = { Line 7718  var modalWindow = {
  $(".LCmodal-overlay").click(function(){modalWindow.close();});   $(".LCmodal-overlay").click(function(){modalWindow.close();});
  }   }
 };  };
  var openMyModal = function(source,width,height,scrolling)   var openMyModal = function(source,width,height,scrolling,transparency,style)
  {   {
                   source = source.replace("'","&#39;");
  modalWindow.windowId = "myModal";   modalWindow.windowId = "myModal";
  modalWindow.width = width;   modalWindow.width = width;
  modalWindow.height = height;   modalWindow.height = height;
  modalWindow.content = "<iframe width='"+width+"' height='"+height+"' frameborder='0' scrolling='"+scrolling+"' allowtransparency='true' src='" + source + "'>&lt/iframe>";   modalWindow.content = "<iframe width='"+width+"' height='"+height+"' frameborder='0' scrolling='"+scrolling+"' allowtransparency='"+transparency+"' src='" + source + "' style='"+style+"'></iframe>";
  modalWindow.open();   modalWindow.open();
  };   };
 // END LON-CAPA Internal -->  // END LON-CAPA Internal -->
Line 7638  ENDMODAL Line 7734  ENDMODAL
 }  }
   
 sub modal_link {  sub modal_link {
     my ($link,$linktext,$width,$height,$target,$scrolling,$title)=@_;      my ($link,$linktext,$width,$height,$target,$scrolling,$title,$transparency,$style)=@_;
     unless ($width) { $width=480; }      unless ($width) { $width=480; }
     unless ($height) { $height=400; }      unless ($height) { $height=400; }
     unless ($scrolling) { $scrolling='yes'; }      unless ($scrolling) { $scrolling='yes'; }
       unless ($transparency) { $transparency='true'; }
   
     my $target_attr;      my $target_attr;
     if (defined($target)) {      if (defined($target)) {
         $target_attr = 'target="'.$target.'"';          $target_attr = 'target="'.$target.'"';
     }      }
     return <<"ENDLINK";      return <<"ENDLINK";
 <a href="$link" $target_attr title="$title" onclick="javascript:openMyModal('$link',$width,$height,'$scrolling'); return false;">  <a href="$link" $target_attr title="$title" onclick="javascript:openMyModal('$link',$width,$height,'$scrolling','$transparency','$style'); return false;">
            $linktext</a>             $linktext</a>
 ENDLINK  ENDLINK
 }  }
Line 7675  sub modal_adhoc_inner { Line 7773  sub modal_adhoc_inner {
     my $innerwidth=$width-20;      my $innerwidth=$width-20;
     $content=&js_ready(      $content=&js_ready(
                &start_page('Dialog',undef,{'only_body'=>1,'bgcolor'=>'#FFFFFF'}).                 &start_page('Dialog',undef,{'only_body'=>1,'bgcolor'=>'#FFFFFF'}).
                  &start_scrollbox($width.'px',$innerwidth.'px',$height.'px').                   &start_scrollbox($width.'px',$innerwidth.'px',$height.'px','myModal','#FFFFFF',undef,1).
                     $content.                   $content.
                  &end_scrollbox().                   &end_scrollbox().
                &end_page()                   &end_page()
              );               );
     return &modal_adhoc_script($funcname,$width,$height,$content);      return &modal_adhoc_script($funcname,$width,$height,$content);
 }  }
Line 7895  sub validate_page { Line 7993  sub validate_page {
   
   
 sub start_scrollbox {  sub start_scrollbox {
     my ($outerwidth,$width,$height,$id,$bgcolor)=@_;      my ($outerwidth,$width,$height,$id,$bgcolor,$cursor,$needjsready) = @_;
     unless ($outerwidth) { $outerwidth='520px'; }      unless ($outerwidth) { $outerwidth='520px'; }
     unless ($width) { $width='500px'; }      unless ($width) { $width='500px'; }
     unless ($height) { $height='200px'; }      unless ($height) { $height='200px'; }
     my ($table_id,$div_id,$tdcol);      my ($table_id,$div_id,$tdcol);
     if ($id ne '') {      if ($id ne '') {
         $table_id = " id='table_$id'";          $table_id = ' id="table_'.$id.'"';
         $div_id = " id='div_$id'";          $div_id = ' id="div_'.$id.'"';
     }      }
     if ($bgcolor ne '') {      if ($bgcolor ne '') {
         $tdcol = "background-color: $bgcolor;";          $tdcol = "background-color: $bgcolor;";
     }      }
       my $nicescroll_js;
       if ($env{'browser.mobile'}) {
           $nicescroll_js = &nicescroll_javascript('div_'.$id,$cursor,$needjsready);
       }
     return <<"END";      return <<"END";
 <table style="width: $outerwidth; border: 1px solid none;"$table_id><tr><td style="width: $width;$tdcol"><div style="overflow:auto; width:$width; height: $height;"$div_id>  $nicescroll_js
   
   <table style="width: $outerwidth; border: 1px solid none;"$table_id><tr><td style="width: $width;$tdcol">
   <div style="overflow:auto; width:$width; height:$height;"$div_id>
 END  END
 }  }
   
Line 7916  sub end_scrollbox { Line 8021  sub end_scrollbox {
     return '</div></td></tr></table>';      return '</div></td></tr></table>';
 }  }
   
   sub nicescroll_javascript {
       my ($id,$cursor,$needjsready,$framecheck,$location) = @_;
       my %options;
       if (ref($cursor) eq 'HASH') {
           %options = %{$cursor};
       }
       unless ($options{'railalign'} =~ /^left|right$/) {
           $options{'railalign'} = 'left';
       }
       unless ($options{'cursorcolor'} =~ /^\#\w+$/) {
           my $function  = &get_users_function();
           $options{'cursorcolor'} = &designparm($function.'.sidebg',$env{'request.role.domain'});
           unless ($options{'cursorcolor'} =~ /^\#\w+$/) {
               $options{'cursorcolor'} = '#00F';
           }
       }
       if ($options{'cursoropacity'} =~ /^[\d.]+$/) {
           unless ($options{'cursoropacity'} >= 0.0 && $options{'cursoropacity'} <=1.0) {
               $options{'cursoropacity'}='1.0';
           }
       } else {
           $options{'cursoropacity'}='1.0';
       }
       if ($options{'cursorfixedheight'} eq 'none') {
           delete($options{'cursorfixedheight'});
       } else {
           unless ($options{'cursorfixedheight'} =~ /^\d+$/) { $options{'cursorfixedheight'}='50'; }
       }
       unless ($options{'railoffset'} =~ /^{[\w\:\d\-,]+}$/) {
           delete($options{'railoffset'});
       }
       my @niceoptions;
       while (my($key,$value) = each(%options)) {
           if ($value =~ /^\{.+\}$/) {
               push(@niceoptions,$key.':'.$value);
           } else {
               push(@niceoptions,$key.':"'.$value.'"');
           }
       }
       my $nicescroll_js = '
   $(document).ready(
         function() {
             $("#'.$id.'").niceScroll({'.join(',',@niceoptions).'});
         }
   );
   ';
       if ($framecheck) {
           $nicescroll_js .= '
   function expand_div(caller) {
       if (top === self) {
           document.getElementById("'.$id.'").style.width = "auto";
           document.getElementById("'.$id.'").style.height = "auto";
       } else {
           try {
               if (parent.frames) {
                   if (parent.frames.length > 1) {
                       var framesrc = parent.frames[1].location.href;
                       var currsrc = framesrc.replace(/\#.*$/,"");
                       if ((caller == "search") || (currsrc == "'.$location.'")) {
                           document.getElementById("'.$id.'").style.width = "auto";
                           document.getElementById("'.$id.'").style.height = "auto";
                       }
                   }
               }
           } catch (e) {
               return;
           }
       }
       return;
   }
   ';
       }
       if ($needjsready) {
           $nicescroll_js = '
   <script type="text/javascript">'."\n".$nicescroll_js."\n</script>\n";
       } else {
           $nicescroll_js = &Apache::lonhtmlcommon::scripttag($nicescroll_js);
       }
       return $nicescroll_js;
   }
   
 sub simple_error_page {  sub simple_error_page {
     my ($r,$title,$msg) = @_;      my ($r,$title,$msg,$args) = @_;
       if (ref($args) eq 'HASH') {
           if (!$args->{'no_auto_mt_msg'}) { $msg = &mt($msg); }
       } else {
           $msg = &mt($msg);
       }
   
     my $page =      my $page =
  &Apache::loncommon::start_page($title).   &Apache::loncommon::start_page($title).
  '<p class="LC_error">'.&mt($msg).'</p>'.   '<p class="LC_error">'.$msg.'</p>'.
  &Apache::loncommon::end_page();   &Apache::loncommon::end_page();
     if (ref($r)) {      if (ref($r)) {
  $r->print($page);   $r->print($page);
Line 8136  role status: active, previous or future. Line 8328  role status: active, previous or future.
 sub check_user_status {  sub check_user_status {
     my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;      my ($udom,$uname,$cdom,$crs,$role,$sec) = @_;
     my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);      my %userinfo = &Apache::lonnet::dump('roles',$udom,$uname);
     my @uroles = keys %userinfo;      my @uroles = keys(%userinfo);
     my $srchstr;      my $srchstr;
     my $active_chk = 'none';      my $active_chk = 'none';
     my $now = time;      my $now = time;
Line 8539  sub get_user_info { Line 8731  sub get_user_info {
   
 =item * &get_user_quota()  =item * &get_user_quota()
   
 Retrieves quota assigned for storage of portfolio files for a user    Retrieves quota assigned for storage of user files.
   Default is to report quota for portfolio files.
   
 Incoming parameters:  Incoming parameters:
 1. user's username  1. user's username
 2. user's domain  2. user's domain
   3. quota name - portfolio, author, or course
      (if no quota name provided, defaults to portfolio).
   4. crstype - official, unofficial, textbook or community, if quota name is
      course
   
 Returns:  Returns:
 1. Disk quota (in Mb) assigned to student.  1. Disk quota (in MB) assigned to student.
 2. (Optional) Type of setting: custom or default  2. (Optional) Type of setting: custom or default
    (individually assigned or default for user's      (individually assigned or default for user's 
    institutional status).     institutional status).
Line 8557  Returns: Line 8754  Returns:
   
 If a value has been stored in the user's environment,   If a value has been stored in the user's environment, 
 it will return that, otherwise it returns the maximal default  it will return that, otherwise it returns the maximal default
 defined for the user's instituional status(es) in the domain.  defined for the user's institutional status(es) in the domain.
   
 =cut  =cut
   
Line 8565  defined for the user's instituional stat Line 8762  defined for the user's instituional stat
   
   
 sub get_user_quota {  sub get_user_quota {
     my ($uname,$udom) = @_;      my ($uname,$udom,$quotaname,$crstype) = @_;
     my ($quota,$quotatype,$settingstatus,$defquota);      my ($quota,$quotatype,$settingstatus,$defquota);
     if (!defined($udom)) {      if (!defined($udom)) {
         $udom = $env{'user.domain'};          $udom = $env{'user.domain'};
Line 8580  sub get_user_quota { Line 8777  sub get_user_quota {
         $defquota = 0;           $defquota = 0; 
     } else {      } else {
         my $inststatus;          my $inststatus;
         if ($udom eq $env{'user.domain'} && $uname eq $env{'user.name'}) {          if ($quotaname eq 'course') {
             $quota = $env{'environment.portfolioquota'};              if (($env{'course.'.$udom.'_'.$uname.'.num'} eq $uname) &&
             $inststatus = $env{'environment.inststatus'};                  ($env{'course.'.$udom.'_'.$uname.'.domain'} eq $udom)) {
         } else {                  $quota = $env{'course.'.$udom.'_'.$uname.'.internal.uploadquota'};
             my %userenv =               } else {
                 &Apache::lonnet::get('environment',['portfolioquota',                  my %cenv = &Apache::lonnet::coursedescription("$udom/$uname");
                                      'inststatus'],$udom,$uname);                  $quota = $cenv{'internal.uploadquota'};
             my ($tmp) = keys(%userenv);              }
             if ($tmp !~ /^(con_lost|error|no_such_host)/i) {  
                 $quota = $userenv{'portfolioquota'};  
                 $inststatus = $userenv{'inststatus'};  
             } else {  
                 undef(%userenv);  
             }  
         }  
         ($defquota,$settingstatus) = &default_quota($udom,$inststatus);  
         if ($quota eq '') {  
             $quota = $defquota;  
             $quotatype = 'default';  
         } else {          } else {
             $quotatype = 'custom';              if ($udom eq $env{'user.domain'} && $uname eq $env{'user.name'}) {
                   if ($quotaname eq 'author') {
                       $quota = $env{'environment.authorquota'};
                   } else {
                       $quota = $env{'environment.portfolioquota'};
                   }
                   $inststatus = $env{'environment.inststatus'};
               } else {
                   my %userenv = 
                       &Apache::lonnet::get('environment',['portfolioquota',
                                            'authorquota','inststatus'],$udom,$uname);
                   my ($tmp) = keys(%userenv);
                   if ($tmp !~ /^(con_lost|error|no_such_host)/i) {
                       if ($quotaname eq 'author') {
                           $quota = $userenv{'authorquota'};
                       } else {
                           $quota = $userenv{'portfolioquota'};
                       }
                       $inststatus = $userenv{'inststatus'};
                   } else {
                       undef(%userenv);
                   }
               }
           }
           if ($quota eq '' || wantarray) {
               if ($quotaname eq 'course') {
                   my %domdefs = &Apache::lonnet::get_domain_defaults($udom);
                   if (($crstype eq 'official') || ($crstype eq 'unofficial') ||
                       ($crstype eq 'community') || ($crstype eq 'textbook')) {
                       $defquota = $domdefs{$crstype.'quota'};
                   }
                   if ($defquota eq '') {
                       $defquota = 500;
                   }
               } else {
                   ($defquota,$settingstatus) = &default_quota($udom,$inststatus,$quotaname);
               }
               if ($quota eq '') {
                   $quota = $defquota;
                   $quotatype = 'default';
               } else {
                   $quotatype = 'custom';
               }
         }          }
     }      }
     if (wantarray) {      if (wantarray) {
Line 8620  Retrieves default quota assigned for sto Line 8848  Retrieves default quota assigned for sto
 given an (optional) user's institutional status.  given an (optional) user's institutional status.
   
 Incoming parameters:  Incoming parameters:
   
 1. domain  1. domain
 2. (Optional) institutional status(es).  This is a : separated list of   2. (Optional) institutional status(es).  This is a : separated list of 
    status types (e.g., faculty, staff, student etc.)     status types (e.g., faculty, staff, student etc.)
    which apply to the user for whom the default is being retrieved.     which apply to the user for whom the default is being retrieved.
    If the institutional status string in undefined, the domain     If the institutional status string in undefined, the domain
    default quota will be returned.      default quota will be returned.
   3.  quota name - portfolio, author, or course
      (if no quota name provided, defaults to portfolio).
   
 Returns:  Returns:
 1. Default disk quota (in Mb) for user portfolios in the domain.  
   1. Default disk quota (in MB) for user portfolios in the domain.
 2. (Optional) institutional type which determined the value of the  2. (Optional) institutional type which determined the value of the
    default quota.     default quota.
   
 If a value has been stored in the domain's configuration db,  If a value has been stored in the domain's configuration db,
 it will return that, otherwise it returns 20 (for backwards   it will return that, otherwise it returns 20 (for backwards 
 compatibility with domains which have not set up a configuration  compatibility with domains which have not set up a configuration
 db file; the original statically defined portfolio quota was 20 Mb).   db file; the original statically defined portfolio quota was 20 MB). 
   
 If the user's status includes multiple types (e.g., staff and student),  If the user's status includes multiple types (e.g., staff and student),
 the largest default quota which applies to the user determines the  the largest default quota which applies to the user determines the
 default quota returned.  default quota returned.
   
 =back  
   
 =cut  =cut
   
 ###############################################  ###############################################
   
   
 sub default_quota {  sub default_quota {
     my ($udom,$inststatus) = @_;      my ($udom,$inststatus,$quotaname) = @_;
     my ($defquota,$settingstatus);      my ($defquota,$settingstatus);
     my %quotahash = &Apache::lonnet::get_dom('configuration',      my %quotahash = &Apache::lonnet::get_dom('configuration',
                                             ['quotas'],$udom);                                              ['quotas'],$udom);
       my $key = 'defaultquota';
       if ($quotaname eq 'author') {
           $key = 'authorquota';
       }
     if (ref($quotahash{'quotas'}) eq 'HASH') {      if (ref($quotahash{'quotas'}) eq 'HASH') {
         if ($inststatus ne '') {          if ($inststatus ne '') {
             my @statuses = map { &unescape($_); } split(/:/,$inststatus);              my @statuses = map { &unescape($_); } split(/:/,$inststatus);
             foreach my $item (@statuses) {              foreach my $item (@statuses) {
                 if (ref($quotahash{'quotas'}{'defaultquota'}) eq 'HASH') {                  if (ref($quotahash{'quotas'}{$key}) eq 'HASH') {
                     if ($quotahash{'quotas'}{'defaultquota'}{$item} ne '') {                      if ($quotahash{'quotas'}{$key}{$item} ne '') {
                         if ($defquota eq '') {                          if ($defquota eq '') {
                             $defquota = $quotahash{'quotas'}{'defaultquota'}{$item};                              $defquota = $quotahash{'quotas'}{$key}{$item};
                             $settingstatus = $item;                              $settingstatus = $item;
                         } elsif ($quotahash{'quotas'}{'defaultquota'}{$item} > $defquota) {                          } elsif ($quotahash{'quotas'}{$key}{$item} > $defquota) {
                             $defquota = $quotahash{'quotas'}{'defaultquota'}{$item};                              $defquota = $quotahash{'quotas'}{$key}{$item};
                             $settingstatus = $item;                              $settingstatus = $item;
                         }                          }
                     }                      }
                 } else {                  } elsif ($key eq 'defaultquota') {
                     if ($quotahash{'quotas'}{$item} ne '') {                      if ($quotahash{'quotas'}{$item} ne '') {
                         if ($defquota eq '') {                          if ($defquota eq '') {
                             $defquota = $quotahash{'quotas'}{$item};                              $defquota = $quotahash{'quotas'}{$item};
Line 8681  sub default_quota { Line 8915  sub default_quota {
             }              }
         }          }
         if ($defquota eq '') {          if ($defquota eq '') {
             if (ref($quotahash{'quotas'}{'defaultquota'}) eq 'HASH') {              if (ref($quotahash{'quotas'}{$key}) eq 'HASH') {
                 $defquota = $quotahash{'quotas'}{'defaultquota'}{'default'};                  $defquota = $quotahash{'quotas'}{$key}{'default'};
             } else {              } elsif ($key eq 'defaultquota') {
                 $defquota = $quotahash{'quotas'}{'default'};                  $defquota = $quotahash{'quotas'}{'default'};
             }              }
             $settingstatus = 'default';              $settingstatus = 'default';
               if ($defquota eq '') {
                   if ($quotaname eq 'author') {
                       $defquota = 500;
                   }
               }
         }          }
     } else {      } else {
         $settingstatus = 'default';          $settingstatus = 'default';
         $defquota = 20;          if ($quotaname eq 'author') {
               $defquota = 500;
           } else {
               $defquota = 20;
           }
     }      }
     if (wantarray) {      if (wantarray) {
         return ($defquota,$settingstatus);          return ($defquota,$settingstatus);
Line 8699  sub default_quota { Line 8942  sub default_quota {
     }      }
 }  }
   
   ###############################################
   
   =pod
   
   =item * &excess_filesize_warning()
   
   Returns warning message if upload of file to authoring space, or copying
   of existing file within authoring space will cause quota for the authoring
   space to be exceeded.
   
   Same, if upload of a file directly to a course/community via Course Editor
   will cause quota for uploaded content for the course to be exceeded.
   
   Inputs: 7 
   1. username or coursenum
   2. domain
   3. context ('author' or 'course')
   4. filename of file for which action is being requested
   5. filesize (kB) of file
   6. action being taken: copy or upload.
   7. quotatype (in course context -- official, unofficial, community or textbook).
   
   Returns: 1 scalar: HTML to display containing warning if quota would be exceeded,
            otherwise return null.
   
   =back
   
   =cut
   
   sub excess_filesize_warning {
       my ($uname,$udom,$context,$filename,$filesize,$action,$quotatype) = @_;
       my $current_disk_usage = 0;
       my $disk_quota = &get_user_quota($uname,$udom,$context,$quotatype); #expressed in MB
       if ($context eq 'author') {
           my $authorspace = $Apache::lonnet::perlvar{'lonDocRoot'}."/priv/$udom/$uname";
           $current_disk_usage = &Apache::lonnet::diskusage($udom,$uname,$authorspace);
       } else {
           foreach my $subdir ('docs','supplemental') {
               $current_disk_usage += &Apache::lonnet::diskusage($udom,$uname,"userfiles/$subdir",1);
           }
       }
       $disk_quota = int($disk_quota * 1000);
       if (($current_disk_usage + $filesize) > $disk_quota) {
           return '<p class="LC_warning">'.
                   &mt("Unable to $action [_1]. (size = [_2] kilobytes). Disk quota will be exceeded.",
                       '<span class="LC_filename">'.$filename.'</span>',$filesize).'</p>'.
                  '<p>'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',
                               $disk_quota,$current_disk_usage).
                  '</p>';
       }
       return;
   }
   
   ###############################################
   
   
 sub get_secgrprole_info {  sub get_secgrprole_info {
     my ($cdom,$cnum,$needroles,$type)  = @_;      my ($cdom,$cnum,$needroles,$type)  = @_;
     my %sections_count = &get_sections($cdom,$cnum);      my %sections_count = &get_sections($cdom,$cnum);
Line 9140  sub personal_data_fieldtitles { Line 9439  sub personal_data_fieldtitles {
   
 sub sorted_inst_types {  sub sorted_inst_types {
     my ($dom) = @_;      my ($dom) = @_;
     my ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($dom);      my ($usertypes,$order);
       my %domdefaults = &Apache::lonnet::get_domain_defaults($dom);
       if (ref($domdefaults{'inststatus'}) eq 'HASH') {
           $usertypes = $domdefaults{'inststatus'}{'inststatustypes'};
           $order = $domdefaults{'inststatus'}{'inststatusorder'};
       } else {
           ($usertypes,$order) = &Apache::lonnet::retrieve_inst_usertypes($dom);
       }
     my $othertitle = &mt('All users');      my $othertitle = &mt('All users');
     if ($env{'request.course.id'}) {      if ($env{'request.course.id'}) {
         $othertitle  = &mt('Any users');          $othertitle  = &mt('Any users');
Line 9538  sub ask_for_embedded_content { Line 9844  sub ask_for_embedded_content {
     my $numexisting = 0;      my $numexisting = 0;
     my $numunused = 0;      my $numunused = 0;
     my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath,$cdom,$cnum,      my ($output,$upload_output,$toplevel,$url,$udom,$uname,$getpropath,$cdom,$cnum,
         $fileloc,$filename,$delete_output,$modify_output,$title,$symb,$path);          $fileloc,$filename,$delete_output,$modify_output,$title,$symb,$path,$navmap);
     my $heading = &mt('Upload embedded files');      my $heading = &mt('Upload embedded files');
     my $buttontext = &mt('Upload');      my $buttontext = &mt('Upload');
   
     my ($navmap,$cdom,$cnum);  
     if ($env{'request.course.id'}) {      if ($env{'request.course.id'}) {
         if ($actionurl eq '/adm/dependencies') {          if ($actionurl eq '/adm/dependencies') {
             $navmap = Apache::lonnavmaps::navmap->new();              $navmap = Apache::lonnavmaps::navmap->new();
Line 9604  sub ask_for_embedded_content { Line 9909  sub ask_for_embedded_content {
                     ($path) =                      ($path) =
                         ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/(?:default|\d+)/\d+)/});                          ($toplevel =~ m{^(\Q/uploaded/$cdom/$cnum/\E(?:docs|supplemental)/(?:default|\d+)/\d+)/});
                 }                  }
                 $fileloc = &Apache::lonnet::filelocation('',$toplevel);                  if ($toplevel=~/^\/*(uploaded|editupload)/) {
                       $fileloc = $toplevel;
                       $fileloc=~ s/^\s*(\S+)\s*$/$1/;
                       my ($udom,$uname,$fname) =
                           ($fileloc=~ m{^/+(?:uploaded|editupload)/+($match_domain)/+($match_name)/+(.*)$});
                       $fileloc = propath($udom,$uname).'/userfiles/'.$fname;
                   } else {
                       $fileloc = &Apache::lonnet::filelocation('',$toplevel);
                   }
                 $fileloc =~ s{^/}{};                  $fileloc =~ s{^/}{};
                 ($filename) = ($fileloc =~ m{.+/([^/]+)$});                  ($filename) = ($fileloc =~ m{.+/([^/]+)$});
                 $heading = &mt('Status of dependencies in [_1]',"$title ($filename)");                  $heading = &mt('Status of dependencies in [_1]',"$title ($filename)");
Line 9619  sub ask_for_embedded_content { Line 9932  sub ask_for_embedded_content {
         $fileloc = &Apache::lonnet::filelocation('',$toplevel).'/';          $fileloc = &Apache::lonnet::filelocation('',$toplevel).'/';
         $fileloc =~ s{^/}{};          $fileloc =~ s{^/}{};
     }      }
     }  
     foreach my $file (keys(%{$allfiles})) {      foreach my $file (keys(%{$allfiles})) {
         my $embed_file;          my $embed_file;
         if (($path eq "/uploaded/$cdom/$cnum/portfolio/syllabus") && ($file =~ m{^\Q$path/\E(.+)$})) {          if (($path eq "/uploaded/$cdom/$cnum/portfolio/syllabus") && ($file =~ m{^\Q$path/\E(.+)$})) {
Line 9627  sub ask_for_embedded_content { Line 9939  sub ask_for_embedded_content {
         } else {          } else {
             $embed_file = $file;              $embed_file = $file;
         }          }
         my $absolutepath;          my ($absolutepath,$cleaned_file);
         if ($embed_file =~ m{^\w+://}) {          if ($embed_file =~ m{^\w+://}) {
             $newfiles{$embed_file} = 1;              $cleaned_file = $embed_file;
             $mapping{$embed_file} = $embed_file;              $newfiles{$cleaned_file} = 1;
               $mapping{$cleaned_file} = $embed_file;
         } else {          } else {
               $cleaned_file = &clean_path($embed_file);
             if ($embed_file =~ m{^/}) {              if ($embed_file =~ m{^/}) {
                 $absolutepath = $embed_file;                  $absolutepath = $embed_file;
                 $embed_file =~ s{^(/+)}{};  
             }              }
             if ($embed_file =~ m{/}) {              if ($cleaned_file =~ m{/}) {
                 my ($path,$fname) = ($embed_file =~ m{^(.+)/([^/]*)$});                  my ($path,$fname) = ($cleaned_file =~ m{^(.+)/([^/]*)$});
                 $path = &check_for_traversal($path,$url,$toplevel);                  $path = &check_for_traversal($path,$url,$toplevel);
                 my $item = $fname;                  my $item = $fname;
                 if ($path ne '') {                  if ($path ne '') {
Line 9654  sub ask_for_embedded_content { Line 9967  sub ask_for_embedded_content {
             } else {              } else {
                 $dependencies{$embed_file} = 1;                  $dependencies{$embed_file} = 1;
                 if ($absolutepath) {                  if ($absolutepath) {
                     $mapping{$embed_file} = $absolutepath;                      $mapping{$cleaned_file} = $absolutepath;
                 } else {                  } else {
                     $mapping{$embed_file} = $embed_file;                      $mapping{$cleaned_file} = $embed_file;
                 }                  }
             }              }
         }          }
Line 10030  sub ask_for_embedded_content { Line 10343  sub ask_for_embedded_content {
     return ($output,$counter,$numpathchg);      return ($output,$counter,$numpathchg);
 }  }
   
   =pod
   
   =item * clean_path($name)
   
   Performs clean-up of directories, subdirectories and filename in an
   embedded object, referenced in an HTML file which is being uploaded
   to a course or portfolio, where
   "Upload embedded images/multimedia files if HTML file" checkbox was
   checked.
   
   Clean-up is similar to replacements in lonnet::clean_filename()
   except each / between sub-directory and next level is preserved.
   
   =cut
   
   sub clean_path {
       my ($embed_file) = @_;
       $embed_file =~s{^/+}{};
       my @contents;
       if ($embed_file =~ m{/}) {
           @contents = split(/\//,$embed_file);
       } else {
           @contents = ($embed_file);
       }
       my $lastidx = scalar(@contents)-1;
       for (my $i=0; $i<=$lastidx; $i++) {
           $contents[$i]=~s{\\}{/}g;
           $contents[$i]=~s/\s+/\_/g;
           $contents[$i]=~s{[^/\w\.\-]}{}g;
           if ($i == $lastidx) {
               $contents[$i]=~s/\.(\d+)(?=\.)/_$1/g;
           }
       }
       if ($lastidx > 0) {
           return join('/',@contents);
       } else {
           return $contents[0];
       }
   }
   
 sub embedded_file_element {  sub embedded_file_element {
     my ($context,$num,$embed_file,$mapping,$allfiles,$codebase,$type) = @_;      my ($context,$num,$embed_file,$mapping,$allfiles,$codebase,$type) = @_;
     return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') &&      return unless ((ref($mapping) eq 'HASH') && (ref($allfiles) eq 'HASH') &&
Line 10154  sub upload_embedded { Line 10507  sub upload_embedded {
         # Check if extension is valid          # Check if extension is valid
         if (($fname =~ /\.(\w+)$/) &&          if (($fname =~ /\.(\w+)$/) &&
             (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {              (&Apache::loncommon::fileembstyle($1) eq 'hdn')) {
             $output .= &mt('Invalid file extension ([_1]) - reserved for LONCAPA use - rename the file with a different extension and re-upload. ',$1).'<br />';              $output .= &mt('Invalid file extension ([_1]) - reserved for internal use.',$1)
                         .' '.&mt('Rename the file with a different extension and re-upload.').'<br />';
             next;              next;
         } elsif (($fname =~ /\.(\w+)$/) &&          } elsif (($fname =~ /\.(\w+)$/) &&
                  (!defined(&Apache::loncommon::fileembstyle($1)))) {                   (!defined(&Apache::loncommon::fileembstyle($1)))) {
Line 10418  sub modify_html_refs { Line 10772  sub modify_html_refs {
                         my $numchg = ($content =~ s{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);                          my $numchg = ($content =~ s{($attrib_regexp\s*=\s*['"]?)\Q$ref\E(['"]?)}{$1$newname$2}gi);
                         $count += $numchg;                          $count += $numchg;
                         $allfiles{$newname} = $allfiles{$ref};                          $allfiles{$newname} = $allfiles{$ref};
                           delete($allfiles{$ref});
                     }                      }
                     if ($env{'form.embedded_codebase_'.$i} ne '') {                      if ($env{'form.embedded_codebase_'.$i} ne '') {
                         $codebase = &unescape($env{'form.embedded_codebase_'.$i});                          $codebase = &unescape($env{'form.embedded_codebase_'.$i});
Line 10593  sub check_for_upload { Line 10948  sub check_for_upload {
                     if ($currsize < $filesize) {                      if ($currsize < $filesize) {
                         my $extra = $filesize - $currsize;                          my $extra = $filesize - $currsize;
                         if (($current_disk_usage + $extra) > $disk_quota) {                          if (($current_disk_usage + $extra) > $disk_quota) {
                             my $msg = '<span class="LC_error">'.                              my $msg = '<p class="LC_warning">'.
                                       &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.',                                        &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded if existing (smaller) file with same name (size = [_3] kilobytes) is replaced.',
                                           '<span class="LC_filename">'.$fname.'</span>',$filesize,$currsize).'</span>'.                                            '<span class="LC_filename">'.$fname.'</span>',$filesize,$currsize).'</p>'.
                                       '<br />'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',                                        '<p>'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',
                                                    $disk_quota,$current_disk_usage);                                                     $disk_quota,$current_disk_usage).'</p>';
                             return ('will_exceed_quota',$msg);                              return ('will_exceed_quota',$msg);
                         }                          }
                     }                      }
Line 10606  sub check_for_upload { Line 10961  sub check_for_upload {
         }          }
     }      }
     if (($current_disk_usage + $filesize) > $disk_quota){      if (($current_disk_usage + $filesize) > $disk_quota){
         my $msg = '<span class="LC_error">'.          my $msg = '<p class="LC_warning">'.
                 &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded.','<span class="LC_filename">'.$fname.'</span>',$filesize).'</span>'.                  &mt('Unable to upload [_1]. (size = [_2] kilobytes). Disk quota will be exceeded.','<span class="LC_filename">'.$fname.'</span>',$filesize).'</p>'.
                   '<br />'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',$disk_quota,$current_disk_usage);                    '<p>'.&mt('Disk quota is [_1] kilobytes. Your current disk usage is [_2] kilobytes.',$disk_quota,$current_disk_usage).'</p>';
         return ('will_exceed_quota',$msg);          return ('will_exceed_quota',$msg);
     } elsif ($found_file) {      } elsif ($found_file) {
         if ($locked_file) {          if ($locked_file) {
             my $msg = '<span class="LC_error">';              my $msg = '<p class="LC_warning">';
             $msg .= &mt('Unable to upload [_1]. A locked file by that name was found in [_2].','<span class="LC_filename">'.$fname.'</span>','<span class="LC_filename">'.$port_path.$env{'form.currentpath'}.'</span>');              $msg .= &mt('Unable to upload [_1]. A locked file by that name was found in [_2].','<span class="LC_filename">'.$fname.'</span>','<span class="LC_filename">'.$port_path.$env{'form.currentpath'}.'</span>');
             $msg .= '</span><br />';              $msg .= '</p>';
             $msg .= &mt('You will be able to rename or delete existing [_1] after a grade has been assigned.','<span class="LC_filename">'.$fname.'</span>');              $msg .= &mt('You will be able to rename or delete existing [_1] after a grade has been assigned.','<span class="LC_filename">'.$fname.'</span>');
             return ('file_locked',$msg);              return ('file_locked',$msg);
         } else {          } else {
             my $msg = '<span class="LC_error">';              my $msg = '<p class="LC_error">';
             $msg .= &mt(' A file by that name: [_1] was found in [_2].','<span class="LC_filename">'.$fname.'</span>',$port_path.$env{'form.currentpath'});              $msg .= &mt(' A file by that name: [_1] was found in [_2].','<span class="LC_filename">'.$fname.'</span>',$port_path.$env{'form.currentpath'});
             $msg .= '</span>';              $msg .= '</p>';
             return ('existingfile',$msg);              return ('existingfile',$msg);
         }          }
     }      }
Line 10711  sub decompress_form { Line 11066  sub decompress_form {
         }          }
     }      }
     if ($mimetype =~ m{^application/(x\-)?(compressed|zip)}) {      if ($mimetype =~ m{^application/(x\-)?(compressed|zip)}) {
         my @camtasia = ("$topdir/","$topdir/index.html",          my @camtasia6 = ("$topdir/","$topdir/index.html",
                         "$topdir/media/",                          "$topdir/media/",
                         "$topdir/media/$topdir.mp4",                          "$topdir/media/$topdir.mp4",
                         "$topdir/media/FirstFrame.png",                          "$topdir/media/FirstFrame.png",
                         "$topdir/media/player.swf",                          "$topdir/media/player.swf",
                         "$topdir/media/swfobject.js",                          "$topdir/media/swfobject.js",
                         "$topdir/media/expressInstall.swf");                          "$topdir/media/expressInstall.swf");
         my @diffs = &compare_arrays(\@paths,\@camtasia);          my @camtasia8_1 = ("$topdir/","$topdir/$topdir.html",
                            "$topdir/$topdir.mp4",
                            "$topdir/$topdir\_config.xml",
                            "$topdir/$topdir\_controller.swf",
                            "$topdir/$topdir\_embed.css",
                            "$topdir/$topdir\_First_Frame.png",
                            "$topdir/$topdir\_player.html",
                            "$topdir/$topdir\_Thumbnails.png",
                            "$topdir/playerProductInstall.swf",
                            "$topdir/scripts/",
                            "$topdir/scripts/config_xml.js",
                            "$topdir/scripts/handlebars.js",
                            "$topdir/scripts/jquery-1.7.1.min.js",
                            "$topdir/scripts/jquery-ui-1.8.15.custom.min.js",
                            "$topdir/scripts/modernizr.js",
                            "$topdir/scripts/player-min.js",
                            "$topdir/scripts/swfobject.js",
                            "$topdir/skins/",
                            "$topdir/skins/configuration_express.xml",
                            "$topdir/skins/express_show/",
                            "$topdir/skins/express_show/player-min.css",
                            "$topdir/skins/express_show/spritesheet.png");
           my @camtasia8_4 = ("$topdir/","$topdir/$topdir.html",
                            "$topdir/$topdir.mp4",
                            "$topdir/$topdir\_config.xml",
                            "$topdir/$topdir\_controller.swf",
                            "$topdir/$topdir\_embed.css",
                            "$topdir/$topdir\_First_Frame.png",
                            "$topdir/$topdir\_player.html",
                            "$topdir/$topdir\_Thumbnails.png",
                            "$topdir/playerProductInstall.swf",
                            "$topdir/scripts/",
                            "$topdir/scripts/config_xml.js",
                            "$topdir/scripts/techsmith-smart-player.min.js",
                            "$topdir/skins/",
                            "$topdir/skins/configuration_express.xml",
                            "$topdir/skins/express_show/",
                            "$topdir/skins/express_show/spritesheet.min.css",
                            "$topdir/skins/express_show/spritesheet.png",
                            "$topdir/skins/express_show/techsmith-smart-player.min.css");
           my @diffs = &compare_arrays(\@paths,\@camtasia6);
         if (@diffs == 0) {          if (@diffs == 0) {
             $is_camtasia = 1;              $is_camtasia = 6;
           } else {
               @diffs = &compare_arrays(\@paths,\@camtasia8_1);
               if (@diffs == 0) {
                   $is_camtasia = 8;
               } else {
                   @diffs = &compare_arrays(\@paths,\@camtasia8_4);
                   if (@diffs == 0) {
                       $is_camtasia = 8;
                   }
               }
         }          }
     }      }
     my $output;      my $output;
Line 10732  sub decompress_form { Line 11137  sub decompress_form {
 function camtasiaToggle() {  function camtasiaToggle() {
     for (var i=0; i<document.uploaded_decompress.autoextract_camtasia.length; i++) {      for (var i=0; i<document.uploaded_decompress.autoextract_camtasia.length; i++) {
         if (document.uploaded_decompress.autoextract_camtasia[i].checked) {          if (document.uploaded_decompress.autoextract_camtasia[i].checked) {
             if (document.uploaded_decompress.autoextract_camtasia[i].value == 1) {              if (document.uploaded_decompress.autoextract_camtasia[i].value == $is_camtasia) {
   
                 document.getElementById('camtasia_titles').style.display='block';                  document.getElementById('camtasia_titles').style.display='block';
             } else {              } else {
                 document.getElementById('camtasia_titles').style.display='none';                  document.getElementById('camtasia_titles').style.display='none';
Line 10795  ENDCAM Line 11199  ENDCAM
     if ($is_camtasia) {      if ($is_camtasia) {
         $output .= $lt{'auto'}.'<br />'.          $output .= $lt{'auto'}.'<br />'.
                    '<span class="LC_nobreak">'.$lt{'proa'}.'<label>'.                     '<span class="LC_nobreak">'.$lt{'proa'}.'<label>'.
                    '<input type="radio" name="autoextract_camtasia" value="1" onclick="javascript:camtasiaToggle();" checked="checked" />'.                     '<input type="radio" name="autoextract_camtasia" value="'.$is_camtasia.'" onclick="javascript:camtasiaToggle();" checked="checked" />'.
                    $lt{'yes'}.'</label>&nbsp;<label>'.                     $lt{'yes'}.'</label>&nbsp;<label>'.
                    '<input type="radio" name="autoextract_camtasia" value="0" onclick="javascript:camtasiaToggle();" />'.                     '<input type="radio" name="autoextract_camtasia" value="0" onclick="javascript:camtasiaToggle();" />'.
                    $lt{'no'}.'</label></span><br />'.                     $lt{'no'}.'</label></span><br />'.
Line 10918  sub decompress_uploaded_file { Line 11322  sub decompress_uploaded_file {
 sub process_decompression {  sub process_decompression {
     my ($docudom,$docuname,$file,$destination,$dir_root,$hiddenelem) = @_;      my ($docudom,$docuname,$file,$destination,$dir_root,$hiddenelem) = @_;
     my ($dir,$error,$warning,$output);      my ($dir,$error,$warning,$output);
     if ($file !~ /\.(zip|tar|bz2|gz|tar.gz|tar.bz2|tgz)$/) {      if ($file !~ /\.(zip|tar|bz2|gz|tar.gz|tar.bz2|tgz)$/i) {
         $error = &mt('Filename not a supported archive file type.').          $error = &mt('Filename not a supported archive file type.').
                  '<br />'.&mt('Filename should end with one of: [_1].',                   '<br />'.&mt('Filename should end with one of: [_1].',
                               '.zip, .tar, .bz2, .gz, .tar.gz, .tar.bz2, .tgz');                                '.zip, .tar, .bz2, .gz, .tar.gz, .tar.bz2, .tgz');
Line 11028  sub process_decompression { Line 11432  sub process_decompression {
                                                            \%titles,\%children);                                                             \%titles,\%children);
                         }                          }
                         if ($env{'form.autoextract_camtasia'}) {                          if ($env{'form.autoextract_camtasia'}) {
                               my $version = $env{'form.autoextract_camtasia'};
                             my %displayed;                              my %displayed;
                             my $total = 1;                              my $total = 1;
                             $env{'form.archive_directory'} = [];                              $env{'form.archive_directory'} = [];
Line 11046  sub process_decompression { Line 11451  sub process_decompression {
                                     $env{'form.archive_'.$i} = 'display';                                      $env{'form.archive_'.$i} = 'display';
                                     $env{'form.archive_title_'.$i} = $env{'form.camtasia_foldername'};                                      $env{'form.archive_title_'.$i} = $env{'form.camtasia_foldername'};
                                     $displayed{'folder'} = $i;                                      $displayed{'folder'} = $i;
                                 } elsif ($item eq "$contents[0]/index.html") {                                  } elsif ((($item eq "$contents[0]/index.html") && ($version == 6)) ||
                                            (($item eq "$contents[0]/$contents[0]".'.html') && ($version == 8))) {
                                     $env{'form.archive_'.$i} = 'display';                                      $env{'form.archive_'.$i} = 'display';
                                     $env{'form.archive_title_'.$i} = $env{'form.camtasia_moviename'};                                      $env{'form.archive_title_'.$i} = $env{'form.camtasia_moviename'};
                                     $displayed{'web'} = $i;                                      $displayed{'web'} = $i;
                                 } else {                                  } else {
                                     if ($item eq "$contents[0]/media") {                                      if ((($item eq "$contents[0]/media") && ($version == 6)) ||
                                           ((($item eq "$contents[0]/scripts") || ($item eq "$contents[0]/skins") ||
                                                ($item eq "$contents[0]/skins/express_show")) && ($version == 8))) {
                                         push(@{$env{'form.archive_directory'}},$i);                                          push(@{$env{'form.archive_directory'}},$i);
                                     }                                      }
                                     $env{'form.archive_'.$i} = 'dependency';                                      $env{'form.archive_'.$i} = 'dependency';
Line 11778  sub cleanup_empty_dirs { Line 12186  sub cleanup_empty_dirs {
   
 =pod  =pod
   
 =item &get_folder_hierarchy()  =item * &get_folder_hierarchy()
   
 Provides hierarchy of names of folders/sub-folders containing the current  Provides hierarchy of names of folders/sub-folders containing the current
 item,  item,
Line 11806  sub get_folder_hierarchy { Line 12214  sub get_folder_hierarchy {
                 my @pcs = split(/,/,$pcslist);                  my @pcs = split(/,/,$pcslist);
                 foreach my $pc (@pcs) {                  foreach my $pc (@pcs) {
                     if ($pc == 1) {                      if ($pc == 1) {
                         push(@pathitems,&mt('Main Course Documents'));                          push(@pathitems,&mt('Main Content'));
                     } else {                      } else {
                         my $res = $navmap->getByMapPc($pc);                          my $res = $navmap->getByMapPc($pc);
                         if (ref($res)) {                          if (ref($res)) {
Line 11821  sub get_folder_hierarchy { Line 12229  sub get_folder_hierarchy {
             }              }
             if ($showitem) {              if ($showitem) {
                 if ($mapres->{ID} eq '0.0') {                  if ($mapres->{ID} eq '0.0') {
                     push(@pathitems,&mt('Main Course Documents'));                      push(@pathitems,&mt('Main Content'));
                 } else {                  } else {
                     my $maptitle = $mapres->compTitle();                      my $maptitle = $mapres->compTitle();
                     $maptitle =~ s/\W+/_/g;                      $maptitle =~ s/\W+/_/g;
Line 11888  sub get_turnedin_filepath { Line 12296  sub get_turnedin_filepath {
                             my $title = $res->compTitle();                              my $title = $res->compTitle();
                             $title =~ s/\W+/_/g;                              $title =~ s/\W+/_/g;
                             if ($title ne '') {                              if ($title ne '') {
                                   if (($pc > 1) && (length($title) > 12)) {
                                       $title = substr($title,0,12);
                                   }
                                 push(@pathitems,$title);                                  push(@pathitems,$title);
                             }                              }
                         }                          }
Line 11896  sub get_turnedin_filepath { Line 12307  sub get_turnedin_filepath {
                 my $maptitle = $mapres->compTitle();                  my $maptitle = $mapres->compTitle();
                 $maptitle =~ s/\W+/_/g;                  $maptitle =~ s/\W+/_/g;
                 if ($maptitle ne '') {                  if ($maptitle ne '') {
                       if (length($maptitle) > 12) {
                           $maptitle = substr($maptitle,0,12);
                       }
                     push(@pathitems,$maptitle);                      push(@pathitems,$maptitle);
                 }                  }
                 unless ($env{'request.state'} eq 'construct') {                  unless ($env{'request.state'} eq 'construct') {
Line 11936  sub get_turnedin_filepath { Line 12350  sub get_turnedin_filepath {
                 $restitle = time;                  $restitle = time;
             }              }
         }          }
           if (length($restitle) > 12) {
               $restitle = substr($restitle,0,12);
           }
         push(@pathitems,$restitle);          push(@pathitems,$restitle);
         $path .= join('/',@pathitems);          $path .= join('/',@pathitems);
     }      }
Line 12873  sub restore_settings { Line 13290  sub restore_settings {
   
 =item * &build_recipient_list()  =item * &build_recipient_list()
   
 Build recipient lists for five types of e-mail:  Build recipient lists for following types of e-mail:
 (a) Error Reports, (b) Package Updates, (c) lonstatus warnings/errors  (a) Error Reports, (b) Package Updates, (c) lonstatus warnings/errors
 (d) Help requests, (e) Course requests needing approval,  generated by  (d) Help requests, (e) Course requests needing approval, (f) loncapa
 lonerrorhandler.pm, CHECKRPMS, loncron, lonsupportreq.pm and  module change checking, student/employee ID conflict checks, as
 loncoursequeueadmin.pm respectively.  generated by lonerrorhandler.pm, CHECKRPMS, loncron,
   lonsupportreq.pm, loncoursequeueadmin.pm, searchcat.pl respectively.
   
 Inputs:  Inputs:
 defmail (scalar - email address of default recipient),   defmail (scalar - email address of default recipient),
 mailing type (scalar - errormail, packagesmail, or helpdeskmail),   mailing type (scalar: errormail, packagesmail, helpdeskmail,
   requestsmail, updatesmail, or idconflictsmail).
   
 defdom (domain for which to retrieve configuration settings),  defdom (domain for which to retrieve configuration settings),
 origmail (scalar - email address of recipient from loncapa.conf,   
 i.e., predates configuration by DC via domainprefs.pm   origmail (scalar - email address of recipient from loncapa.conf,
   i.e., predates configuration by DC via domainprefs.pm
   
 Returns: comma separated list of addresses to which to send e-mail.  Returns: comma separated list of addresses to which to send e-mail.
   
Line 13078  sub extract_categories { Line 13499  sub extract_categories {
   
 =pod  =pod
   
 =item *&recurse_categories()  =item * &recurse_categories()
   
 Recursively used to generate breadcrumb trails for course categories.  Recursively used to generate breadcrumb trails for course categories.
   
Line 13149  sub recurse_categories { Line 13570  sub recurse_categories {
   
 =pod  =pod
   
 =item *&assign_categories_table()  =item * &assign_categories_table()
   
 Create a datatable for display of hierarchical categories in a domain,  Create a datatable for display of hierarchical categories in a domain,
 with checkboxes to allow a course to be categorized.   with checkboxes to allow a course to be categorized. 
Line 13226  sub assign_categories_table { Line 13647  sub assign_categories_table {
   
 =pod  =pod
   
 =item *&assign_category_rows()  =item * &assign_category_rows()
   
 Create a datatable row for display of nested categories in a domain,  Create a datatable row for display of nested categories in a domain,
 with checkboxes to allow a course to be categorized,called recursively.  with checkboxes to allow a course to be categorized,called recursively.
Line 13260  sub assign_category_rows { Line 13681  sub assign_category_rows {
             if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {              if (ref($cats->[$depth]{$parent}) eq 'ARRAY') {
                 my $numchildren = @{$cats->[$depth]{$parent}};                  my $numchildren = @{$cats->[$depth]{$parent}};
                 my $css_class = $itemcount%2?' class="LC_odd_row"':'';                  my $css_class = $itemcount%2?' class="LC_odd_row"':'';
                 $text .= '<td><table class="LC_datatable">';                  $text .= '<td><table class="LC_data_table">';
                 for (my $j=0; $j<$numchildren; $j++) {                  for (my $j=0; $j<$numchildren; $j++) {
                     $name = $cats->[$depth]{$parent}[$j];                      $name = $cats->[$depth]{$parent}[$j];
                     $item = &escape($name).':'.&escape($parent).':'.$depth;                      $item = &escape($name).':'.&escape($parent).':'.$depth;
Line 13292  sub assign_category_rows { Line 13713  sub assign_category_rows {
     return $text;      return $text;
 }  }
   
   =pod
   
   =back
   
   =cut
   
 ############################################################  ############################################################
 ############################################################  ############################################################
   
Line 13544  sub check_clone { Line 13971  sub check_clone {
 }  }
   
 sub construct_course {  sub construct_course {
     my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname,$context,$cnum,$category) = @_;      my ($args,$logmsg,$courseid,$crsudom,$crsunum,$udom,$uname,$context,$cnum,$category,$coderef) = @_;
     my $outcome;      my $outcome;
     my $linefeed =  '<br />'."\n";      my $linefeed =  '<br />'."\n";
     if ($context eq 'auto') {      if ($context eq 'auto') {
Line 13641  sub construct_course { Line 14068  sub construct_course {
                    'plc.users.denied',                     'plc.users.denied',
                    'hidefromcat',                     'hidefromcat',
                    'checkforpriv',                     'checkforpriv',
                    'categories'],                     'categories',
                      'internal.uniquecode'],
                    $$crsudom,$$crsunum);                     $$crsudom,$$crsunum);
           if ($args->{'textbook'}) {
               $cenv{'internal.textbook'} = $args->{'textbook'};
           }
     }      }
   
 #  #
Line 13826  sub construct_course { Line 14257  sub construct_course {
  }   }
     }      }
   
   #
   #  generate and store uniquecode (available to course requester), if course should have one.
   #
       if ($args->{'uniquecode'}) {
           my ($code,$error) = &make_unique_code($$crsudom,$$crsunum);
           if ($code) {
               $cenv{'internal.uniquecode'} = $code;
               my %crsinfo =
                   &Apache::lonnet::courseiddump($$crsudom,'.',1,'.','.',$$crsunum,undef,undef,'.');
               if (ref($crsinfo{$$crsudom.'_'.$$crsunum}) eq 'HASH') {
                   $crsinfo{$$crsudom.'_'.$$crsunum}{'uniquecode'} = $code;
                   my $putres = &Apache::lonnet::courseidput($$crsudom,\%crsinfo,$crsuhome,'notime');
               }
               if (ref($coderef)) {
                   $$coderef = $code;
               }
           }
       }
   
     if ($args->{'disresdis'}) {      if ($args->{'disresdis'}) {
         $cenv{'pch.roles.denied'}='st';          $cenv{'pch.roles.denied'}='st';
     }      }
Line 13894  sub construct_course { Line 14344  sub construct_course {
     return (1,$outcome);      return (1,$outcome);
 }  }
   
   sub make_unique_code {
       my ($cdom,$cnum) = @_;
       # get lock on uniquecodes db
       my $lockhash = {
                         $cnum."\0".'uniquecodes' => $env{'user.name'}.
                                                     ':'.$env{'user.domain'},
                      };
       my $tries = 0;
       my $gotlock = &Apache::lonnet::newput_dom('uniquecodes',$lockhash,$cdom);
       my ($code,$error);
   
       while (($gotlock ne 'ok') && ($tries<3)) {
           $tries ++;
           sleep 1;
           $gotlock = &Apache::lonnet::newput_dom('uniquecodes',$lockhash,$cdom);
       }
       if ($gotlock eq 'ok') {
           my %currcodes = &Apache::lonnet::dump_dom('uniquecodes',$cdom);
           my $gotcode;
           my $attempts = 0;
           while ((!$gotcode) && ($attempts < 100)) {
               $code = &generate_code();
               if (!exists($currcodes{$code})) {
                   $gotcode = 1;
                   unless (&Apache::lonnet::newput_dom('uniquecodes',{ $code => $cnum },$cdom) eq 'ok') {
                       $error = 'nostore';
                   }
               }
               $attempts ++;
           }
           my @del_lock = ($cnum."\0".'uniquecodes');
           my $dellockoutcome = &Apache::lonnet::del_dom('uniquecodes',\@del_lock,$cdom);
       } else {
           $error = 'nolock';
       }
       return ($code,$error);
   }
   
   sub generate_code {
       my $code;
       my @letts = qw(B C D G H J K M N P Q R S T V W X Z);
       for (my $i=0; $i<6; $i++) {
           my $lettnum = int (rand 2);
           my $item = '';
           if ($lettnum) {
               $item = $letts[int( rand(18) )];
           } else {
               $item = 1+int( rand(8) );
           }
           $code .= $item;
       }
       return $code;
   }
   
 ############################################################  ############################################################
 ############################################################  ############################################################
   
Line 13921  sub group_term { Line 14425  sub group_term {
 }  }
   
 sub course_types {  sub course_types {
     my @types = ('official','unofficial','community');      my @types = ('official','unofficial','community','textbook');
     my %typename = (      my %typename = (
                          official   => 'Official course',                           official   => 'Official course',
                          unofficial => 'Unofficial course',                           unofficial => 'Unofficial course',
                          community  => 'Community',                           community  => 'Community',
                            textbook   => 'Textbook course',
                    );                     );
     return (\@types,\%typename);      return (\@types,\%typename);
 }  }
Line 13986  sub escape_url { Line 14491  sub escape_url {
     my ($url)   = @_;      my ($url)   = @_;
     my @urlslices = split(/\//, $url,-1);      my @urlslices = split(/\//, $url,-1);
     my $lastitem = &escape(pop(@urlslices));      my $lastitem = &escape(pop(@urlslices));
     return join('/',@urlslices).'/'.$lastitem;      return &HTML::Entities::encode(join('/',@urlslices),"'").'/'.$lastitem;
 }  }
   
 sub compare_arrays {  sub compare_arrays {
Line 14044  sub init_user_environment { Line 14549  sub init_user_environment {
  }   }
     }      }
     closedir(DIR);      closedir(DIR);
   # If there is a undeleted lockfile for the user's paste buffer remove it.
               my $namespace = 'nohist_courseeditor';
               my $lockingkey = 'paste'."\0".'locked_num';
               my %lockhash = &Apache::lonnet::get($namespace,[$lockingkey],
                                                   $domain,$username);
               if (exists($lockhash{$lockingkey})) {
                   my $delresult = &Apache::lonnet::del($namespace,[$lockingkey],$domain,$username);
                   unless ($delresult eq 'ok') {
                       &Apache::lonnet::logthis("Failed to delete paste buffer locking key in $namespace for ".$username.":".$domain." Result was: $delresult");
                   }
               }
  }   }
 # Give them a new cookie  # Give them a new cookie
  my $id = ($args->{'robot'} ? 'robot'.$args->{'robot'}   my $id = ($args->{'robot'} ? 'robot'.$args->{'robot'}
Line 14057  sub init_user_environment { Line 14573  sub init_user_environment {
     }      }
 # ------------------------------------ Check browser type and MathML capability  # ------------------------------------ Check browser type and MathML capability
   
     my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,      my ($httpbrowser,$clientbrowser,$clientversion,$clientmathml,$clientunicode,
         $clientunicode,$clientos) = &decode_user_agent($r);          $clientos,$clientmobile,$clientinfo,$clientosversion) = &decode_user_agent($r);
   
 # ------------------------------------------------------------- Get environment  # ------------------------------------------------------------- Get environment
   
Line 14089  sub init_user_environment { Line 14605  sub init_user_environment {
      "browser.mathml"     => $clientmathml,       "browser.mathml"     => $clientmathml,
      "browser.unicode"    => $clientunicode,       "browser.unicode"    => $clientunicode,
      "browser.os"         => $clientos,       "browser.os"         => $clientos,
                "browser.mobile"     => $clientmobile,
                "browser.info"       => $clientinfo,
                "browser.osversion"  => $clientosversion,
      "server.domain"      => $Apache::lonnet::perlvar{'lonDefDomain'},       "server.domain"      => $Apache::lonnet::perlvar{'lonDefDomain'},
      "request.course.fn"  => '',       "request.course.fn"  => '',
      "request.course.uri" => '',       "request.course.uri" => '',
Line 14108  sub init_user_environment { Line 14627  sub init_user_environment {
     $env{'browser.interface'}=$form->{'interface'};      $env{'browser.interface'}=$form->{'interface'};
  }   }
   
           if ($form->{'iptoken'}) {
               my $lonhost = $r->dir_config('lonHostID');
               $initial_env{"user.noloadbalance"} = $lonhost;
               $env{'user.noloadbalance'} = $lonhost;
           }
   
         my %is_adv = ( is_adv => $env{'user.adv'} );          my %is_adv = ( is_adv => $env{'user.adv'} );
         my %domdef;          my %domdef;
         unless ($domain eq 'public') {          unless ($domain eq 'public') {
Line 14120  sub init_user_environment { Line 14645  sub init_user_environment {
                                                   undef,\%userenv,\%domdef,\%is_adv);                                                    undef,\%userenv,\%domdef,\%is_adv);
         }          }
   
         foreach my $crstype ('official','unofficial','community') {          foreach my $crstype ('official','unofficial','community','textbook') {
             $userenv{'canrequest.'.$crstype} =              $userenv{'canrequest.'.$crstype} =
                 &Apache::lonnet::usertools_access($username,$domain,$crstype,                  &Apache::lonnet::usertools_access($username,$domain,$crstype,
                                                   'reload','requestcourses',                                                    'reload','requestcourses',
Line 14225  sub clean_symb { Line 14750  sub clean_symb {
     return ($symb,$enc);      return ($symb,$enc);
 }  }
   
 sub build_release_hashes {  ############################################################
     my ($checkparms,$checkresponsetypes,$checkcrstypes,$anonsurvey,$randomizetry) = @_;  ############################################################
     return unless((ref($checkparms) eq 'HASH') && (ref($checkresponsetypes) eq 'HASH') &&  
                   (ref($checkcrstypes) eq 'HASH') && (ref($anonsurvey) eq 'HASH') &&  =pod
                   (ref($randomizetry) eq 'HASH'));  
     foreach my $key (keys(%Apache::lonnet::needsrelease)) {  =head1 Routines for building display used to search for courses
         my ($item,$name,$value) = split(/:/,$key);  
         if ($item eq 'parameter') {  
             if (ref($checkparms->{$name}) eq 'ARRAY') {  =over 4
                 unless(grep(/^\Q$name\E$/,@{$checkparms->{$name}})) {  
                     push(@{$checkparms->{$name}},$value);  =item * &build_filters()
                 }  
   Create markup for a table used to set filters to use when selecting
   courses in a domain.  Used by lonpickcourse.pm, lonmodifycourse.pm
   and quotacheck.pl
   
   
   Inputs:
   
   filterlist - anonymous array of fields to include as potential filters
   
   crstype - course type
   
   roleelement - fifth arg in selectcourse_link() populates fifth arg in javascript: opencrsbrowser() function, used
                 to pop-open a course selector (will contain "extra element").
   
   multelement - if multiple course selections will be allowed, this will be a hidden form element: name: multiple; value: 1
   
   filter - anonymous hash of criteria and their values
   
   action - form action
   
   numfiltersref - ref to scalar (count of number of elements in institutional codes -- e.g., 4 for year, semester, department, and number)
   
   caller - caller context (e.g., set to 'modifycourse' when routine is called from lonmodifycourse.pm)
   
   cloneruname - username of owner of new course who wants to clone
   
   clonerudom - domain of owner of new course who wants to clone
   
   typeelem - text to use for left column in row containing course type (i.e., Course, Community or Course/Community)
   
   codetitlesref - reference to array of titles of components in institutional codes (official courses)
   
   codedom - domain
   
   formname - value of form element named "form".
   
   fixeddom - domain, if fixed.
   
   prevphase - value to assign to form element named "phase" when going back to the previous screen
   
   cnameelement - name of form element in form on opener page which will receive title of selected course
   
   cnumelement - name of form element in form on opener page which will receive courseID  of selected course
   
   cdomelement - name of form element in form on opener page which will receive domain of selected course
   
   setroles - includes access constraint identifier when setting a roles-based condition for acces to a portfolio file
   
   clonetext - hidden form elements containing list of courses cloneable by intended course owner when DC creates a course
   
   clonewarning - warning message about missing information for intended course owner when DC creates a course
   
   
   Returns: $output - HTML for display of search criteria, and hidden form elements.
   
   
   Side Effects: None
   
   =cut
   
   # ---------------------------------------------- search for courses based on last activity etc.
   
   sub build_filters {
       my ($filterlist,$crstype,$roleelement,$multelement,$filter,$action,
           $numtitlesref,$caller,$cloneruname,$clonerudom,$typeelement,
           $codetitlesref,$codedom,$formname,$fixeddom,$prevphase,
           $cnameelement,$cnumelement,$cdomelement,$setroles,
           $clonetext,$clonewarning) = @_;
       my ($list,$jscript);
       my $onchange = 'javascript:updateFilters(this)';
       my ($domainselectform,$sincefilterform,$createdfilterform,
           $ownerdomselectform,$persondomselectform,$instcodeform,
           $typeselectform,$instcodetitle);
       if ($formname eq '') {
           $formname = $caller;
       }
       foreach my $item (@{$filterlist}) {
           unless (($item eq 'descriptfilter') || ($item eq 'instcodefilter') ||
                   ($item eq 'sincefilter') || ($item eq 'createdfilter')) {
               if ($item eq 'domainfilter') {
                   $filter->{$item} = &LONCAPA::clean_domain($filter->{$item});
               } elsif ($item eq 'coursefilter') {
                   $filter->{$item} = &LONCAPA::clean_courseid($filter->{$item});
               } elsif ($item eq 'ownerfilter') {
                   $filter->{$item} = &LONCAPA::clean_username($filter->{$item});
               } elsif ($item eq 'ownerdomfilter') {
                   $filter->{'ownerdomfilter'} =
                       &LONCAPA::clean_domain($filter->{$item});
                   $ownerdomselectform = &select_dom_form($filter->{'ownerdomfilter'},
                                                          'ownerdomfilter',1);
               } elsif ($item eq 'personfilter') {
                   $filter->{$item} = &LONCAPA::clean_username($filter->{$item});
               } elsif ($item eq 'persondomfilter') {
                   $persondomselectform = &select_dom_form($filter->{'persondomfilter'},
                                                           'persondomfilter',1);
             } else {              } else {
                 push(@{$checkparms->{$name}},$value);                  $filter->{$item} =~ s/\W//g;
             }              }
         } elsif ($item eq 'resourcetag') {              if (!$filter->{$item}) {
             if ($name eq 'responsetype') {                  $filter->{$item} = '';
                 $checkresponsetypes->{$value} = $Apache::lonnet::needsrelease{$key}              }
           }
           if ($item eq 'domainfilter') {
               my $allow_blank = 1;
               if ($formname eq 'portform') {
                   $allow_blank=0;
               } elsif ($formname eq 'studentform') {
                   $allow_blank=0;
             }              }
         } elsif ($item eq 'course') {              if ($fixeddom) {
             if ($name eq 'crstype') {                  $domainselectform = '<input type="hidden" name="domainfilter"'.
                 $checkcrstypes->{$value} = $Apache::lonnet::needsrelease{$key};                                      ' value="'.$codedom.'" />'.
                                       &Apache::lonnet::domain($codedom,'description');
               } else {
                   $domainselectform = &select_dom_form($filter->{$item},
                                                        'domainfilter',
                                                         $allow_blank,'',$onchange);
             }              }
           } else {
               $list->{$item} = &HTML::Entities::encode($filter->{$item},'<>&"');
           }
       }
   
       # last course activity filter and selection
       $sincefilterform = &timebased_select_form('sincefilter',$filter);
   
       # course created filter and selection
       if (exists($filter->{'createdfilter'})) {
           $createdfilterform = &timebased_select_form('createdfilter',$filter);
       }
   
       my %lt = &Apache::lonlocal::texthash(
                   'cac' => "$crstype Activity",
                   'ccr' => "$crstype Created",
                   'cde' => "$crstype Title",
                   'cdo' => "$crstype Domain",
                   'ins' => 'Institutional Code',
                   'inc' => 'Institutional Categorization',
                   'cow' => "$crstype Owner/Co-owner",
                   'cop' => "$crstype Personnel Includes",
                   'cog' => 'Type',
                );
   
       if (($formname eq 'ccrs') || ($formname eq 'requestcrs')) {
           my $typeval = 'Course';
           if ($crstype eq 'Community') {
               $typeval = 'Community';
           }
           $typeselectform = '<input type="hidden" name="type" value="'.$typeval.'" />';
       } else {
           $typeselectform =  '<select name="type" size="1"';
           if ($onchange) {
               $typeselectform .= ' onchange="'.$onchange.'"';
           }
           $typeselectform .= '>'."\n";
           foreach my $posstype ('Course','Community') {
               $typeselectform.='<option value="'.$posstype.'"'.
                   ($posstype eq $crstype ? ' selected="selected" ' : ''). ">".&mt($posstype)."</option>\n";
           }
           $typeselectform.="</select>";
       }
   
       my ($cloneableonlyform,$cloneabletitle);
       if (exists($filter->{'cloneableonly'})) {
           my $cloneableon = '';
           my $cloneableoff = ' checked="checked"';
           if ($filter->{'cloneableonly'}) {
               $cloneableon = $cloneableoff;
               $cloneableoff = '';
           }
           $cloneableonlyform = '<span class="LC_nobreak"><label><input type="radio" name="cloneableonly" value="1" '.$cloneableon.'/>&nbsp;'.&mt('Required').'</label>'.('&nbsp;'x3).'<label><input type="radio" name="cloneableonly" value="" '.$cloneableoff.' />&nbsp;'.&mt('No restriction').'</label></span>';
           if ($formname eq 'ccrs') {
               $cloneabletitle = &mt('Cloneable for [_1]',$cloneruname.':'.$clonerudom);
           } else {
               $cloneabletitle = &mt('Cloneable by you');
           }
       }
       my $officialjs;
       if ($crstype eq 'Course') {
           if (exists($filter->{'instcodefilter'})) {
   #            if (($fixeddom) || ($formname eq 'requestcrs') ||
   #                ($formname eq 'modifycourse') || ($formname eq 'filterpicker')) {
               if ($codedom) {
                   $officialjs = 1;
                   ($instcodeform,$jscript,$$numtitlesref) =
                       &Apache::courseclassifier::instcode_selectors($codedom,'filterpicker',
                                                                     $officialjs,$codetitlesref);
                   if ($jscript) {
                       $jscript = '<script type="text/javascript">'."\n".
                                  '// <![CDATA['."\n".
                                  $jscript."\n".
                                  '// ]]>'."\n".
                                  '</script>'."\n";
                   }
               }
               if ($instcodeform eq '') {
                   $instcodeform =
                       '<input type="text" name="instcodefilter" size="10" value="'.
                       $list->{'instcodefilter'}.'" />';
                   $instcodetitle = $lt{'ins'};
               } else {
                   $instcodetitle = $lt{'inc'};
               }
               if ($fixeddom) {
                   $instcodetitle .= '<br />('.$codedom.')';
               }
           }
       }
       my $output = qq|
   <form method="post" name="filterpicker" action="$action">
   <input type="hidden" name="form" value="$formname" />
   |;
       if ($formname eq 'modifycourse') {
           $output .= '<input type="hidden" name="phase" value="courselist" />'."\n".
                      '<input type="hidden" name="prevphase" value="'.
                      $prevphase.'" />'."\n";
       } elsif ($formname eq 'quotacheck') {
           $output .= qq|
   <input type="hidden" name="sortby" value="" />
   <input type="hidden" name="sortorder" value="" />
   |;
       } else {
           my $name_input;
           if ($cnameelement ne '') {
               $name_input = '<input type="hidden" name="cnameelement" value="'.
                             $cnameelement.'" />';
           }
           $output .= qq|
   <input type="hidden" name="cnumelement" value="$cnumelement" />
   <input type="hidden" name="cdomelement" value="$cdomelement" />
   $name_input
   $roleelement
   $multelement
   $typeelement
   |;
           if ($formname eq 'portform') {
               $output .= '<input type="hidden" name="setroles" value="'.$setroles.'" />'."\n";
         }          }
     }      }
     ($anonsurvey->{major},$anonsurvey->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:anonsurvey'});      if ($fixeddom) {
     ($randomizetry->{major},$randomizetry->{minor}) = split(/\./,$Apache::lonnet::needsrelease{'parameter:type:randomizetry'});          $output .= '<input type="hidden" name="fixeddom" value="'.$fixeddom.'" />'."\n";
       }
       $output .= "<br />\n".&Apache::lonhtmlcommon::start_pick_box();
       if ($sincefilterform) {
           $output .= &Apache::lonhtmlcommon::row_title($lt{'cac'})
                     .$sincefilterform
                     .&Apache::lonhtmlcommon::row_closure();
       }
       if ($createdfilterform) {
           $output .= &Apache::lonhtmlcommon::row_title($lt{'ccr'})
                     .$createdfilterform
                     .&Apache::lonhtmlcommon::row_closure();
       }
       if ($domainselectform) {
           $output .= &Apache::lonhtmlcommon::row_title($lt{'cdo'})
                     .$domainselectform
                     .&Apache::lonhtmlcommon::row_closure();
       }
       if ($typeselectform) {
           if (($formname eq 'ccrs') || ($formname eq 'requestcrs')) {
               $output .= $typeselectform;
           } else {
               $output .= &Apache::lonhtmlcommon::row_title($lt{'cog'})
                         .$typeselectform
                         .&Apache::lonhtmlcommon::row_closure();
           }
       }
       if ($instcodeform) {
           $output .= &Apache::lonhtmlcommon::row_title($instcodetitle)
                     .$instcodeform
                     .&Apache::lonhtmlcommon::row_closure();
       }
       if (exists($filter->{'ownerfilter'})) {
           $output .= &Apache::lonhtmlcommon::row_title($lt{'cow'}).
                      '<table><tr><td>'.&mt('Username').'<br />'.
                      '<input type="text" name="ownerfilter" size="20" value="'.
                      $list->{'ownerfilter'}.'" /></td><td>'.&mt('Domain').'<br />'.
                      $ownerdomselectform.'</td></tr></table>'.
                      &Apache::lonhtmlcommon::row_closure();
       }
       if (exists($filter->{'personfilter'})) {
           $output .= &Apache::lonhtmlcommon::row_title($lt{'cop'}).
                      '<table><tr><td>'.&mt('Username').'<br />'.
                      '<input type="text" name="personfilter" size="20" value="'.
                      $list->{'personfilter'}.'" /></td><td>'.&mt('Domain').'<br />'.
                      $persondomselectform.'</td></tr></table>'.
                      &Apache::lonhtmlcommon::row_closure();
       }
       if (exists($filter->{'coursefilter'})) {
           $output .= &Apache::lonhtmlcommon::row_title(&mt('LON-CAPA course ID'))
                     .'<input type="text" name="coursefilter" size="25" value="'
                     .$list->{'coursefilter'}.'" />'
                     .&Apache::lonhtmlcommon::row_closure();
       }
       if ($cloneableonlyform) {
           $output .= &Apache::lonhtmlcommon::row_title($cloneabletitle).
                      $cloneableonlyform.&Apache::lonhtmlcommon::row_closure();
       }
       if (exists($filter->{'descriptfilter'})) {
           $output .= &Apache::lonhtmlcommon::row_title($lt{'cde'})
                     .'<input type="text" name="descriptfilter" size="40" value="'
                     .$list->{'descriptfilter'}.'" />'
                     .&Apache::lonhtmlcommon::row_closure(1);
       }
       $output .= &Apache::lonhtmlcommon::end_pick_box().'<p>'.$clonetext."\n".
                  '<input type="hidden" name="updater" value="" />'."\n".
                  '<input type="submit" name="gosearch" value="'.
                  &mt('Search').'" /></p>'."\n".'</form>'."\n".'<hr />'."\n";
       return $jscript.$clonewarning.$output;
   }
   
   =pod
   
   =item * &timebased_select_form()
   
   Create markup for a dropdown list used to select a time-based
   filter e.g., Course Activity, Course Created, when searching for courses
   or communities
   
   Inputs:
   
   item - name of form element (sincefilter or createdfilter)
   
   filter - anonymous hash of criteria and their values
   
   Returns: HTML for a select box contained a blank, then six time selections,
            with value set in incoming form variables currently selected.
   
   Side Effects: None
   
   =cut
   
   sub timebased_select_form {
       my ($item,$filter) = @_;
       if (ref($filter) eq 'HASH') {
           $filter->{$item} =~ s/[^\d-]//g;
           if (!$filter->{$item}) { $filter->{$item}=-1; }
           return &select_form(
                               $filter->{$item},
                               $item,
                               {      '-1' => '',
                                   '86400' => &mt('today'),
                                  '604800' => &mt('last week'),
                                 '2592000' => &mt('last month'),
                                 '7776000' => &mt('last three months'),
                                '15552000' => &mt('last six months'),
                                '31104000' => &mt('last year'),
                       'select_form_order' =>
                              ['-1','86400','604800','2592000','7776000',
                               '15552000','31104000']});
       }
   }
   
   =pod
   
   =item * &js_changer()
   
   Create script tag containing Javascript used to submit course search form
   when course type or domain is changed, and also to hide 'Searching ...' on
   page load completion for page showing search result.
   
   Inputs: None
   
   Returns: markup containing updateFilters() and hideSearching() javascript functions.
   
   Side Effects: None
   
   =cut
   
   sub js_changer {
       return <<ENDJS;
   <script type="text/javascript">
   // <![CDATA[
   function updateFilters(caller) {
       if (typeof(caller) != "undefined") {
           document.filterpicker.updater.value = caller.name;
       }
       document.filterpicker.submit();
   }
   
   function hideSearching() {
       if (document.getElementById('searching')) {
           document.getElementById('searching').style.display = 'none';
       }
     return;      return;
 }  }
   
   // ]]>
   </script>
   
   ENDJS
   }
   
   =pod
   
   =item * &search_courses()
   
   Process selected filters form course search form and pass to lonnet::courseiddump
   to retrieve a hash for which keys are courseIDs which match the selected filters.
   
   Inputs:
   
   dom - domain being searched
   
   type - course type ('Course' or 'Community' or '.' if any).
   
   filter - anonymous hash of criteria and their values
   
   numtitles - for institutional codes - number of categories
   
   cloneruname - optional username of new course owner
   
   clonerudom - optional domain of new course owner
   
   domcloner - Optional "domcloner" flag; has value=1 if user has ccc priv in domain being filtered by,
               (used when DC is using course creation form)
   
   codetitles - reference to array of titles of components in institutional codes (official courses).
   
   
   Returns: %courses - hash of courses satisfying search criteria, keys = course IDs, values are corresponding colon-separated escaped description, institutional code, owner and type.
   
   
   Side Effects: None
   
   =cut
   
   
   sub search_courses {
       my ($dom,$type,$filter,$numtitles,$cloneruname,$clonerudom,$domcloner,$codetitles) = @_;
       my (%courses,%showcourses,$cloner);
       if (($filter->{'ownerfilter'} ne '') ||
           ($filter->{'ownerdomfilter'} ne '')) {
           $filter->{'combownerfilter'} = $filter->{'ownerfilter'}.':'.
                                          $filter->{'ownerdomfilter'};
       }
       foreach my $item ('descriptfilter','coursefilter','combownerfilter') {
           if (!$filter->{$item}) {
               $filter->{$item}='.';
           }
       }
       my $now = time;
       my $timefilter =
          ($filter->{'sincefilter'}==-1?1:$now-$filter->{'sincefilter'});
       my ($createdbefore,$createdafter);
       if (($filter->{'createdfilter'} ne '') && ($filter->{'createdfilter'} !=-1)) {
           $createdbefore = $now;
           $createdafter = $now-$filter->{'createdfilter'};
       }
       my ($instcodefilter,$regexpok);
       if ($numtitles) {
           if ($env{'form.official'} eq 'on') {
               $instcodefilter =
                   &Apache::courseclassifier::instcode_search_str($dom,$numtitles,$codetitles);
               $regexpok = 1;
           } elsif ($env{'form.official'} eq 'off') {
               $instcodefilter = &Apache::courseclassifier::instcode_search_str($dom,$numtitles,$codetitles);
               unless ($instcodefilter eq '') {
                   $regexpok = -1;
               }
           }
       } else {
           $instcodefilter = $filter->{'instcodefilter'};
       }
       if ($instcodefilter eq '') { $instcodefilter = '.'; }
       if ($type eq '') { $type = '.'; }
   
       if (($clonerudom ne '') && ($cloneruname ne '')) {
           $cloner = $cloneruname.':'.$clonerudom;
       }
       %courses = &Apache::lonnet::courseiddump($dom,
                                                $filter->{'descriptfilter'},
                                                $timefilter,
                                                $instcodefilter,
                                                $filter->{'combownerfilter'},
                                                $filter->{'coursefilter'},
                                                undef,undef,$type,$regexpok,undef,undef,
                                                undef,undef,$cloner,$env{'form.cc_clone'},
                                                $filter->{'cloneableonly'},
                                                $createdbefore,$createdafter,undef,
                                                $domcloner);
       if (($filter->{'personfilter'} ne '') && ($filter->{'persondomfilter'} ne '')) {
           my $ccrole;
           if ($type eq 'Community') {
               $ccrole = 'co';
           } else {
               $ccrole = 'cc';
           }
           my %rolehash = &Apache::lonnet::get_my_roles($filter->{'personfilter'},
                                                        $filter->{'persondomfilter'},
                                                        'userroles',undef,
                                                        [$ccrole,'in','ad','ep','ta','cr'],
                                                        $dom);
           foreach my $role (keys(%rolehash)) {
               my ($cnum,$cdom,$courserole) = split(':',$role);
               my $cid = $cdom.'_'.$cnum;
               if (exists($courses{$cid})) {
                   if (ref($courses{$cid}) eq 'HASH') {
                       if (ref($courses{$cid}{roles}) eq 'ARRAY') {
                           if (!grep(/^\Q$courserole\E$/,@{$courses{$cid}{roles}})) {
                               push (@{$courses{$cid}{roles}},$courserole);
                           }
                       } else {
                           $courses{$cid}{roles} = [$courserole];
                       }
                       $showcourses{$cid} = $courses{$cid};
                   }
               }
           }
           %courses = %showcourses;
       }
       return %courses;
   }
   
   =pod
   
   =back
   
   =cut
   
   
 sub update_content_constraints {  sub update_content_constraints {
     my ($cdom,$cnum,$chome,$cid) = @_;      my ($cdom,$cnum,$chome,$cid) = @_;
     my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired');      my %curr_reqd_hash = &Apache::lonnet::userenvironment($cdom,$cnum,'internal.releaserequired');
Line 14341  sub parse_supplemental_title { Line 15369  sub parse_supplemental_title {
     return $title;      return $title;
 }  }
   
   sub recurse_supplemental {
       my ($cnum,$cdom,$suppmap,$numfiles,$errors) = @_;
       if ($suppmap) {
           my ($errtext,$fatal) = &LONCAPA::map::mapread('/uploaded/'.$cdom.'/'.$cnum.'/'.$suppmap);
           if ($fatal) {
               $errors ++;
           } else {
               if ($#LONCAPA::map::resources > 0) {
                   foreach my $res (@LONCAPA::map::resources) {
                       my ($title,$src,$ext,$type,$status)=split(/\:/,$res);
                       if (($src ne '') && ($status eq 'res')) {
                           if ($src =~ m{^\Q/uploaded/$cdom/$cnum/\E(supplemental_\d+\.sequence)$}) {
                               ($numfiles,$errors) = &recurse_supplemental($cnum,$cdom,$1,$numfiles,$errors);
                           } else {
                               $numfiles ++;
                           }
                       }
                   }
               }
           }
       }
       return ($numfiles,$errors);
   }
   
 sub symb_to_docspath {  sub symb_to_docspath {
     my ($symb) = @_;      my ($symb) = @_;
     return unless ($symb);      return unless ($symb);
Line 14370  sub symb_to_docspath { Line 15422  sub symb_to_docspath {
                     my $thistitle = $res->title();                      my $thistitle = $res->title();
                     $path .= '&'.                      $path .= '&'.
                              &Apache::lonhtmlcommon::entity_encode($thisurl).'&'.                               &Apache::lonhtmlcommon::entity_encode($thisurl).'&'.
                              &Apache::lonhtmlcommon::entity_encode($thistitle).                               &escape($thistitle).
                              ':'.$res->randompick().                               ':'.$res->randompick().
                              ':'.$res->randomout().                               ':'.$res->randomout().
                              ':'.$res->encrypted().                               ':'.$res->encrypted().
Line 14382  sub symb_to_docspath { Line 15434  sub symb_to_docspath {
         $path =~ s/^\&//;          $path =~ s/^\&//;
         my $maptitle = $mapresobj->title();          my $maptitle = $mapresobj->title();
         if ($mapurl eq 'default') {          if ($mapurl eq 'default') {
             $maptitle = 'Main Course Documents';              $maptitle = 'Main Content';
         }          }
         $path .= (($path ne '')? '&' : '').          $path .= (($path ne '')? '&' : '').
                  &Apache::lonhtmlcommon::entity_encode($mapurl).'&'.                   &Apache::lonhtmlcommon::entity_encode($mapurl).'&'.
                  &Apache::lonhtmlcommon::entity_encode($maptitle).                   &escape($maptitle).
                  ':'.$mapresobj->randompick().                   ':'.$mapresobj->randompick().
                  ':'.$mapresobj->randomout().                   ':'.$mapresobj->randomout().
                  ':'.$mapresobj->encrypted().                   ':'.$mapresobj->encrypted().
Line 14396  sub symb_to_docspath { Line 15448  sub symb_to_docspath {
         my $maptitle = &Apache::lonnet::gettitle($mapurl);          my $maptitle = &Apache::lonnet::gettitle($mapurl);
         my $ispage = (($type eq 'page')? 1 : '');          my $ispage = (($type eq 'page')? 1 : '');
         if ($mapurl eq 'default') {          if ($mapurl eq 'default') {
             $maptitle = 'Main Course Documents';              $maptitle = 'Main Content';
         }          }
         $path = &Apache::lonhtmlcommon::entity_encode($mapurl).'&'.          $path = &Apache::lonhtmlcommon::entity_encode($mapurl).'&'.
                 &Apache::lonhtmlcommon::entity_encode($maptitle).':::::'.$ispage;                  &escape($maptitle).':::::'.$ispage;
     }      }
     unless ($mapurl eq 'default') {      unless ($mapurl eq 'default') {
         $path = 'default&'.          $path = 'default&'.
                 &Apache::lonhtmlcommon::entity_encode('Main Course Documents').                  &escape('Main Content').
                 ':::::&'.$path;                  ':::::&'.$path;
     }      }
     return $path;      return $path;
Line 14424  sub captcha_display { Line 15476  sub captcha_display {
             $error = 'recaptcha';              $error = 'recaptcha';
         }          }
     }      }
     return ($output,$error);      return ($output,$error,$captcha);
 }  }
   
 sub captcha_response {  sub captcha_response {
Line 14500  sub create_captcha { Line 15552  sub create_captcha {
         if (-e $Apache::lonnet::perlvar{'lonCaptchaDir'}.'/'.$md5sum.'.png') {          if (-e $Apache::lonnet::perlvar{'lonCaptchaDir'}.'/'.$md5sum.'.png') {
             $output = '<input type="hidden" name="crypt" value="'.$md5sum.'" />'."\n".              $output = '<input type="hidden" name="crypt" value="'.$md5sum.'" />'."\n".
                       &mt('Type in the letters/numbers shown below').'&nbsp;'.                        &mt('Type in the letters/numbers shown below').'&nbsp;'.
                      '<input type="text" size="5" name="code" value="" /><br />'.                        '<input type="text" size="5" name="code" value="" autocomplete="off" />'.
                      '<img src="'.$captcha_params{'www_output_dir'}.'/'.$md5sum.'.png" />';                        '<br />'.
                         '<img src="'.$captcha_params{'www_output_dir'}.'/'.$md5sum.'.png" alt="captcha" />';
             last;              last;
         }          }
     }      }
Line 14542  sub check_captcha { Line 15595  sub check_captcha {
   
 sub create_recaptcha {  sub create_recaptcha {
     my ($pubkey) = @_;      my ($pubkey) = @_;
       my $use_ssl;
       if ($ENV{'SERVER_PORT'} == 443) {
           $use_ssl = 1;
       }
     my $captcha = Captcha::reCAPTCHA->new;      my $captcha = Captcha::reCAPTCHA->new;
     return $captcha->get_options_setter({theme => 'white'})."\n".      return $captcha->get_options_setter({theme => 'white'})."\n".
            $captcha->get_html($pubkey).             $captcha->get_html($pubkey,undef,$use_ssl).
            &mt('If either word is hard to read, [_1] will replace them.',             &mt('If either word is hard to read, [_1] will replace them.',
                '<image src="/res/adm/pages/refresh.gif" alt="reCAPTCHA refresh" />').                 '<img src="/res/adm/pages/refresh.gif" alt="reCAPTCHA refresh" />').
            '<br /><br />';             '<br /><br />';
 }  }
   
Line 14567  sub check_recaptcha { Line 15624  sub check_recaptcha {
     return $captcha_chk;      return $captcha_chk;
 }  }
   
 =pod  sub emailusername_info {
       my @fields = ('firstname','lastname','institution','web','location','officialemail');
       my %titles = &Apache::lonlocal::texthash (
                        lastname      => 'Last Name',
                        firstname     => 'First Name',
                        institution   => 'School/college/university',
                        location      => "School's city, state/province, country",
                        web           => "School's web address",
                        officialemail => 'E-mail address at institution (if different)',
                    );
       return (\@fields,\%titles);
   }
   
 =back  sub cleanup_html {
       my ($incoming) = @_;
       my $outgoing;
       if ($incoming ne '') {
           $outgoing = $incoming;
           $outgoing =~ s/;/&#059;/g;
           $outgoing =~ s/\#/&#035;/g;
           $outgoing =~ s/\&/&#038;/g;
           $outgoing =~ s/</&#060;/g;
           $outgoing =~ s/>/&#062;/g;
           $outgoing =~ s/\(/&#040/g;
           $outgoing =~ s/\)/&#041;/g;
           $outgoing =~ s/"/&#034;/g;
           $outgoing =~ s/'/&#039;/g;
           $outgoing =~ s/\$/&#036;/g;
           $outgoing =~ s{/}{&#047;}g;
           $outgoing =~ s/=/&#061;/g;
           $outgoing =~ s/\\/&#092;/g
       }
       return $outgoing;
   }
   
   # Checks for critical messages and returns a redirect url if one exists.
   # $interval indicates how often to check for messages.
   sub critical_redirect {
       my ($interval) = @_;
       if ((time-$env{'user.criticalcheck.time'})>$interval) {
           my @what=&Apache::lonnet::dump('critical', $env{'user.domain'},
                                           $env{'user.name'});
           &Apache::lonnet::appenv({'user.criticalcheck.time'=>time});
           my $redirecturl;
           if ($what[0]) {
               if (($what[0] ne 'con_lost') && ($what[0]!~/^error\:/)) {
                   $redirecturl='/adm/email?critical=display';
                   my $url=&Apache::lonnet::absolute_url().$redirecturl;
                   return (1, $url);
               }
           }
       }
       return ();
   }
   
 =cut  # Use:
   #   my $answer=reply("encrypt:passwd:$udom:$uname:$upass",$tryserver);
   #
   ##################################################
   #          password associated functions         #
   ##################################################
   sub des_keys {
       # Make a new key for DES encryption.
       # Each key has two parts which are returned separately.
       # Please note:  Each key must be passed through the &hex function
       # before it is output to the web browser.  The hex versions cannot
       # be used to decrypt.
       my @hexstr=('0','1','2','3','4','5','6','7',
                   '8','9','a','b','c','d','e','f');
       my $lkey='';
       for (0..7) {
           $lkey.=$hexstr[rand(15)];
       }
       my $ukey='';
       for (0..7) {
           $ukey.=$hexstr[rand(15)];
       }
       return ($lkey,$ukey);
   }
   
   sub des_decrypt {
       my ($key,$cyphertext) = @_;
       my $keybin=pack("H16",$key);
       my $cypher;
       if ($Crypt::DES::VERSION>=2.03) {
           $cypher=new Crypt::DES $keybin;
       } else {
           $cypher=new DES $keybin;
       }
       my $plaintext=
           $cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,0,16))));
       $plaintext.=
           $cypher->decrypt(unpack("a8",pack("H16",substr($cyphertext,16,16))));
       $plaintext=substr($plaintext,1,ord(substr($plaintext,0,1)) );
       return $plaintext;
   }
   
 1;  1;
 __END__;  __END__;

Removed from v.1.1075.2.36  
changed lines
  Added in v.1.1075.2.85


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>