File:  [LON-CAPA] / rat / lonpageflip.pm
Revision 1.88: download - view: text, annotated - select for diffs
Sat Mar 14 22:26:50 2015 UTC (9 years, 2 months ago) by raeburn
Branches: MAIN
CVS tags: HEAD
- $direction and $currenturl bound to regexp for $env{'form.postdata'}.

    1: # The LearningOnline Network with CAPA
    2: #
    3: # Page flip handler
    4: #
    5: # $Id: lonpageflip.pm,v 1.88 2015/03/14 22:26:50 raeburn Exp $
    6: #
    7: # Copyright Michigan State University Board of Trustees
    8: #
    9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   10: #
   11: # LON-CAPA is free software; you can redistribute it and/or modify
   12: # it under the terms of the GNU General Public License as published by
   13: # the Free Software Foundation; either version 2 of the License, or
   14: # (at your option) any later version.
   15: #
   16: # LON-CAPA is distributed in the hope that it will be useful,
   17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   19: # GNU General Public License for more details.
   20: #
   21: # You should have received a copy of the GNU General Public License
   22: # along with LON-CAPA; if not, write to the Free Software
   23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   24: #
   25: # /home/httpd/html/adm/gpl.txt
   26: #
   27: # http://www.lon-capa.org/
   28: #
   29: 
   30: 
   31: 
   32: package Apache::lonpageflip;
   33: 
   34: use strict;
   35: use LONCAPA;
   36: use Apache::Constants qw(:common :http REDIRECT);
   37: use Apache::lonnet;
   38: use Apache::loncommon();
   39: use Apache::lonuserstate;
   40: use Apache::lonlocal;
   41: use HTML::TokeParser;
   42: use GDBM_File;
   43: 
   44: # ========================================================== Module Global Hash
   45:   
   46: my %hash;
   47: 
   48: sub cleanup {
   49:     if (tied(%hash)){
   50: 	&Apache::lonnet::logthis('Cleanup pageflip: hash');
   51:         unless (untie(%hash)) {
   52: 	    &Apache::lonnet::logthis('Failed cleanup pageflip: hash');
   53:         }
   54:     }
   55:     return OK;
   56: }
   57: 
   58: sub addrid {
   59:     my ($current,$new,$condid)=@_;
   60:     unless ($condid) { $condid=0; }
   61: 
   62: 	if ($current) {
   63: 	    $current.=','.$new;
   64:         } else {
   65:             $current=''.$new;
   66:         }
   67: 
   68:     return $current;
   69: }
   70: 
   71: sub fullmove {
   72:     my ($rid,$mapurl,$direction)=@_;
   73:     if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db',
   74:                         &GDBM_READER(),0640)) {
   75: 	($rid,$mapurl)=&move($rid,$mapurl,$direction);
   76:         untie(%hash);
   77:     }
   78:     return($rid,$mapurl);
   79: }
   80: 
   81: sub hash_src {
   82:     my ($id)=@_;
   83:     my ($mapid,$resid)=split(/\./,$id);
   84:     my $symb=&Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},
   85: 					  $resid,$hash{'src_'.$id});
   86:     if ($hash{'encrypted_'.$id}) {
   87: 	return (&Apache::lonenc::encrypted($hash{'src_'.$id}),
   88: 		&Apache::lonenc::encrypted($symb));
   89:     }
   90:     return ($hash{'src_'.$id},$symb);
   91: }
   92: 
   93: sub move {
   94:     my ($next,$endupmap,$direction) = @_;
   95:     my $safecount=0;
   96:     my $allowed=0;
   97:     do {
   98: 	($next,$endupmap)=&get_next_possible_move($next,$endupmap,$direction);
   99: 
  100: 	my $url = $hash{'src_'.$next};
  101: 	my ($mapid,$resid)=split(/\./,$next);
  102: 	my $symb = &Apache::lonnet::encode_symb($hash{'map_id_'.$mapid},
  103: 						$resid,$url);
  104: 	if ($url eq '' || $symb eq '') {
  105: 	    $allowed = 0;
  106: 	} else {
  107: 	    my $priv = &Apache::lonnet::allowed('bre',$url,$symb);
  108: 	    $allowed = (($priv eq 'F') || ($priv eq '2'));
  109: 	}
  110: 	$safecount++;
  111:     } while (   ($next)
  112: 	     && ($next!~/\,/)
  113: 	     && (
  114: 		    (!$hash{'src_'.$next})
  115: 		 || (
  116: 		        (!$env{'request.role.adv'})
  117: 		     &&  $hash{'randomout_'.$next}
  118: 		    )
  119: 		 || (!$allowed)
  120: 		)
  121: 	     && ($safecount<10000));
  122: 
  123:     return ($next,$endupmap);
  124: }
  125: 
  126: sub get_next_possible_move {
  127:     my ($rid,$mapurl,$direction)=@_;
  128:     my $startoutrid=$rid;
  129: 
  130:     my $next='';
  131: 
  132:               my $mincond=1;
  133:               my $posnext='';
  134:               if ($direction eq 'forward') {
  135: # --------------------------------------------------------------------- Forward
  136:                   while ($hash{'type_'.$rid} eq 'finish') {
  137: 	             $rid=$hash{'ids_'.$hash{'map_id_'.(split(/\./,$rid))[0]}};
  138:                   }
  139: 		  foreach my $id (split(/\,/,$hash{'to_'.$rid})) {
  140: 		     my $condition= $hash{'conditions_'.$hash{'goesto_'.$id}};
  141: 		     my $rescond  = &Apache::lonnet::docondval($condition);
  142: 		     my $linkcond = &Apache::lonnet::directcondval($hash{'condid_'.$hash{'undercond_'.$id}});
  143: 		     my $thiscond = ($rescond<$linkcond)?$rescond:$linkcond;
  144: 		     if ($thiscond>=$mincond) {
  145: 		          if ($posnext) {
  146: 		             $posnext.=','.$id.':'.$thiscond;
  147:                           } else {
  148:                              $posnext=$id.':'.$thiscond;
  149: 		          }
  150:                           if ($thiscond>$mincond) { $mincond=$thiscond; }
  151: 	              }
  152:                   } 
  153: 		  foreach my $id (split(/\,/,$posnext))  {
  154:                       my ($linkid,$condval)=split(/\:/,$id);
  155:                       if ($condval>=$mincond) {
  156: 		          $next=&addrid($next,$hash{'goesto_'.$linkid},
  157:                                 $hash{'condid_'.$hash{'undercond_'.$linkid}});
  158:                       }
  159:                   }
  160:                   if ($hash{'is_map_'.$next}) {
  161: # This jumps to the beginning of a new map (going down level)
  162:                       if (
  163:       $hash{'map_type_'.$hash{'map_pc_'.$hash{'src_'.$next}}} eq 'sequence') {
  164: 			  $mapurl=$hash{'src_'.$next};
  165: 			  $next=$hash{'map_start_'.$hash{'src_'.$next}};
  166:                      } elsif (
  167: # This jumps back up from an empty sequence, to a page up one level
  168:                          $hash{'map_type_'.$hash{'map_pc_'.$hash{'src_'.$next}}} eq 'page') {
  169:                          $mapurl=$hash{'map_id_'.(split(/\./,$next))[0]};
  170:                      }
  171:                   } elsif 
  172:                     ((split(/\./,$startoutrid))[0]!=(split(/\./,$next))[0]) {
  173: # This comes up from a map (coming up one level);
  174: 		      $mapurl=$hash{'map_id_'.(split(/\./,$next))[0]};
  175: 		  }
  176:               } elsif ($direction eq 'back') {
  177: # ------------------------------------------------------------------- Backwards
  178:                  while ($hash{'type_'.$rid} eq 'start') {
  179: 	             $rid=$hash{'ids_'.$hash{'map_id_'.(split(/\./,$rid))[0]}};
  180: 		 }
  181: 		 foreach my $id (split(/\,/,$hash{'from_'.$rid})) {
  182: 		     my $condition= $hash{'conditions_'.$hash{'comesfrom_'.$id}};
  183: 		     my $rescond  = &Apache::lonnet::docondval($condition);
  184: 		     my $linkcond = &Apache::lonnet::directcondval($hash{'condid_'.$hash{'undercond_'.$id}});
  185: 		     my $thiscond = ($rescond<$linkcond)?$rescond:$linkcond;
  186: 		     if ($thiscond>=$mincond) {
  187: 			 if ($posnext) {
  188: 		             $posnext.=','.$id.':'.$thiscond;
  189: 			 } else {
  190:                              $posnext=$id.':'.$thiscond;
  191: 			 }
  192: 			 if ($thiscond>$mincond) { $mincond=$thiscond; }
  193: 		     }
  194: 		 } 
  195: 		 foreach my $id (split(/\,/,$posnext)) {
  196: 		     my ($linkid,$condval)=split(/\:/,$id);
  197: 		     if ($condval>=$mincond) {
  198: 			 $next=&addrid($next,$hash{'comesfrom_'.$linkid},
  199: 				       $hash{'condid_'.$hash{'undercond_'.$linkid}});
  200: 		     }
  201: 		 }
  202:                   if ($hash{'is_map_'.$next}) {
  203: # This jumps to the end of a new map (going down one level)
  204:                       if (
  205:       $hash{'map_type_'.$hash{'map_pc_'.$hash{'src_'.$next}}} eq 'sequence') {
  206: 			  $mapurl=$hash{'src_'.$next};
  207: 			  $next=$hash{'map_finish_'.$hash{'src_'.$next}};
  208:                       } elsif (
  209:       $hash{'map_type_'.$hash{'map_pc_'.$hash{'src_'.$next}}} eq 'page') {
  210: # This jumps back up from an empty sequence, to a page up one level
  211:                           $mapurl=$hash{'map_id_'.(split(/\./,$next))[0]};
  212:                       }
  213:                   } elsif 
  214:                     ((split(/\./,$startoutrid))[0]!=(split(/\./,$next))[0]) {
  215: # This comes back up from a map (going up one level);
  216: 		      $mapurl=$hash{'map_id_'.(split(/\./,$next))[0]};
  217:                   }
  218: 	      }
  219:               return ($next,$mapurl);
  220: }
  221: 
  222: sub first_accessible_resource {
  223:     my $furl;
  224:     if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db',
  225: 	    &GDBM_READER(),0640)) {
  226: 	$furl=$hash{'first_url'};
  227: 	my %args;
  228: 	my ($url,$args) = split(/\?/,$furl);
  229: 	foreach my $pair (split(/\&/,$args)) {
  230: 	    my ($name,$value) = split(/=/,$pair);
  231: 	    $args{&unescape($name)} = &unescape($value);
  232: 	}
  233:         if (!&Apache::lonnet::allowed('bre',$url,$args{'symb'})) {
  234: # Wow, we cannot see this ... move forward to the next one that we can see
  235: 	    my ($newrid,$newmap)=&move($hash{'first_rid'},$hash{'first_mapurl'},'forward');
  236: # Build the new URL
  237: 	    my ($newmapid,$newresid)=split(/\./,$newrid);
  238: 	    my $symb=&Apache::lonnet::encode_symb($newmap,$newresid,$hash{'src_'.$newrid});
  239: 	    $furl=&add_get_param($hash{'src_'.$newrid},{ 'symb' => $symb });
  240: 	    if ($hash{'encrypted_'.$newrid}) {
  241: 		$furl=&Apache::lonenc::encrypted($furl);
  242: 	    }
  243: 	}
  244: 	untie(%hash);
  245: 	return $furl;
  246:     } else {
  247: 	return '/adm/navmaps';
  248:     }
  249: }
  250: 
  251: # ================================================================ Main Handler
  252: 
  253: sub handler {
  254:    my $r=shift;
  255: 
  256: # ------------------------------------------- Set document type for header only
  257: 
  258:   if ($r->header_only) {
  259:       &Apache::loncommon::content_type($r,'text/html');
  260:       $r->send_http_header;
  261:       return OK;
  262:   }
  263: 
  264:   my %cachehash=(); 
  265:   my $multichoice=0;
  266:   my %multichoicehash=();
  267:   my ($redirecturl,$redirectsymb);
  268:   my $next='';
  269:   my @possibilities=();
  270:    &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},['postdata']);
  271:   if (($env{'form.postdata'})&&($env{'request.course.fn'})) {
  272:       my ($direction,$currenturl) = ($env{'form.postdata'}=~/(\w+)\:(.*)/);
  273: 
  274:       if ($env{'request.course.id'}) {
  275:           # Check if course needs to be re-initialized
  276:           my $loncaparev = $r->dir_config('lonVersion');
  277:           my ($result,@reinit) = &Apache::loncommon::needs_coursereinit($loncaparev);
  278:           if ($result eq 'switch') {
  279:               &Apache::loncommon::content_type($r,'text/html');
  280:               $r->send_http_header;
  281:               $r->print(&Apache::loncommon::check_release_result(@reinit));
  282:               return OK;
  283:           } elsif ($result eq 'update') {
  284:               my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
  285:               my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
  286:               my ($furl,$ferr) = &Apache::lonuserstate::readmap("$cdom/$cnum");
  287:               if ($ferr) {
  288:                   my $requrl = $r->uri;
  289:                   $env{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";
  290:                   $env{'user.reinit'} = 1;
  291:                   return HTTP_NOT_ACCEPTABLE;
  292:               }
  293:           }
  294:       }
  295: 
  296:       if ($currenturl=~m|^/enc/|) {
  297: 	  $currenturl=&Apache::lonenc::unencrypted($currenturl);
  298:       }
  299:       $currenturl=~s/\.\d+\.(\w+)$/\.$1/;
  300:       if ($direction eq 'firstres') {
  301: 	  my $furl=&first_accessible_resource();
  302: 	  &Apache::loncommon::content_type($r,'text/html');
  303: 	  $r->header_out(Location => 
  304: 			 &Apache::lonnet::absolute_url().$furl);
  305: 	     
  306: 	  return REDIRECT;
  307:       }
  308:       if ($direction eq 'return') {
  309: # -------------------------------------------------------- Return to last known
  310:          my $last;
  311:          if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
  312:                     &GDBM_READER(),0640)) {
  313: 	     $last=$hash{'last_known'};
  314:              untie(%hash);
  315:          }
  316:          my $newloc;
  317:          if (($last) && (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db',
  318:                         &GDBM_READER(),0640))) {
  319:             my ($murl,$id,$fn)=&Apache::lonnet::decode_symb($last);
  320: 	    $id=$hash{'map_pc_'.&Apache::lonnet::clutter($murl)}.'.'.$id;
  321: 	    $newloc=$hash{'src_'.$id};
  322: 	    if ($newloc) {
  323: 		if ($hash{'encrypted_'.$id}) { $newloc=&Apache::lonenc::encrypted($newloc); }
  324: 			      
  325: 	    } else {
  326: 		$newloc='/adm/navmaps';
  327: 	    }
  328:             untie %hash;
  329:          } else {
  330: 	    $newloc='/adm/navmaps';
  331:          }  
  332: 	     &Apache::loncommon::content_type($r,'text/html');
  333: 	     $r->header_out(Location => 
  334: 			    &Apache::lonnet::absolute_url().$newloc);
  335: 	     
  336: 	     return REDIRECT;
  337:       }
  338:       $currenturl=~s/^https?\:\/\///;
  339:       $currenturl=~s/^[^\/]+//;
  340: #
  341: # Is the current URL on the map? If not, start with last known URL
  342: #
  343:       unless (&Apache::lonnet::is_on_map($currenturl)) {
  344: 	 my $last;
  345:          if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'_symb.db',
  346:                     &GDBM_READER(),0640)) {
  347: 	     $last=$hash{'last_known'};
  348:              untie(%hash);
  349:          }
  350:          if ($last) {
  351: 	     $currenturl=&Apache::lonnet::clutter((&Apache::lonnet::decode_symb($last))[2]);
  352: 	 } else {
  353: 		 &Apache::loncommon::content_type($r,'text/html');
  354: 		 $r->header_out(Location => 
  355: 				&Apache::lonnet::absolute_url().
  356: 				'/adm/noidea.html');
  357: 		 return REDIRECT;
  358:          }
  359:       }
  360: # ------------------------------------------- Do we have any idea where we are?
  361:       my $position;
  362:       if ($position=Apache::lonnet::symbread($currenturl)) {
  363: # ------------------------------------------------------------------------- Yes
  364: 	  my ($startoutmap,$mapnum,$thisurl)=&Apache::lonnet::decode_symb($position);
  365:           $cachehash{$startoutmap}{$thisurl}=[$thisurl,$mapnum];
  366:           $cachehash{$startoutmap}{'last_known'}=
  367:                              [&Apache::lonnet::declutter($currenturl),$mapnum];
  368: 
  369: # ============================================================ Tie the big hash
  370:           if (tie(%hash,'GDBM_File',$env{'request.course.fn'}.'.db',
  371:                         &GDBM_READER(),0640)) {
  372:               my $rid=$hash{'map_pc_'.&Apache::lonnet::clutter($startoutmap)}.
  373:                       '.'.$mapnum;
  374: 
  375: # ------------------------------------------------- Move forward, backward, etc
  376:               my $endupmap;
  377:               ($next,$endupmap)=&move($rid,$startoutmap,$direction);
  378: # -------------------------------------- Do we have one and only one empty URL?
  379: # We are now at at least one non-empty URL
  380: # ----------------------------------------------------- Check out possibilities
  381:               if ($next) {
  382:                   @possibilities=split(/\,/,$next);
  383:                   if ($#possibilities==0) {
  384: # ---------------------------------------------- Only one possibility, redirect
  385: 	              ($redirecturl,$redirectsymb)=&hash_src($next);
  386:                       $cachehash{$endupmap}{$redirecturl}=
  387: 			  [$redirecturl,(split(/\./,$next))[1]];
  388:                   } else {
  389: # ------------------------ There are multiple possibilities for a next resource
  390:                       $multichoice=1;
  391: 		      foreach my $id (@possibilities) {
  392: 			  $multichoicehash{'src_'.$id}=$hash{'src_'.$id};
  393:                           $multichoicehash{'title_'.$id}=$hash{'title_'.$id};
  394:                           $multichoicehash{'type_'.$id}=$hash{'type_'.$id};
  395:                           (my $first, my $second) = $id =~ /(\d+).(\d+)/;
  396:                           my $symbSrc = Apache::lonnet::declutter($hash{'src_'.$id});
  397:                           $multichoicehash{'symb_'.$id} = 
  398:                               Apache::lonnet::declutter($hash{'map_id_'.$first}.'___'.
  399:                                                         $second.'___'.$symbSrc);
  400:                                                          
  401:                           my ($choicemap,$choiceres)=split(/\./,$id);
  402: 			  my $map=&Apache::lonnet::declutter($hash{'src_'.$choicemap});
  403: 			  my $url=$multichoicehash{'src_'.$id};
  404:                           $cachehash{$map}{$url}=[$url,$choiceres];
  405:                       }
  406:                   }
  407: 	      } else {
  408: # -------------------------------------------------------------- No place to go
  409:                   $multichoice=-1;
  410:               }
  411: # ----------------- The program must come past this point to untie the big hash
  412: 	      untie(%hash);
  413: # --------------------------------------------------------- Store position info
  414:               $cachehash{$startoutmap}{'last_direction'}=[$direction,'notasymb'];
  415:               foreach my $thismap (keys(%cachehash)) {
  416: 		  my $mapnum=$cachehash{$thismap}->{'mapnum'};
  417: 		  delete($cachehash{$thismap}->{'mapnum'});
  418: 		  &Apache::lonnet::symblist($thismap,
  419: 					    %{$cachehash{$thismap}});
  420: 	      }
  421: # ============================================== Do not return before this line
  422:               if ($redirecturl) {
  423: # ----------------------------------------------------- There is a URL to go to
  424: 		  if ($direction eq 'forward') {
  425:                      &Apache::lonnet::linklog($currenturl,$redirecturl);
  426: 		  }
  427: 		  if ($direction eq 'back') {
  428:                      &Apache::lonnet::linklog($redirecturl,$currenturl);
  429: 		  }
  430: # ------------------------------------- Check for and display critical messages
  431:                   my ($redirect, $url) = &Apache::loncommon::critical_redirect(300);
  432:                   unless ($redirect) { 
  433:                       $url=&Apache::lonnet::absolute_url().$redirecturl;
  434: 		      $url = &add_get_param($url, { 'symb' => $redirectsymb});
  435:                   }
  436: 		  &Apache::loncommon::content_type($r,'text/html');
  437:                   $r->header_out(Location => $url);
  438:                   return REDIRECT;
  439: 	      } else {
  440: # --------------------------------------------------------- There was a problem
  441:                   &Apache::loncommon::content_type($r,'text/html');
  442:                   $r->send_http_header;
  443: 		  my %lt=&Apache::lonlocal::texthash('title' => 'End of Sequence',
  444: 						     'explain' =>
  445: 						     'You have reached the end of the sequence of materials.',
  446: 						     'back' => 'Go Back',
  447: 						     'nav' => 'Course Contents',
  448: 						     'wherenext' =>
  449: 						     'There are several possibilities of where to go next',
  450: 						     'pick' =>
  451: 						     'Please click on the the resource you intend to access',
  452: 						     'titleheader' => 'Title',
  453: 						     'type' => 'Type');
  454:                   if (&Apache::loncommon::course_type() eq 'Community') {
  455:                       $lt{'nav'} = &mt('Community Contents');
  456:                   }
  457:                   if ($#possibilities>0) {
  458: 		      my $start_page=
  459: 			  &Apache::loncommon::start_page('Multiple Resources');
  460:                      $r->print(<<ENDSTART);
  461: $start_page
  462: <h3>$lt{'wherenext'}</h3>
  463: <p>
  464: $lt{'pick'}:
  465: <p>
  466: <table border="2">
  467: <tr><th>$lt{'titleheader'}</th><th>$lt{'type'}</th></tr>
  468: ENDSTART
  469:                      foreach my $id (@possibilities) {
  470:                         $r->print(
  471:                               '<tr><td><a href="'.
  472: 				  &add_get_param($multichoicehash{'src_'.$id},
  473: 						 {'symb' =>
  474: 						      $multichoicehash{'symb_'.$id},
  475: 						  }).'">'.
  476:                               $multichoicehash{'title_'.$id}.
  477:                               '</a></td><td>'.$multichoicehash{'type_'.$id}.
  478: 			      '</td></tr>');
  479:                      }
  480:                      $r->print('</table>');
  481:                   } else {
  482:                       $r->print(
  483:                           &Apache::loncommon::start_page('No Resource')
  484:                          .'<h2>'.$lt{'title'}.'</h2>'
  485:                          .'<p>'.$lt{'explain'}.'</p>');
  486:                   }
  487:                   $r->print(
  488:                       &Apache::lonhtmlcommon::actionbox(
  489:                           ['<a href="/adm/flip?postdata=return:">'.$lt{'back'}.'</a></li>',
  490:                            '<a href="/adm/navmaps">'.$lt{'nav'}.'</a></li>'
  491:                           ])
  492:                      .&Apache::loncommon::end_page());
  493:                   return OK;
  494: 	      }
  495: 	  } else {
  496: # ------------------------------------------------- Problem, could not tie hash
  497:               $env{'user.error.msg'}="/adm/flip:bre:0:1:Course Data Missing";
  498:               return HTTP_NOT_ACCEPTABLE; 
  499:           }
  500:       } else {
  501: # ---------------------------------------- No, could not determine where we are
  502: 	  $r->internal_redirect('/adm/ambiguous');
  503:           return OK;
  504:       }
  505:   } else {
  506: # -------------------------- Class was not initialized or page fliped strangely
  507:       $env{'user.error.msg'}="/adm/flip:bre:0:0:Choose Course";
  508:       return HTTP_NOT_ACCEPTABLE; 
  509:   } 
  510: }
  511: 
  512: 1;
  513: __END__
  514: 
  515: =pod
  516: 
  517: =head1 NAME
  518: 
  519: Apache::lonpageflip
  520: 
  521: =head1 SYNOPSIS
  522: 
  523: Deals with forward, backward, and other page flips.
  524: 
  525: This is part of the LearningOnline Network with CAPA project
  526: described at http://www.lon-capa.org.
  527: 
  528: =head1 OVERVIEW
  529: 
  530: (empty)
  531: 
  532: =head1 SUBROUTINES
  533: 
  534: =over cleanup()
  535: 
  536: =item addrid()
  537: 
  538: =item fullmove()
  539: 
  540: =item hash_src()
  541: 
  542: =item move()
  543: 
  544: =item get_next_possible_move()
  545: 
  546: =item first_accessible_resource()
  547: 
  548: =item handler()
  549: 
  550: =back
  551: 
  552: =cut
  553: 
  554: 
  555: 
  556: 
  557: 
  558: 

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.