Diff for /rat/lonpageflip.pm between versions 1.13 and 1.110

version 1.13, 2000/11/16 11:58:30 version 1.110, 2021/08/21 03:42:02
Line 2 Line 2
 #  #
 # Page flip handler  # Page flip handler
 #  #
 # (Page Handler  # $Id$
 #  #
 # (TeX Content Handler  # Copyright Michigan State University Board of Trustees
 #  #
 # 05/29/00,05/30 Gerd Kortemeyer)  # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
 # 08/30,08/31,09/06,09/14,09/15,09/16,09/19,09/20,09/21,09/23,  
 # 10/02 Gerd Kortemeyer)  
 #  #
 # 10/03,10/05,10/06,10/07,10/09,10/10,10/11,10/16,10/17,  # LON-CAPA is free software; you can redistribute it and/or modify
 # 11/14,11/16 Gerd Kortemeyer  # it under the terms of the GNU General Public License as published by
   # the Free Software Foundation; either version 2 of the License, or
   # (at your option) any later version.
   #
   # LON-CAPA is distributed in the hope that it will be useful,
   # but WITHOUT ANY WARRANTY; without even the implied warranty of
   # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   # GNU General Public License for more details.
   #
   # You should have received a copy of the GNU General Public License
   # along with LON-CAPA; if not, write to the Free Software
   # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   #
   # /home/httpd/html/adm/gpl.txt
   #
   # http://www.lon-capa.org/
   #
   
   
   
 package Apache::lonpageflip;  package Apache::lonpageflip;
   
 use strict;  use strict;
   use LONCAPA;
 use Apache::Constants qw(:common :http REDIRECT);  use Apache::Constants qw(:common :http REDIRECT);
 use Apache::lonnet();  use Apache::lonnet;
   use Apache::loncommon();
   use Apache::lonnavmaps();
   use Apache::lonuserstate;
   use Apache::lonlocal;
 use HTML::TokeParser;  use HTML::TokeParser;
 use GDBM_File;  use GDBM_File;
   
