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

version 1.1, 2000/10/03 20:33:06 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 Gerd Kortemeyer  # LON-CAPA is free software; you can redistribute it and/or modify
   # 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 Apache::Constants qw(:common :http);  use LONCAPA;
 use Apache::lonnet();  use Apache::Constants qw(:common :http REDIRECT);
   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;
   
 # -------------------------------------------------------------- Module Globals  # ========================================================== Module Global Hash
     
 my %hash;  my %hash;
 my @rows;  
   
 # ------------------------------------------------------------------ Euclid gcd  
   
 sub euclid {  sub cleanup {
     my ($e,$f)=@_;      if (tied(%hash)){
     my $a; my $b; my $r;   &Apache::lonnet::logthis('Cleanup pageflip: hash');
     if ($e>$f) { $b=$e; $r=$f; } else { $r=$e; $b=$f; }          unless (untie(%hash)) {
     while ($r!=0) {      &Apache::lonnet::logthis('Failed cleanup pageflip: hash');
  $a=$b; $b=$r;          }
         $r=$a%$b;  
     }  
     return $b;  
 }  
   
 # ------------------------------------------------------------ Build page table  
   
 sub tracetable {  
     my ($sofar,$rid,$beenhere)=@_;  
     my $further=$sofar;  
     unless ($beenhere=~/\&$rid\&/) {  
        $beenhere.=$rid.'&';    
   
        if (defined($hash{'is_map_'.$rid})) {  
            if ((defined($hash{'map_start_'.$hash{'src_'.$rid}})) &&  
                (defined($hash{'map_finish_'.$hash{'src_'.$rid}}))) {  
               my $frid=$hash{'map_finish_'.$hash{'src_'.$rid}};  
       $sofar=  
                 &tracetable($sofar,$hash{'map_start_'.$hash{'src_'.$rid}},  
                 '&'.$frid.'&');  
               $sofar++;  
               if ($hash{'src_'.$frid}) {  
                my $brepriv=&Apache::lonnet::allowed('bre',$hash{'src_'.$frid});  
                if (($brepriv eq '2') || ($brepriv eq 'F')) {  
                  if (defined($rows[$sofar])) {  
                    $rows[$sofar].='&'.$frid;  
                  } else {  
                    $rows[$sofar]=$frid;  
                  }  
        }  
       }  
    }  
        } else {  
           $sofar++;  
           if ($hash{'src_'.$rid}) {  
            my $brepriv=&Apache::lonnet::allowed('bre',$hash{'src_'.$rid});  
            if (($brepriv eq '2') || ($brepriv eq 'F')) {  
              if (defined($rows[$sofar])) {  
                $rows[$sofar].='&'.$rid;  
              } else {  
                $rows[$sofar]=$rid;  
              }  
    }  
           }  
        }  
   
        if (defined($hash{'to_'.$rid})) {  
           map {  
               my $now=&tracetable($sofar,$hash{'goesto_'.$_},$beenhere);  
               if ($now>$further) { $further=$now; }  
           } split(/\,/,$hash{'to_'.$rid});  
        }  
     }      }
     return $further;      return OK;
 }  }
   
 # ================================================================ Main Handler  sub addrid {
       my ($current,$new,$condid)=@_;
 sub handler {      unless ($condid) { $condid=0; }
   my $r=shift;  
    if ($current) {
 # ------------------------------------------- Set document type for header only      $current.=','.$new;
           } else {
               $current=''.$new;
           }
   
 #  if ($r->headers_only) {      return $current;
      $r->content_type('text/html');  }
      $r->send_http_header;  
 #     return OK;  
 #  }  
   
   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);
   }
   
   $r->print('<html><body>'.$ENV{'form.postdata'}.'</body></html>');  sub get_next_possible_move {
   return OK;      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(); 
       }
   }
   
   my $requrl=$r->uri;  sub check_http_req {
 # ----------------------------------------------------------------- Tie db file      my ($srcref,$hostname) = @_;
   if ($ENV{'request.course.fn'}) {      return unless (ref($srcref) eq 'SCALAR');
       my $fn=$ENV{'request.course.fn'};      my $usehttp;
       if (-e "$fn.db") {      if ($env{'request.course.id'}) {
           if (tie(%hash,'GDBM_File',"$fn.db",&GDBM_READER,0640)) {          my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
 # ------------------------------------------------------------------- Hash tied          my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
               my $firstres=$hash{'map_start_'.$requrl};          if (($$srcref =~ m{^\Q/public/$cdom/$cnum/syllabus\E($|\?)}) &&
               my $lastres=$hash{'map_finish_'.$requrl};              ($ENV{'SERVER_PORT'} == 443) &&
               if (($firstres) && ($lastres)) {              ($env{'course.'.$env{'request.course.id'}.'.externalsyllabus'} =~ m{^http://})) {
 # ----------------------------------------------------------------- Render page              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;
   }
   
                   @rows=();  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
   }
   
                   &tracetable(0,$firstres,'&'.$lastres.'&');  sub get_deeplink_login_pc {
                   if ($hash{'src_'.$lastres}) {      my $deeplink_login_pc;
                      my $brepriv=      if (($env{'request.deeplink.login'}) && ($env{'request.course.id'})) {
                         &Apache::lonnet::allowed('bre',$hash{'src_'.$lastres});          my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                      if (($brepriv eq '2') || ($brepriv eq 'F')) {          my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                         $rows[$#rows+1]=''.$lastres;          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;
   }
   
 # ------------------------------------------------------------ Add to symb list  # ================================================================ Main Handler
   
                   my $i;  sub handler {
                   my %symbhash=();     my $r=shift;
                   for ($i=0;$i<=$#rows;$i++) {  
      if ($rows[$i]) {  
                         my @colcont=split(/\&/,$rows[$i]);  
                         map {  
                            $symbhash{$hash{'src_'.$_}}='';  
         } @colcont;  
      }  
   }  
                   &Apache::lonnet::symblist($requrl,%symbhash);  
   
 # ------------------------------------------------------------------ Page parms  # ------------------------------------------- Set document type for header only
   
                   my $j;    if ($r->header_only) {
                   my $lcm=1;        &Apache::loncommon::content_type($r,'text/html');
                   my $contents=0;        $r->send_http_header;
                   my $nforms=0;        return OK;
                       }
                   my %ssibody=();  
                   my %ssibgcolor=();  
                   my %ssitext=();  
                   my %ssilink=();  
                   my %ssivlink=();  
                   my %ssialink=();  
                   my %cellemb=();  
   
                   my $allscript='';  
                   my $allmeta='';  
   
                   my $isxml=0;  
                   my $xmlheader='';  
                   my $xmlbody='';  
   
 # --------------------------------------------- Get SSI output, post parameters  
   
                   for ($i=0;$i<=$#rows;$i++) {  
      if ($rows[$i]) {  
       $contents++;  
                       my @colcont=split(/\&/,$rows[$i]);  
                       $lcm*=($#colcont+1)/euclid($lcm,($#colcont+1));  
                       map {  
                           my $src=$hash{'src_'.$_};  
                           $src=~/\.(\w+)$/;  
                           $cellemb{$_}=Apache::lonnet::fileembstyle($1);  
                           if ($cellemb{$_} eq 'ssi') {  
 # --------------------------------------------------------- This is an SSI cell  
       my $prefix=$_.'_';  
                               my %posthash=('request.prefix' => $prefix);  
                               if (($ENV{'form.'.$prefix.'submit'})   
                                || ($ENV{'form.all_submit'})) {  
                                map {  
   if ($_=~/^form.$prefix/) {  
       my $name=$_;  
                                       $name=~s/^form.$prefix//;  
                                       $posthash{$name}=$ENV{$_};  
                                   }  
                                } keys %ENV;  
       }  
                               my $output=Apache::lonnet::ssi($src,%posthash);  
                               my $parser=HTML::TokeParser->new(\$output);  
                               my $token;  
                               my $bodydef=0;  
                               my $thisxml=0;  
                               if ($output=~/\?xml/) {  
                                  $isxml=1;  
                                  $thisxml=1;  
                                  $output=~  
          /((?:\<(?:\?xml|\!DOC|html)[^\>]*(?:\>|\>\]\>)\s*)+)\<body[^\>]*\>/si;  
                                  $xmlheader=$1;  
       }  
                               while (($bodydef==0) &&  
                                      ($token=$parser->get_token)) {  
   if ($token->[1] eq 'body') {  
       $bodydef=1;  
                                       $ssibgcolor{$_}=$token->[2]->{'bgcolor'};  
                                       $ssitext{$_}=$token->[2]->{'text'};  
                                       $ssilink{$_}=$token->[2]->{'link'};  
                                       $ssivlink{$_}=$token->[2]->{'vlink'};  
                                       $ssialink{$_}=$token->[2]->{'alink'};  
                                       if ($thisxml) {  
   $xmlbody=$token->[4];  
                                       }  
                                   }  
                                   if ($token->[1] eq 'meta') {  
       $allmeta.="\n".$token->[4].'</meta>';  
                                   }  
                                   if ($token->[1] eq 'script') {  
       $allscript.="\n\n"  
                                                 .$parser->get_text('/script');  
                                   }  
                               }  
                               if ($output=~/\<body[^\>]*\>(.*)/si) {  
                                  $output=$1;   
                               }  
                               $output=~s/\<\/body\>.*//si;  
                               if ($output=~/\<form/si) {  
   $nforms++;  
                                   $output=~s/\<form[^\>]*\>//gsi;  
                                   $output=~s/\<\/form[^\>]*\>//gsi;  
                               }  
       $ssibody{$_}=$output;  
   
 # ---------------------------------------------------------------- End SSI cell    my %cachehash=(); 
                           }    my $multichoice=0;
                       } @colcont;    my %multichoicehash=();
                      }     my %prog_state=();
     my ($redirecturl,$redirectsymb,$enc,$anchor,$deeplinklevel);
     my $next='';
     my $hostname = $r->hostname();
     my @possibilities=();
      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['postdata']);
     if (($env{'form.postdata'})&&($env{'request.course.fn'})) {
         my ($direction,$currenturl) = ($env{'form.postdata'}=~/(\w+)\:(.*)/);
         if ($currenturl=~m|^/enc/|) {
             $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);
                   }                    }
                   unless ($contents) {                }
                       $r->content_type('text/html');                &Apache::loncommon::content_type($r,'text/html');
                       $r->send_http_header;                $r->send_http_header;
                       $r->print('<html><body>Empty page.</body></html>');                $r->print(&Apache::loncommon::start_page('Content Changed'));
                   } else {                my $preamble = '<div id="LC_update_'.$env{'request.course.id'}.'" class="LC_info">'.
 # ------------------------------------------------------------------ Build page                               '<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') {
   # -------------------------------------------------------- Return to last known
            my ($newloc,$usehttp);
            if (($last) && (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db',
                           &GDBM_READER(),0640))) {
               my ($murl,$id,$fn)=&Apache::lonnet::decode_symb($last);
       $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';
            }
            if (($usehttp) && ($hostname ne '')) {
                $newloc='http://'.$hostname.$newloc;
            } else {
                $newloc=&Apache::lonnet::absolute_url().$newloc
            }
            if ($reinitcheck eq 'update') {
                $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;
            }
         }
   #
   # Is the current URL on the map? If not, start with last known URL
   #
   
 # ---------------------------------------------------------------- Send headers        unless (&Apache::lonnet::is_on_map($currenturl)) {
                       if ($isxml) {           if ($preupdatepos) {
   $r->content_type('text/xml');               undef($preupdatepos);
                           $r->send_http_header;           } elsif (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
                           $r->print($xmlheader);                              &GDBM_READER(),0640)) {
       } else {               $last=$hash{'last_known'};
                           $r->content_type('text/html');               untie(%hash);
                           $r->send_http_header;           }
                           $r->print('<html>');           if ($last) {
       }       $currenturl=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($last))[2]);
 # ------------------------------------------------------------------------ Head   } else {
                       $r->print("\n<head>\n".$allmeta);               my $newloc = &Apache::lonnet::absolute_url().
                       if ($allscript) {                            '/adm/navmaps'; 
   $r->print("\n<script>\n".$allscript."\n</script>\n");               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());
                    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?
         my $position;
         if ($preupdatepos) {
             $position = $preupdatepos;
         } else {
             $position=Apache::lonnet::symbread($currenturl);
         }
         if ($position) {
   # ------------------------------------------------------------------------- Yes
     my ($startoutmap,$mapnum,$thisurl)=&Apache::lonnet::decode_symb($position);
             $cachehash{$startoutmap}{$thisurl}=[$thisurl,$mapnum];
             $cachehash{$startoutmap}{'last_known'}=
                                [&Apache::lonnet::declutter($currenturl),$mapnum];
   
   # ============================================================ Tie the big hash
             if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db',
                           &GDBM_READER(),0640)) {
                 my $rid=$hash{'map_pc_'.&Apache::lonnet::clutter($startoutmap)}.
                         '.'.$mapnum;
   
   # ------------------------------------------------- Move forward, backward, etc
                 my $endupmap;
                 ($next,$endupmap)=&move($rid,$startoutmap,$direction);
   # -------------------------------------- Do we have one and only one empty URL?
   # We are now at at least one non-empty URL
   # ----------------------------------------------------- Check out possibilities
                 if ($next) {
                     @possibilities=split(/\,/,$next);
                     if ($#possibilities==0) {
   # ---------------------------------------------- Only one possibility, redirect
                 ($redirecturl,$redirectsymb,$enc,$anchor)=&hash_src($next);
                         $cachehash{$endupmap}{$redirecturl}=
     [$redirecturl,(split(/\./,$next))[1]];
                     } else {
   # ------------------------ There are multiple possibilities for a next resource
                         $multichoice=1;
         foreach my $id (@possibilities) {
     $multichoicehash{'src_'.$id}=$hash{'src_'.$id};
                             $multichoicehash{'title_'.$id}=$hash{'title_'.$id};
                             $multichoicehash{'type_'.$id}=$hash{'type_'.$id};
                             (my $first, my $second) = $id =~ /(\d+).(\d+)/;
                             my $symbSrc = Apache::lonnet::declutter($hash{'src_'.$id});
                             $multichoicehash{'symb_'.$id} = 
                                 Apache::lonnet::declutter($hash{'map_id_'.$first}.'___'.
                                                           $second.'___'.$symbSrc);
                                                            
                             my ($choicemap,$choiceres)=split(/\./,$id);
     my $map=&Apache::lonnet::declutter($hash{'src_'.$choicemap});
     my $url=$multichoicehash{'src_'.$id};
                             $cachehash{$map}{$url}=[$url,$choiceres];
                         }
                     }
         } else {
   # -------------------------------------------------------------- No place to go
                     $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);
                       }                        }
                       $r->print("\n</head>\n");                    }
 # ------------------------------------------------------------------ Start body                }
                       if ($isxml) {  # ----------------- The program must come past this point to untie the big hash
                           $r->print($xmlbody);        untie(%hash);
   # --------------------------------------------------------- Store position info
                 $cachehash{$startoutmap}{'last_direction'}=[$direction,'notasymb'];
                 foreach my $thismap (keys(%cachehash)) {
     my $mapnum=$cachehash{$thismap}->{'mapnum'};
     delete($cachehash{$thismap}->{'mapnum'});
     &Apache::lonnet::symblist($thismap,
       %{$cachehash{$thismap}});
         }
   # ============================================== Do not return before this line
                 if ($redirecturl) {
   # ----------------------------------------------------- There is a URL to go to
     if ($direction eq 'forward') {
                        &Apache::lonnet::linklog($currenturl,$redirecturl);
     }
     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 {                        } else {
   $r->print('<body bgcolor="#FFFFFF">');                            $url=&Apache::lonnet::absolute_url().$redirecturl;
                         }
                         my $addanchor;
                         if (($anchor ne '') && (!$enc || $env{'request.role.adv'})) {
                             $addanchor = 1;
                             $url =~ s/\#.+$//;
                       }                        }
 # ------------------------------------------------------------------ Start form                        $url = &add_get_param($url, { 'symb' => $redirectsymb});
                       if ($nforms) {                        if ($addanchor) {
   $r->print('<form method="post" action="'.                            $url .= $anchor;
     $requrl.'">');  
                       }                        }
 # ----------------------------------------------------------------- Start table                    }
                       $r->print('<table cols="'.$lcm.'" border="0">');                    if ($reinitcheck eq 'update') {
                       for ($i=0;$i<=$#rows;$i++) {                        &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
  if ($rows[$i]) {                        $r->print(&reinited_js($url,$env{'request.course.id'},100)); 
                           $r->print("\n<tr>");                        $r->print(&Apache::loncommon::end_page());
                           my @colcont=split(/\&/,$rows[$i]);                        return OK;
                           my $avespan=$lcm/($#colcont+1);                    } else {
                           for ($j=0;$j<=$#colcont;$j++) {                        &Apache::loncommon::content_type($r,'text/html');
                               my $rid=$colcont[$j];                        $r->header_out(Location => $url);
                               $r->print('<td colspan="'.$avespan.'"');                        return REDIRECT;
                               if ($cellemb{$rid} eq 'ssi') {                    }
   if ($ssibgcolor{$rid}) {        } else {
                                      $r->print(' bgcolor="'.  # --------------------------------------------------------- There was a problem
                                                $ssibgcolor{$rid}.'"');                    &Apache::loncommon::content_type($r,'text/html');
                                   }                    $r->send_http_header;
                                   $r->print('><font');    my %lt=&Apache::lonlocal::texthash('title' => 'End of Sequence',
                                   if ($ssitext{$rid}) {                                                       'deeplink' => 'No link available',
      $r->print(' text="'.$ssitext{$rid}.'"');                                                       'deeplinkres' =>
                                   }                                                       'Navigation to other content is unavailable when accessing content via deep-linking',
                                   if ($ssilink{$rid}) {                                                       'deeplinkmap' =>
      $r->print(' link="'.$ssilink{$rid}.'"');                                                       'You have reached the end of the sequence of available materials for access via deep-linking',
                                   }       'explain' =>
                                   if ($ssitext{$rid}) {       'You have reached the end of the sequence of materials.',
      $r->print(' vlink="'.$ssivlink{$rid}.'"');       'back' => 'Go Back',
                                   }       'nav' => 'Course Contents',
                                   if ($ssialink{$rid}) {       'wherenext' =>
      $r->print(' alink="'.$ssialink{$rid}.'"');       'There are several possibilities of where to go next',
                                   }       'pick' =>
                                    'Please click on the the resource you intend to access',
                                   $r->print('>'.$ssibody{$rid}.'</font>');       'titleheader' => 'Title',
                               } elsif ($cellemb{$rid} eq 'img') {       'type' => 'Type',
                                   $r->print('><img src="'.                                                       'update' => 'Content updated',
                                     $hash{'src_'.$rid}.'"></img>');                                                       '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.',
                               $r->print('</td>');                                                       );
                     if (&Apache::loncommon::course_type() eq 'Community') {
                         $lt{'nav'} = &mt('Community Contents');
                     }
                     if ($#possibilities>0) {
         my $start_page=
     &Apache::loncommon::start_page('Multiple Resources');
                        $r->print(<<ENDSTART);
   $start_page
   <h3>$lt{'wherenext'}</h3>
   <p>
   $lt{'pick'}:
   <p>
   <table border="2">
   <tr><th>$lt{'titleheader'}</th><th>$lt{'type'}</th></tr>
   ENDSTART
                        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(
                                 '<tr><td><a href="'.
     &add_get_param($src,
    {'symb' =>
         $multichoicehash{'symb_'.$id},
     }).'">'.
                                 $multichoicehash{'title_'.$id}.
                                 '</a></td><td>'.$multichoicehash{'type_'.$id}.
         '</td></tr>');
                        }
                        $r->print('</table>');
                     } else {
                         if ($reinitcheck) {
                             if (&Apache::loncommon::course_type() eq 'Community') {
                                 $r->print(
                                     &Apache::loncommon::start_page('Community Contents Updated'));
                             } else { 
                                 $r->print(
                                     &Apache::loncommon::start_page('Course Contents Updated'));
                             }
                             $r->print('<h2>'.$lt{'update'}.'</h2>'
                                     .'<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>');
                                 }
                           }                            }
                           $r->print('</tr>');  
         }  
                       }                        }
                       $r->print("\n</table>");    }
 # ---------------------------------------------------------------- Submit, etc.                    unless (($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') ||
                       if ($nforms) {                            ($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(                            $r->print(
                   '<input name="all_submit" value="Submit All" type="'.                                &Apache::lonhtmlcommon::actionbox(
   (($nforms>1)?'submit':'hidden').'"></input></form>');                                    ['<a href="/adm/flip?postdata=return:">'.$lt{'back'}.'</a></li>',
                                      '<a href="/adm/navmaps">'.$lt{'nav'}.'</a></li>'
                                     ]));
                       }                        }
                       $r->print('</body></html>');  
 # -------------------------------------------------------------------- End page                    }
                   }                                      $r->print(&Apache::loncommon::end_page());
 # ------------------------------------------------------------- End render page        
               } else {                    return OK;
                   $r->content_type('text/html');        }
                   $r->send_http_header;    } else {
   $r->print('<html><body>Page undefined.</body></html>');  # ------------------------------------------------- Problem, could not tie hash
               }                if ($reinitcheck eq 'update') {
 # ------------------------------------------------------------------ Untie hash                    &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
               unless (untie(%hash)) {                    $r->print(&Apache::loncommon::end_page());
                    &Apache::lonnet::logthis("<font color=blue>WARNING: ".                } 
                        "Could not untie coursemap $fn (browse).</font>");                 $env{'user.error.msg'}="/adm/flip:bre:0:1:Course Data Missing";
               }                return HTTP_NOT_ACCEPTABLE; 
 # -------------------------------------------------------------------- All done  
       return OK;  
 # ----------------------------------------------- Errors, hash could no be tied  
           }            }
       }         } else {
   }  # ---------------------------------------- No, could not determine where we are
   $ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";            my $newloc = '/adm/ambiguous';
   return HTTP_NOT_ACCEPTABLE;             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 {
   # -------------------------- Class was not initialized or page fliped strangely
         $env{'user.error.msg'}="/adm/flip:bre:0:0:Choose Course";
         return HTTP_NOT_ACCEPTABLE; 
     } 
 }  }
   
 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.1  
changed lines
  Added in v.1.110


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