Line 25  use GDBM_File; Line 46  use GDBM_File;
       
 my %hash;  my %hash;
   
   sub cleanup {
       if (tied(%hash)){
    &Apache::lonnet::logthis('Cleanup pageflip: hash');
           unless (untie(%hash)) {
       &Apache::lonnet::logthis('Failed cleanup pageflip: hash');
           }
       }
       return OK;
   }
   
 sub addrid {  sub addrid {
     my ($current,$new,$condid)=@_;      my ($current,$new,$condid)=@_;
     unless ($condid) { $condid=0; }      unless ($condid) { $condid=0; }
     if (&Apache::lonnet::allowed('bre',$hash{'src_'.$new})) {  
  if ($current) {   if ($current) {
     $current.=','.$new;      $current.=','.$new;
         } else {          } else {
             $current=''.$new;              $current=''.$new;
         }          }
     }  
     return $current;      return $current;
 }  }
   
   sub fullmove {
       my ($rid,$mapurl,$direction)=@_;
       if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db',
                           &GDBM_READER(),0640)) {
    ($rid,$mapurl)=&move($rid,$mapurl,$direction);
           untie(%hash);
       }
       return($rid,$mapurl);
   }
   
   sub hash_src {
       my ($id)=@_;
       my ($mapid,$resid)=split(/\./,$id);
       my $symb=&Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},
     $resid,$hash{'src_'.$id});
       my $anchor;
       if ($hash{'ext_'.$id} eq 'true:') {
           if ($hash{'src_'.$id} =~ /(\#.+)$/) {
               $anchor = $1;
           }
       }
       if ($hash{'encrypted_'.$id}) {
    return (&Apache::lonenc::encrypted($hash{'src_'.$id}),
    &Apache::lonenc::encrypted($symb),
                   $hash{'encrypted_'.$id},$anchor);
       }
       return ($hash{'src_'.$id},$symb,$hash{'encrypted_'.$id},$anchor);
   }
   
   sub move {
       my ($next,$endupmap,$direction,$firstres) = @_;
       my $safecount=0;
       my $allowed=0;
       my $deeplinkonly=0;
       my $deeplinkchecked;
       my $deeplink_login_pc;
       my $prev=$next;
       my ($prevmapid)=split(/\./,$next);
       do {
    ($next,$endupmap)=&get_next_possible_move($next,$endupmap,$direction);
   
    my $url = $hash{'src_'.$next};
    my ($mapid,$resid)=split(/\./,$next);
    my $symb = &Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},
    $resid,$url);
    if ($url eq '' || $symb eq '') {
       $allowed = 0;
    } else {
               my $nodeeplinkcheck = 0;
               if ($hash{'is_map_'.$next}) {
                   $nodeeplinkcheck = 1;
               }
       my $priv = &Apache::lonnet::allowed('bre',$url,$symb,'','','','',$nodeeplinkcheck);
       $allowed = (($priv eq 'F') || ($priv eq '2') || ($priv eq 'A'));
    }
           $deeplinkonly = 0;
           if ($hash{'deeplinkonly_'.$next}) {
               my ($value,$level) = map { &unescape($_); } split(/:/,$hash{'deeplinkonly_'.$next});
               my ($state,$others,$listed,$scope,$protect) = split(/,/,$value);
               unless (($state eq 'both') || ($hash{'is_map_'.$next})) {
                   if ($level eq 'resource') {
                       $deeplinkonly = 1;
                   } elsif ($level eq 'map') {
                       if ($scope eq 'rec') {
                           unless ($mapid == $prevmapid) {
                               unless ($deeplinkchecked) {
                                   $deeplink_login_pc = &get_deeplink_login_pc();
                                   $deeplinkchecked = 1;
                               }
                               if ($deeplink_login_pc) {
                                   my $poss_map_pc;
                                   if ($hash{'is_map_'.$next}) {
                                       $poss_map_pc = $hash{'map_pc_'.$url};
                                   } else {
                                       $poss_map_pc = $hash{'map_pc_'.$hash{'map_id_'.$mapid}};
                                   }
                                   unless ($deeplink_login_pc == $poss_map_pc) {
                                       unless (grep(/^$deeplink_login_pc$/,split(/,/,$hash{'map_hierarchy_'.$poss_map_pc}))) {
                                           $deeplinkonly = 1;
                                       }
                                   }
                               } else {
                                   $deeplinkonly = 1;
                               }
                           }
                       } elsif ($mapid != $prevmapid) {
                           $deeplinkonly = 1;
                       }
                   }
               }
           } elsif (($hash{'deeplinkonly_'.$prev}) && (!$firstres)) {
               my ($value,$level) = map { &unescape($_); } split(/:/,$hash{'deeplinkonly_'.$prev});
               my ($state,$others,$listed,$scope,$protect) = split(/,/,$value);
               unless (($state eq 'both') || ($hash{'is_map_'.$prev})) {
                   if ($level eq 'resource') {
                       $deeplinkonly = 1;
                   } elsif ($level eq 'map') {
                       if ($scope eq 'rec') {
                           unless ($mapid == $prevmapid) {
                               unless ($deeplinkchecked) {
                                   $deeplink_login_pc = &get_deeplink_login_pc();
                                   $deeplinkchecked = 1;
                               }
                               if ($deeplink_login_pc) {
                                   my $poss_map_pc;
                                   if ($hash{'is_map_'.$prev}) {
                                       $poss_map_pc = $hash{'map_pc_'.$url};
                                   } else {
                                       $poss_map_pc = $hash{'map_pc_'.$hash{'map_id_'.$mapid}};
                                   }
                                   unless ($deeplink_login_pc == $poss_map_pc) {
                                       unless (grep(/^$deeplink_login_pc$/,split(/,/,$hash{'map_hierarchy_'.$poss_map_pc}))) {
                                           $deeplinkonly = 1;
                                       }
                                   }
                               }
                           }
                       } else {
                           if ($mapid != $prevmapid) {
                               $deeplinkonly = 1;
                           }
                       }
                   }
               }
           }
    $safecount++;
       } while (   ($next)
        && ($next!~/\,/)
        && (
       (!$hash{'src_'.$next})
    || (
                           (!$env{'request.role.adv'})
                        && (($hash{'randomout_'.$next})
                        ||  ($deeplinkonly)
                        ||  ($hash{'deeplinkout_'.$next}))
       )
    || (!$allowed)
    )
        && ($safecount<10000));
   
       return ($next,$endupmap);
   }
   
   sub get_next_possible_move {
       my ($rid,$mapurl,$direction)=@_;
       my $startoutrid=$rid;
   
       my $next='';
   
                 my $mincond=1;
                 my $posnext='';
                 if ($direction eq 'forward') {
   # --------------------------------------------------------------------- Forward
                     while ($hash{'type_'.$rid} eq 'finish') {
                $rid=$hash{'ids_'.$hash{'map_id_'.(split(/\./,$rid))[0]}};
                     }
     foreach my $id (split(/\,/,$hash{'to_'.$rid})) {
        my $condition= $hash{'conditions_'.$hash{'goesto_'.$id}};
        my $rescond  = &Apache::lonnet::docondval($condition);
        my $linkcond = &Apache::lonnet::directcondval($hash{'condid_'.$hash{'undercond_'.$id}});
        my $thiscond = ($rescond<$linkcond)?$rescond:$linkcond;
        if ($thiscond>=$mincond) {
             if ($posnext) {
                $posnext.=','.$id.':'.$thiscond;
                             } else {
                                $posnext=$id.':'.$thiscond;
             }
                             if ($thiscond>$mincond) { $mincond=$thiscond; }
                 }
                     }
     foreach my $id (split(/\,/,$posnext))  {
                         my ($linkid,$condval)=split(/\:/,$id);
                         if ($condval>=$mincond) {
             $next=&addrid($next,$hash{'goesto_'.$linkid},
                                   $hash{'condid_'.$hash{'undercond_'.$linkid}});
                         }
                     }
                     if ($hash{'is_map_'.$next}) {
   # This jumps to the beginning of a new map (going down level)
                         if (
         $hash{'map_type_'.$hash{'map_pc_'.$hash{'src_'.$next}}} eq 'sequence') {
     $mapurl=$hash{'src_'.$next};
     $next=$hash{'map_start_'.$hash{'src_'.$next}};
                        } elsif (
   # This jumps back up from an empty sequence, to a page up one level
                            $hash{'map_type_'.$hash{'map_pc_'.$hash{'src_'.$next}}} eq 'page') {
                            $mapurl=$hash{'map_id_'.(split(/\./,$next))[0]};
                        }
                     } elsif 
                       ((split(/\./,$startoutrid))[0]!=(split(/\./,$next))[0]) {
   # This comes up from a map (coming up one level);
         $mapurl=$hash{'map_id_'.(split(/\./,$next))[0]};
     }
                 } elsif ($direction eq 'back') {
   # ------------------------------------------------------------------- Backwards
                    while ($hash{'type_'.$rid} eq 'start') {
                $rid=$hash{'ids_'.$hash{'map_id_'.(split(/\./,$rid))[0]}};
    }
    foreach my $id (split(/\,/,$hash{'from_'.$rid})) {
        my $condition= $hash{'conditions_'.$hash{'comesfrom_'.$id}};
        my $rescond  = &Apache::lonnet::docondval($condition);
        my $linkcond = &Apache::lonnet::directcondval($hash{'condid_'.$hash{'undercond_'.$id}});
        my $thiscond = ($rescond<$linkcond)?$rescond:$linkcond;
        if ($thiscond>=$mincond) {
    if ($posnext) {
                $posnext.=','.$id.':'.$thiscond;
    } else {
                                $posnext=$id.':'.$thiscond;
    }
    if ($thiscond>$mincond) { $mincond=$thiscond; }
        }
    }
    foreach my $id (split(/\,/,$posnext)) {
        my ($linkid,$condval)=split(/\:/,$id);
        if ($condval>=$mincond) {
    $next=&addrid($next,$hash{'comesfrom_'.$linkid},
          $hash{'condid_'.$hash{'undercond_'.$linkid}});
        }
    }
                     if ($hash{'is_map_'.$next}) {
   # This jumps to the end of a new map (going down one level)
                         if (
         $hash{'map_type_'.$hash{'map_pc_'.$hash{'src_'.$next}}} eq 'sequence') {
     $mapurl=$hash{'src_'.$next};
     $next=$hash{'map_finish_'.$hash{'src_'.$next}};
                         } elsif (
         $hash{'map_type_'.$hash{'map_pc_'.$hash{'src_'.$next}}} eq 'page') {
   # This jumps back up from an empty sequence, to a page up one level
                             $mapurl=$hash{'map_id_'.(split(/\./,$next))[0]};
                         }
                     } elsif 
                       ((split(/\./,$startoutrid))[0]!=(split(/\./,$next))[0]) {
   # This comes back up from a map (going up one level);
         $mapurl=$hash{'map_id_'.(split(/\./,$next))[0]};
                     }
         }
                 return ($next,$mapurl);
   }
   
   sub first_accessible_resource {
       my $furl;
       if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db',
       &GDBM_READER(),0640)) {
    $furl=$hash{'first_url'};
    my (%args,$url,$argstr);
    if ($furl =~ m{^/enc/}) {
       ($url,$argstr) = split(/\?/,&Apache::lonenc::unencrypted($furl));
    } else {
       ($url,$argstr) = split(/\?/,$furl);
    }
    foreach my $pair (split(/\&/,$argstr)) {
       my ($name,$value) = split(/=/,$pair);
       $args{&unescape($name)} = &unescape($value);
    }
           my $priv = &Apache::lonnet::allowed('bre',$url,$args{'symb'});
           my $allowed = (($priv eq 'F') || ($priv eq '2') || ($priv eq 'A'));
           if (!$allowed) {
   # Wow, we cannot see this ... move forward to the next one that we can see
       my ($newrid,$newmap)=&move($hash{'first_rid'},$hash{'first_mapurl'},'forward',1);
   # Build the new URL
               if ($newrid eq '') {
                   $furl = '/adm/navmaps';
               } else {
           my ($newmapid,$newresid)=split(/\./,$newrid);
           my $symb=&Apache::lonnet::encode_symb($newmap,$newresid,$hash{'src_'.$newrid});
           $furl=&add_get_param($hash{'src_'.$newrid},{ 'symb' => $symb });
           if ($hash{'encrypted_'.$newrid}) {
       $furl=&Apache::lonenc::encrypted($furl);
           }
               }
    }
    untie(%hash);
    return $furl;
       } else {
    return '/adm/navmaps';
       }
   }
   
   sub first_answerable_ressymb {
       my $navmap = Apache::lonnavmaps::navmap->new;
       return unless (ref($navmap));
       my $iterator = $navmap->getIterator(undef,undef,undef,1);
       return unless (ref($iterator));
       my ($curRes,$result);
       while ($curRes = $iterator->next()) {
           if (ref($curRes) && $curRes->is_problem()) {
               foreach my $part (@{$curRes->parts()}) {
                   if ($curRes->tries($part) < $curRes->maxtries($part)) {
                       $result = $curRes->link().'?symb='.$curRes->shown_symb();
                       last;
                   }    
               }
           }
       }
       if ($result) {
           return $result; 
       } else {
           return &first_accessible_resource(); 
       }
   }
   
   sub check_http_req {
       my ($srcref,$hostname) = @_;
       return unless (ref($srcref) eq 'SCALAR');
       my $usehttp;
       if ($env{'request.course.id'}) {
           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           if (($$srcref =~ m{^\Q/public/$cdom/$cnum/syllabus\E($|\?)}) &&
               ($ENV{'SERVER_PORT'} == 443) &&
               ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
               unless ((&Apache::lonnet::uses_sts()) ||
                       (&Apache::lonnet::waf_allssl($hostname))) {
                   $$srcref .= (($$srcref =~/\?/)? '&':'?') . 'usehttp=1';
                   $usehttp = 1;
               }
           } elsif (($$srcref =~ m{^\Q/adm/wrapper/ext/\E(?!https:)}) &&
                    ($ENV{'SERVER_PORT'} == 443)) {
               unless ((&Apache::lonnet::uses_sts()) ||
                       (&Apache::lonnet::waf_allssl($hostname))) {
                   my ($url,$anchor) = ($$srcref =~ /^([^\#]+)(?:|(\#[^\#]+))$/);
                   $$srcref = $url . (($$srcref =~/\?/)? '&':'?') . 'usehttp=1' .$anchor; 
                   $usehttp = 1;
               }
           }
       }
       return $usehttp;
   }
   
   sub reinited_js {
       my ($url,$cid,$timeout) = @_;
       if (!$timeout) {
           $timeout = 0;
       }
       return <<"END";
   <script type="text/javascript">
   // <![CDATA[
   setTimeout(function() {
       var newurl = '$url';
       if (document.getElementById('LC_update_$cid')) {
           document.getElementById('LC_update_$cid').style.display = 'none';
       }
       if ((newurl !== null) && (newurl !== '') && (newurl !== 'undefined')) {
           window.location.href = "$url";
       }
   }, $timeout);
   // ]]>
   </script>
   END
   }
   
   sub get_deeplink_login_pc {
       my $deeplink_login_pc;
       if (($env{'request.deeplink.login'}) && ($env{'request.course.id'})) {
           my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
           my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
           my $deeplink_symb = &Apache::loncommon::deeplink_login_symb($cnum,$cdom);
           if ($deeplink_symb) {
               my $loginmap;
               if ($deeplink_symb =~ /\.(page|sequence)$/) {
                   $loginmap = &Apache::lonnet::clutter((&Apache::lonnet::decode_symb($deeplink_symb))[2]);
               } else {
                   $loginmap = &Apache::lonnet::clutter((&Apache::lonnet::decode_symb($deeplink_symb))[0]);
               }
               $deeplink_login_pc = $hash{'map_pc_'.$loginmap};
           }
       }
       return $deeplink_login_pc;
   }
   
 # ================================================================ Main Handler  # ================================================================ Main Handler
   
 sub handler {  sub handler {
Line 46  sub handler { Line 447  sub handler {
 # ------------------------------------------- Set document type for header only  # ------------------------------------------- Set document type for header only
   
   if ($r->header_only) {    if ($r->header_only) {
      $r->content_type('text/html');        &Apache::loncommon::content_type($r,'text/html');
      $r->send_http_header;        $r->send_http_header;
      return OK;        return OK;
   }    }
   
   my %cachehash=();     my %cachehash=(); 
   my $multichoice=0;    my $multichoice=0;
   my %multichoicehash=();    my %multichoicehash=();
   my $redirecturl='';    my %prog_state=();
     my ($redirecturl,$redirectsymb,$enc,$anchor,$deeplinklevel);
   my $next='';    my $next='';
     my $hostname = $r->hostname();
   my @possibilities=();    my @possibilities=();
      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['postdata']);
   if (($ENV{'form.postdata'})&&($ENV{'request.course.fn'})) {    if (($env{'form.postdata'})&&($env{'request.course.fn'})) {
       $ENV{'form.postdata'}=~/(\w+)\:(.*)/;        my ($direction,$currenturl) = ($env{'form.postdata'}=~/(\w+)\:(.*)/);
       my $direction=$1;        if ($currenturl=~m|^/enc/|) {
       my $currenturl=$2;            $currenturl=&Apache::lonenc::unencrypted($currenturl);
         }
         $currenturl=~s/\.\d+\.(\w+)$/\.$1/;
         $currenturl=~s/^https?\:\/\///;
         $currenturl=~s/^[^\/]+//;
         my ($preupdatepos,$last,$reinitcheck);
         if ($direction eq 'return') {
             if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                       &GDBM_READER(),0640)) {
                 $last=$hash{'last_known'};
                 untie(%hash);
             }
         } elsif ($direction eq 'firstanswerable') {
             my $furl = &first_answerable_ressymb();
             my $usehttp = &check_http_req(\$furl,$hostname);
             if (($usehttp) && ($hostname ne '')) {
                 $furl='http://'.$hostname.$furl;
             } else {
                 $furl=&Apache::lonnet::absolute_url().$furl;
             }
             &Apache::loncommon::content_type($r,'text/html');
             $r->header_out(Location => $furl);
             return REDIRECT;
         } elsif ($direction eq 'endplacement') {
             &Apache::loncommon::content_type($r,'text/html');
             $r->send_http_header;
             $r->print(&Apache::lonplacementtest::showresult());
             return OK;
         }
         if ($env{'request.course.id'}) {
             # Check if course needs to be re-initialized
             my $loncaparev = $r->dir_config('lonVersion');
             ($reinitcheck,my @reinit) = &Apache::loncommon::needs_coursereinit($loncaparev);
             if ($reinitcheck eq 'switch') {
                 &Apache::loncommon::content_type($r,'text/html');
                 $r->send_http_header;
                 $r->print(&Apache::loncommon::check_release_result(@reinit));
                 return OK;
             } elsif ($reinitcheck eq 'update') {
                 my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                 my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                 $preupdatepos = &Apache::lonnet::symbread($currenturl);
                 unless ($direction eq 'return') {
                     if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                                   &GDBM_READER(),0640)) {
                         $last=$hash{'last_known'};
                         untie(%hash);
                     }
                 }
                 &Apache::loncommon::content_type($r,'text/html');
                 $r->send_http_header;
                 $r->print(&Apache::loncommon::start_page('Content Changed'));
                 my $preamble = '<div id="LC_update_'.$env{'request.course.id'}.'" class="LC_info">'.
                                '<br />'.
                                &mt('Your course session is being updated because of recent changes by course personnel.').
                                ' '.&mt('Please be patient').'.<br /></div>'.
                                '<div style="padding:0;clear:both;margin:0;border:0"></div>';
                 %prog_state = &Apache::lonhtmlcommon::Create_PrgWin($r,undef,$preamble);
                 &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,&mt('Updating course'));
                 my ($furl,$ferr) = &Apache::lonuserstate::readmap("$cdom/$cnum");
                 &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,&mt('Finished!'));
                 if ($ferr) {
                     &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
                     my $requrl = $r->uri;
                     $env{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";
                     $env{'user.reinit'} = 1;
                     return HTTP_NOT_ACCEPTABLE;
                 } else {
                     if ($last) {
                         my ($murl,$id,$fn)=&Apache::lonnet::decode_symb($last);
                         unless (&Apache::lonnet::symbverify($last,$fn)) {
                             undef($last);
                         }
                     }
                 }
             }
         }
         if ($direction eq 'firstres') {
     my $furl=&first_accessible_resource();
             my $usehttp = &check_http_req(\$furl,$hostname);
             if (($usehttp) && ($hostname ne '')) {
                 $furl='http://'.$hostname.$furl;
             } else {
                 $furl=&Apache::lonnet::absolute_url().$furl;
             }
             if ($reinitcheck eq 'update') {
                 &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
                 $r->print(&reinited_js($furl,$env{'request.course.id'},100));
                 $r->print(&Apache::loncommon::end_page());
                 return OK;
             } else {
         &Apache::loncommon::content_type($r,'text/html');
         $r->header_out(Location => $furl);
         return REDIRECT;
             }
         }
       if ($direction eq 'return') {        if ($direction eq 'return') {
 # -------------------------------------------------------- Return to last known  # -------------------------------------------------------- Return to last known
          my $last;           my ($newloc,$usehttp);
          if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.'_symb.db',           if (($last) && (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db',
                     &GDBM_READER,0640)) {                          &GDBM_READER(),0640))) {
      $last=$hash{'last_known'};              my ($murl,$id,$fn)=&Apache::lonnet::decode_symb($last);
              untie(%hash);      $id=$hash{'map_pc_'.&Apache::lonnet::clutter($murl)}.'.'.$id;
       $newloc=$hash{'src_'.$id};
       if ($newloc) {
                   $usehttp = &check_http_req(\$newloc,$hostname);
    if ($hash{'encrypted_'.$id}) { 
                       $newloc=&Apache::lonenc::encrypted($newloc);
                   }
                   if ($newloc =~ m{^(/adm/wrapper/ext/[^\#]+)(?:|(\#[^\#]+))$}) {
                       my ($url,$anchor) = ($1,$2);
                       if ($anchor) {
                           $newloc = $url.(($url=~/\?/)?'&':'?').'symb='.&escape($last).$anchor;
                       }
                   }
       } else {
    $newloc='/adm/navmaps';
       }
               untie %hash;
            } else {
       $newloc='/adm/navmaps';
          }           }
          my $newloc;           if (($usehttp) && ($hostname ne '')) {
          if ($last) {               $newloc='http://'.$hostname.$newloc;
             $newloc='/res/'.(split(/\_\_\_/,$last))[1];  
          } else {           } else {
     $newloc='/adm/noidea.html';               $newloc=&Apache::lonnet::absolute_url().$newloc
          }             }
  $r->content_type('text/html');           if ($reinitcheck eq 'update') {
          $r->header_out(Location =>                $r->print(&reinited_js($newloc,$env{'request.course.id'},100));
  'http://'.$ENV{'HTTP_HOST'}.$newloc);               $r->print(&Apache::loncommon::end_page());
                                               return OK;
          return REDIRECT;           } else {
        &Apache::loncommon::content_type($r,'text/html');
        $r->header_out(Location => $newloc);
        return REDIRECT;
            }
       }        }
       $currenturl=~s/^http\:\/\///;  #
       $currenturl=~s/^[^\/]+//;  # Is the current URL on the map? If not, start with last known URL
       unless ($currenturl=~/\/res\//) {  #
  my $last;  
          if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.'_symb.db',        unless (&Apache::lonnet::is_on_map($currenturl)) {
                     &GDBM_READER,0640)) {           if ($preupdatepos) {
      $last=$hash{'last_known'};               undef($preupdatepos);
            } elsif (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                               &GDBM_READER(),0640)) {
                $last=$hash{'last_known'};
              untie(%hash);               untie(%hash);
          }           }
          if ($last) {           if ($last) {
      $currenturl='/res/'.(split(/\_\_\_/,$last))[1];       $currenturl=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($last))[2]);
  } else {   } else {
      $r->content_type('text/html');               my $newloc = &Apache::lonnet::absolute_url().
              $r->header_out(Location =>                             '/adm/navmaps'; 
                                'http://'.$ENV{'HTTP_HOST'}.'/adm/noidea.html');               if ($reinitcheck eq 'update') {
              return REDIRECT;                   &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
                    $r->print(&reinited_js($newloc,$env{'request.course.id'},100));
                    $r->print(&Apache::loncommon::end_page());
                    return OK;
                } else {
            &Apache::loncommon::content_type($r,'text/html');
            $r->header_out(Location => $newloc); 
            return REDIRECT;
                }
          }           }
       }        }
 # ------------------------------------------- Do we have any idea where we are?  # ------------------------------------------- Do we have any idea where we are?
       my $position;        my $position;
       if ($position=Apache::lonnet::symbread($currenturl)) {        if ($preupdatepos) {
             $position = $preupdatepos;
         } else {
             $position=Apache::lonnet::symbread($currenturl);
         }
         if ($position) {
 # ------------------------------------------------------------------------- Yes  # ------------------------------------------------------------------------- Yes
   my ($mapurl,$mapnum,$thisurl)=split(/\_\_\_/,$position);    my ($startoutmap,$mapnum,$thisurl)=&Apache::lonnet::decode_symb($position);
           $cachehash{$thisurl}=$mapnum;            $cachehash{$startoutmap}{$thisurl}=[$thisurl,$mapnum];
             $cachehash{$startoutmap}{'last_known'}=
                                [&Apache::lonnet::declutter($currenturl),$mapnum];
   
 # ============================================================ Tie the big hash  # ============================================================ Tie the big hash
           if (tie(%hash,'GDBM_File',$ENV{'request.course.fn'}.'.db',            if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db',
                         &GDBM_READER,0640)) {                          &GDBM_READER(),0640)) {
               my $rid=$hash{'map_pc_/res/'.$mapurl}.'.'.$mapnum;                my $rid=$hash{'map_pc_'.&Apache::lonnet::clutter($startoutmap)}.
               my $next='';                        '.'.$mapnum;
               my $mincond=1;  
               my $posnext='';  # ------------------------------------------------- Move forward, backward, etc
               if ($direction eq 'forward') {                my $endupmap;
 # --------------------------------------------------------------------- Forward                ($next,$endupmap)=&move($rid,$startoutmap,$direction);
                   map {  # -------------------------------------- Do we have one and only one empty URL?
                       my $thiscond=  # We are now at at least one non-empty URL
       &Apache::lonnet::directcondval($hash{'condid_'.$hash{'undercond_'.$_}});  
                       if ($thiscond>=$mincond) {  
           if ($posnext) {  
              $posnext.=','.$_.':'.$thiscond;  
                           } else {  
                              $posnext=$_.':'.$thiscond;  
           }  
                           if ($thiscond>$mincond) { $mincond=$thiscond; }  
               }  
                   } split(/\,/,$hash{'to_'.$rid});  
                   map {  
                       my ($linkid,$condval)=split(/\:/,$_);  
                       if ($condval>=$mincond) {  
           $next=&addrid($next,$hash{'goesto_'.$linkid},  
                                 $hash{'condid_'.$hash{'undercond_'.$linkid}});  
                       }  
                   } split(/\,/,$posnext);  
               } elsif ($direction eq 'back') {  
 # ------------------------------------------------------------------- Backwards  
                   map {  
                       my $thiscond=  
       &Apache::lonnet::directcondval($hash{'condid_'.$hash{'undercond_'.$_}});  
                       if ($thiscond>=$mincond) {  
           if ($posnext) {  
              $posnext.=','.$_.':'.$thiscond;  
                           } else {  
                              $posnext=$_.':'.$thiscond;  
           }  
                           if ($thiscond>$mincond) { $mincond=$thiscond; }  
               }  
                   } split(/\,/,$hash{'from_'.$rid});  
                   map {  
                       my ($linkid,$condval)=split(/\:/,$_);  
                       if ($condval>=$mincond) {  
           $next=&addrid($next,$hash{'comesfrom_'.$linkid},  
                                 $hash{'condid_'.$hash{'undercond_'.$linkid}});  
                       }  
                   } split(/\,/,$posnext);  
        } elsif ($direction eq 'up') {  
 # -------------------------------------------------------------------------- Up  
               } elsif ($direction eq 'down') {  
 # ------------------------------------------------------------------------ Down  
       }  
 # ----------------------------------------------------- Check out possibilities  # ----------------------------------------------------- Check out possibilities
               if ($next) {                if ($next) {
                   @possibilities=split(/\,/,$next);                    @possibilities=split(/\,/,$next);
                   if ($#possibilities==0) {                    if ($#possibilities==0) {
 # ---------------------------------------------- Only one possibility, redirect  # ---------------------------------------------- Only one possibility, redirect
               $redirecturl=$hash{'src_'.$next};                ($redirecturl,$redirectsymb,$enc,$anchor)=&hash_src($next);
                       $cachehash{&Apache::lonnet::declutter($redirecturl)}                        $cachehash{$endupmap}{$redirecturl}=
                                  =(split(/\./,$next))[1];    [$redirecturl,(split(/\./,$next))[1]];
                   } else {                    } else {
 # ------------------------ There are multiple possibilities for a next resource  # ------------------------ There are multiple possibilities for a next resource
                       $multichoice=1;                        $multichoice=1;
                       map {        foreach my $id (@possibilities) {
   $multichoicehash{'src_'.$_}=$hash{'src_'.$_};    $multichoicehash{'src_'.$id}=$hash{'src_'.$id};
                           $multichoicehash{'title_'.$_}=$hash{'title_'.$_};                            $multichoicehash{'title_'.$id}=$hash{'title_'.$id};
                           $multichoicehash{'type_'.$_}=$hash{'type_'.$_};                            $multichoicehash{'type_'.$id}=$hash{'type_'.$id};
                           $cachehash                            (my $first, my $second) = $id =~ /(\d+).(\d+)/;
                             {&Apache::lonnet::declutter(                            my $symbSrc = Apache::lonnet::declutter($hash{'src_'.$id});
       $multichoicehash                            $multichoicehash{'symb_'.$id} = 
                                                          {'src_'.$_}                                Apache::lonnet::declutter($hash{'map_id_'.$first}.'___'.
                                                        )}                                                          $second.'___'.$symbSrc);
                                  =(split(/\./,$_))[1];                                                           
                       } @possibilities;                            my ($choicemap,$choiceres)=split(/\./,$id);
     my $map=&Apache::lonnet::declutter($hash{'src_'.$choicemap});
     my $url=$multichoicehash{'src_'.$id};
                             $cachehash{$map}{$url}=[$url,$choiceres];
                         }
                   }                    }
       } else {        } else {
 # -------------------------------------------------------------- No place to go  # -------------------------------------------------------------- No place to go
                   $multichoice=-1;                    $multichoice=-1;
                     if ($position && $env{'request.deeplink.login'}) {
                         my ($map,$resid,$url) = &Apache::lonnet::decode_symb($position);
                         my $mapid = $hash{'map_pc_'.&Apache::lonnet::clutter($map)};
                         my $position_deeplink = $hash{'deeplinkonly_'.$mapid.'.'.$resid};
                         if ($position_deeplink) {
                             (my $value,$deeplinklevel) = map { &unescape($_); } 
                                                          split(/:/,$position_deeplink);
                         }
                     }
               }                }
 # ----------------- The program must come past this point to untie the big hash  # ----------------- The program must come past this point to untie the big hash
       untie(%hash);        untie(%hash);
 # --------------------------------------------------------- Store position info  # --------------------------------------------------------- Store position info
               $cachehash{'last_direction'}=$direction;                $cachehash{$startoutmap}{'last_direction'}=[$direction,'notasymb'];
               $cachehash{'last_known'}=&Apache::lonnet::declutter($currenturl);                foreach my $thismap (keys(%cachehash)) {
               &Apache::lonnet::symblist($mapurl,%cachehash);    my $mapnum=$cachehash{$thismap}->{'mapnum'};
     delete($cachehash{$thismap}->{'mapnum'});
     &Apache::lonnet::symblist($thismap,
       %{$cachehash{$thismap}});
         }
 # ============================================== Do not return before this line  # ============================================== Do not return before this line
               if ($redirecturl) {                if ($redirecturl) {
 # ----------------------------------------------------- There is a URL to go to  # ----------------------------------------------------- There is a URL to go to
   $r->content_type('text/html');    if ($direction eq 'forward') {
                   $r->header_out(Location =>                        &Apache::lonnet::linklog($currenturl,$redirecturl);
                                 'http://'.$ENV{'HTTP_HOST'}.$redirecturl);    }
                   return REDIRECT;    if ($direction eq 'back') {
                        &Apache::lonnet::linklog($redirecturl,$currenturl);
     }
   # ------------------------------------- Check for and display critical messages
                     my ($redirect, $url) = &Apache::loncommon::critical_redirect(300,'flip');
                     unless ($redirect) {
                         my $usehttp = &check_http_req(\$redirecturl,$hostname);
                         if (($usehttp) && ($hostname ne '')) {
                             $url='http://'.$hostname.$redirecturl;
                         } else {
                             $url=&Apache::lonnet::absolute_url().$redirecturl;
                         }
                         my $addanchor;
                         if (($anchor ne '') && (!$enc || $env{'request.role.adv'})) {
                             $addanchor = 1;
                             $url =~ s/\#.+$//;
                         }
                         $url = &add_get_param($url, { 'symb' => $redirectsymb});
                         if ($addanchor) {
                             $url .= $anchor;
                         }
                     }
                     if ($reinitcheck eq 'update') {
                         &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
                         $r->print(&reinited_js($url,$env{'request.course.id'},100)); 
                         $r->print(&Apache::loncommon::end_page());
                         return OK;
                     } else {
                         &Apache::loncommon::content_type($r,'text/html');
                         $r->header_out(Location => $url);
                         return REDIRECT;
                     }
       } else {        } else {
 # --------------------------------------------------------- There was a problem  # --------------------------------------------------------- There was a problem
                   $r->content_type('text/html');                    &Apache::loncommon::content_type($r,'text/html');
                   $r->send_http_header;                    $r->send_http_header;
     my %lt=&Apache::lonlocal::texthash('title' => 'End of Sequence',
                                                        'deeplink' => 'No link available',
                                                        'deeplinkres' =>
                                                        'Navigation to other content is unavailable when accessing content via deep-linking',
                                                        'deeplinkmap' =>
                                                        'You have reached the end of the sequence of available materials for access via deep-linking',
        'explain' =>
        'You have reached the end of the sequence of materials.',
        'back' => 'Go Back',
        'nav' => 'Course Contents',
        'wherenext' =>
        'There are several possibilities of where to go next',
        'pick' =>
        'Please click on the the resource you intend to access',
        'titleheader' => 'Title',
        'type' => 'Type',
                                                        'update' => 'Content updated',
                                                        'expupdate' => 'As a result of a recent update to the sequence of materials, it is not possible to complete the page flip.',
                                                        'gonav' => 'Go to the Contents page to select a resource to display.',
                                                        );
                     if (&Apache::loncommon::course_type() eq 'Community') {
                         $lt{'nav'} = &mt('Community Contents');
                     }
                   if ($#possibilities>0) {                    if ($#possibilities>0) {
         my $start_page=
     &Apache::loncommon::start_page('Multiple Resources');
                      $r->print(<<ENDSTART);                       $r->print(<<ENDSTART);
 <head><title>Choose Next Location</title></head>  $start_page
 <body bgcolor="#FFFFFF">  <h3>$lt{'wherenext'}</h3>
 <h1>LON-CAPA</h1>  
 There are several possibilities of where to go next.  
 <p>  <p>
 Please click on the the resource you intend to access:  $lt{'pick'}:
 <p>  <p>
 <table border=2>  <table border="2">
 <tr><th>Title</th><th>Type</th></tr>  <tr><th>$lt{'titleheader'}</th><th>$lt{'type'}</th></tr>
 ENDSTART  ENDSTART
                      map {                       foreach my $id (@possibilities) {
                           my $src = $multichoicehash{'src_'.$id};
                           my $usehttp = &check_http_req(\$src,$hostname);
                           if (($usehttp) && ($hostname ne '')) {
                               $src = 'http://'.$hostname.$src;
                           }
                         $r->print(                          $r->print(
                               '<tr><td><a href="'.                                '<tr><td><a href="'.
                               $multichoicehash{'src_'.$_}.'">'.    &add_get_param($src,
                               $multichoicehash{'title_'.$_}.   {'symb' =>
                               '</a></td><td>'.$multichoicehash{'type_'.$_}.        $multichoicehash{'symb_'.$id},
     }).'">'.
                                 $multichoicehash{'title_'.$id}.
                                 '</a></td><td>'.$multichoicehash{'type_'.$id}.
       '</td></tr>');        '</td></tr>');
                      } @possibilities;                       }
                      $r->print('</table></body></html>');                       $r->print('</table>');
      return OK;  
                   } else {                    } else {
                      $r->print(<<ENDNONE);                        if ($reinitcheck) {
 <head><title>Choose Next Location</title></head>                            if (&Apache::loncommon::course_type() eq 'Community') {
 <body bgcolor="#FFFFFF">                                $r->print(
 <img src="/adm/lonKaputt/lonlogo_broken.gif" align=left>                                    &Apache::loncommon::start_page('Community Contents Updated'));
 <h1>Sorry!</h1>                            } else { 
 <h2>Next resource could not be identified.</h2>                                $r->print(
 </body>                                    &Apache::loncommon::start_page('Course Contents Updated'));
 </html>                            }
 ENDNONE                            $r->print('<h2>'.$lt{'update'}.'</h2>'
                      return OK;                                    .'<p>'.$lt{'expupdate'}.'<br />'
          }                                    .$lt{'gonav'}.'</p>');
      }                        } else {
                             if (($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') && 
                                 (!$env{'request.role.adv'})) {
                                 my ($score,$incomplete) = &Apache::lonplacementtest::check_completion(undef,undef,1); 
                                 if ($incomplete) {
                                     $r->print(&Apache::lonplacementtest::showincomplete($incomplete)); 
                                 } else {
                                     $r->print(&Apache::lonplacementtest::showresult(1));
                                 }
                             } else {
                                 $r->print(
                                     &Apache::loncommon::start_page('No Resource'));
                                 if ($deeplinklevel eq 'resource') {
                                     $r->print('<h2>'.$lt{'deeplink'}.'</h2>'
                                              .'<p>'.$lt{'deeplinkres'}.'</p>');
                                 } elsif ($deeplinklevel eq 'map') {
                                     $r->print('<h2>'.$lt{'title'}.'</h2>'
                                              .'<p>'.$lt{'deeplinkmap'}.'</p>');
                                 } else {
                                     $r->print('<h2>'.$lt{'title'}.'</h2>'
                                              .'<p>'.$lt{'explain'}.'</p>');
                                 }
                             }
                         }
     }
                     unless (($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') ||
                             ($env{'request.role.adv'})) {
                         if ($deeplinklevel) {
                             $r->print(
                                 &Apache::lonhtmlcommon::actionbox(
                                     ['<a href="/adm/flip?postdata=return:">'.$lt{'back'}.'</a>']));
                         } elsif ((!@possibilities) && ($reinitcheck))  {
                             $r->print(
                                 &Apache::lonhtmlcommon::actionbox(
                                     ['<a href="/adm/navmaps">'.$lt{'nav'}.'</a></li>'
                                     ]));
                         } else {
                             $r->print(
                                 &Apache::lonhtmlcommon::actionbox(
                                     ['<a href="/adm/flip?postdata=return:">'.$lt{'back'}.'</a></li>',
                                      '<a href="/adm/navmaps">'.$lt{'nav'}.'</a></li>'
                                     ]));
                         }
   
                     }
                     $r->print(&Apache::loncommon::end_page());
         
                     return OK;
         }
   } else {    } else {
 # ------------------------------------------------- Problem, could not tie hash  # ------------------------------------------------- Problem, could not tie hash
               $ENV{'user.error.msg'}="/adm/flip:bre:0:1:Course Data Missing";                if ($reinitcheck eq 'update') {
                     &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
                     $r->print(&Apache::loncommon::end_page());
                 } 
                 $env{'user.error.msg'}="/adm/flip:bre:0:1:Course Data Missing";
               return HTTP_NOT_ACCEPTABLE;                 return HTTP_NOT_ACCEPTABLE; 
           }            }
       } else {        } else {
 # ---------------------------------------- No, could not determine where we are  # ---------------------------------------- No, could not determine where we are
          $r->internal_redirect('/adm/ambiguous');            my $newloc = '/adm/ambiguous';
             if ($reinitcheck eq 'update') {
                 &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
                 $r->print(&reinited_js($newloc,$env{'request.course.id'},100));
                 $r->print(&Apache::loncommon::end_page());
             } else {
         $r->internal_redirect($newloc);
             }
             return OK;
       }        }
   } else {    } else {
 # -------------------------- Class was not initialized or page fliped strangely  # -------------------------- Class was not initialized or page fliped strangely
       $ENV{'user.error.msg'}="/adm/flip:bre:0:0:Choose Course";        $env{'user.error.msg'}="/adm/flip:bre:0:0:Choose Course";
       return HTTP_NOT_ACCEPTABLE;         return HTTP_NOT_ACCEPTABLE; 
   }     } 
 }  }
Line 258  ENDNONE Line 891  ENDNONE
 1;  1;
 __END__  __END__
   
   =pod
   
   =head1 NAME
   
   Apache::lonpageflip
   
   =head1 SYNOPSIS
   
   Deals with forward, backward, and other page flips.
   
   This is part of the LearningOnline Network with CAPA project
   described at http://www.lon-capa.org.
   
   =head1 OVERVIEW
   
   (empty)
   
   =head1 SUBROUTINES
   
   =over cleanup()
   
   =item addrid()
   
   =item fullmove()
   
   =item hash_src()
   
   =item move()
   
   =item get_next_possible_move()
   
   =item first_accessible_resource()
   
   =item handler()
   
   =back
   
   =cut
   
   
   

Removed from v.1.13  
changed lines
  Added in v.1.110


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.