Diff for /rat/lonpage.pm between versions 1.1 and 1.35

version 1.1, 2000/08/30 11:10:23 version 1.35, 2002/03/26 23:12:57
Line 1 Line 1
 # The LearningOnline Network with CAPA  # The LearningOnline Network with CAPA
 # Page Handler  # Page Handler
 #  #
   # $Id$
   #
   # Copyright Michigan State University Board of Trustees
   #
   # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
   #
   # 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/
   #
 # (TeX Content Handler  # (TeX Content Handler
 #  #
   # YEAR=2000
 # 05/29/00,05/30 Gerd Kortemeyer)  # 05/29/00,05/30 Gerd Kortemeyer)
 # 08/30 Gerd Kortemeyer  # 08/30,08/31,09/06,09/14,09/15,09/16,09/19,09/20,09/21,09/23,
   # 10/02,10/10,10/14,10/16,10/18,10/19,10/31,11/6,11/14,11/16,
   # YEAR=2001
   # 08/13/01,08/30,10/1 Gerd Kortemeyer
   # 12/16 Scott Harrison
   # YEAR=2002
   # 03/19 Gerd Kortemeyer
   #
   ###
   
 package Apache::lonpage;  package Apache::lonpage;
   
 use strict;  use strict;
 use Apache::Constants qw(:common :http);  use Apache::Constants qw(:common :http);
 use Apache::lonnet();  use Apache::lonnet();
   use Apache::loncommon();
   use Apache::lonxml();
   use HTML::TokeParser;
 use GDBM_File;  use GDBM_File;
   
   # -------------------------------------------------------------- Module Globals
   my %hash;
   my @rows;
   
   # ------------------------------------------------------------------ Euclid gcd
   
   sub euclid {
       my ($e,$f)=@_;
       my $a; my $b; my $r;
       if ($e>$f) { $b=$e; $r=$f; } else { $r=$e; $b=$f; }
       while ($r!=0) {
    $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})) {
     my $mincond=1;
             my $next='';
             foreach (split(/\,/,$hash{'to_'.$rid})) {
                 my $thiscond=
         &Apache::lonnet::directcondval($hash{'condid_'.$hash{'undercond_'.$_}});
                 if ($thiscond>=$mincond) {
     if ($next) {
         $next.=','.$_.':'.$thiscond;
                     } else {
                         $next=$_.':'.$thiscond;
     }
                     if ($thiscond>$mincond) { $mincond=$thiscond; }
         }
             }
             foreach (split(/\,/,$next)) {
                 my ($linkid,$condval)=split(/\:/,$_);
                 if ($condval>=$mincond) {
                   my $now=&tracetable($sofar,$hash{'goesto_'.$linkid},$beenhere);
                   if ($now>$further) { $further=$now; }
         }
             }
   
          }
       }
       return $further;
   }
   
 # ================================================================ Main Handler  # ================================================================ Main Handler
   
 sub handler {  sub handler {
   my $r=shift;    my $r=shift;
   
 # ----------------------------------------------------------- Set document type  # ------------------------------------------- Set document type for header only
   
   if ($ENV{'browser.mathml'}) {  
     $r->content_type('text/xml');  
   } else {  
     $r->content_type('text/html');  
   }  
   $r->send_http_header;  
   
   return OK if $r->header_only;    if ($r->header_only) {
          if ($ENV{'browser.mathml'}) {
              $r->content_type('text/xml');
          } else {
              $r->content_type('text/html');
          }
          $r->send_http_header;
          return OK;
      }
   
   my $requrl=$r->uri;    my $requrl=$r->uri;
 # ----------------------------------------------------------------- Tie db file  # ----------------------------------------------------------------- Tie db file
   if ($ENV{'request.course.fn'}) {    if ($ENV{'request.course.fn'}) {
       my $fn=$ENV{'request.course.fn'};        my $fn=$ENV{'request.course.fn'};
       if (-e "$fn.db") {        if (-e "$fn.db") {
           my %hash;            if (tie(%hash,'GDBM_File',"$fn.db",&GDBM_READER,0640)) {
           if (tie(%hash,'GDBM_File',"$fn.db",&GDBM_WRCREAT,0640)) {  
 # ------------------------------------------------------------------- Hash tied  # ------------------------------------------------------------------- Hash tied
               my $firstres=$hash{'map_start_'.$requrl};                my $firstres=$hash{'map_start_'.$requrl};
               my $lastres=$hash{'map_finish_'.$requrl};                my $lastres=$hash{'map_finish_'.$requrl};
               if (($firstres) && ($lastres)) {                if (($firstres) && ($lastres)) {
 # ----------------------------------------------------------------- Render page  # ----------------------------------------------------------------- Render page
   
   $r->print("<h2>All is cool.</h2>");                    @rows=();
   
                     &tracetable(0,$firstres,'&'.$lastres.'&');
                     if ($hash{'src_'.$lastres}) {
                        my $brepriv=
                           &Apache::lonnet::allowed('bre',$hash{'src_'.$lastres});
                        if (($brepriv eq '2') || ($brepriv eq 'F')) {
                           $rows[$#rows+1]=''.$lastres;
        }
     }
   
   # ------------------------------------------------------------ Add to symb list
   
                     my $i;
                     my %symbhash=();
                     for ($i=0;$i<=$#rows;$i++) {
        if ($rows[$i]) {
                           my @colcont=split(/\&/,$rows[$i]);
                           foreach (@colcont) {
                              $symbhash{$hash{'src_'.$_}}='';
           }
        }
     }
                     &Apache::lonnet::symblist($requrl,%symbhash);
   
   # ------------------------------------------------------------------ Page parms
   
                     my $j;
                     my $lcm=1;
                     my $contents=0;
                     my $nforms=0;
                     
                     my %ssibody=();
                     my %ssibgcolor=();
                     my %ssitext=();
                     my %ssilink=();
                     my %ssivlink=();
                     my %ssialink=();
        
                     my %metalink=();
   
                     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));
                         foreach (@colcont) {
                             my $src=$hash{'src_'.$_};
                             $src=~/\.(\w+)$/;
                             $metalink{$_}=$src.'.meta';
                             $cellemb{$_}=Apache::loncommon::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'})) {
                                  foreach (keys %ENV) {
     if ($_=~/^form.$prefix/) {
         my $name=$_;
                                         $name=~s/^form.$prefix//;
                                         $posthash{$name}=$ENV{$_};
                                     }
                                  }
         }
                                 my $output=Apache::lonnet::ssi($src,%posthash);
                                 my $parser=HTML::TokeParser->new(\$output);
                                 my $token;
                                 my $thisdir=$src;
                                 my $bodydef=0;
                                 my $thisxml=0;
                                 my @rlinks=();
                                 if ($output=~/\?xml/) {
                                    $isxml=1;
                                    $thisxml=1;
                                    $output=~
            /((?:\<(?:\?xml|\!DOC|html)[^\>]*(?:\>|\>\]\>)\s*)+)\<body[^\>]*\>/si;
                                    $xmlheader=$1;
         }
                                 while ($token=$parser->get_token) {
    if ($token->[0] eq 'S') {
                                     if ($token->[1] eq 'a') {
         if ($token->[2]->{'href'}) {
                                            $rlinks[$#rlinks+1]=
        $token->[2]->{'href'};
         }
     } elsif ($token->[1] eq 'img') {
                                            $rlinks[$#rlinks+1]=
        $token->[2]->{'src'};
     } elsif ($token->[1] eq 'embed') {
                                            $rlinks[$#rlinks+1]=
        $token->[2]->{'src'};
     } elsif ($token->[1] eq 'base') {
         $thisdir=$token->[2]->{'href'};
     } elsif ($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];
                                         }
                                     } elsif ($token->[1] eq 'meta') {
       if ($token->[4] !~ m:/>$:) {
         $allmeta.="\n".$token->[4].'</meta>';
       } else {
         $allmeta.="\n".$token->[4];
       }
                                     } elsif (($token->[1] eq 'script') &&
                                              ($bodydef==0)) {
         $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;
                                     $output=~
         s/\<((?:input|select|button|textarea)[^\>]+)name\s*\=\s*[\'\"]*([\w\.\:]+)[\'\"]*([^\>]*)\>/\<$1 name="$prefix$2" $3\>/gsi;
                                 }
                                 $thisdir=~s/\/[^\/]*$//;
         foreach (@rlinks) {
     unless (($_=~/^http:\/\//i) ||
     ($_=~/^\//) ||
     ($_=~/^javascript:/i) ||
     ($_=~/^mailto:/i) ||
     ($_=~/^\#/)) {
         my $newlocation=
       &Apache::lonnet::hreflocation($thisdir,$_);
                        $output=~s/(\"|\'|\=\s*)$_(\"|\'|\s|\>)/$1$newlocation$2/;
     }
         }
   # -------------------------------------------------- Deal with Applet codebases
     $output=~s/(\<applet[^\>]+)(codebase\=[^\S\>]+)*([^\>]*)\>/$1.($2?$2:' codebase="'.$thisdir.'"').$3.'>'/gei;
         $ssibody{$_}=$output;
   # ---------------------------------------------------------------- End SSI cell
                             }
                         }
                        } 
                     }
                     unless ($contents) {
                         $r->content_type('text/html');
                         $r->send_http_header;
                         $r->print('<html><body>Empty page.</body></html>');
                     } else {
   # ------------------------------------------------------------------ Build page
   
   # ---------------------------------------------------------------- Send headers
                         if ($isxml) {
     $r->content_type('text/xml');
                             $r->send_http_header;
                             $r->print($xmlheader);
         } else {
                             $r->content_type('text/html');
                             $r->send_http_header;
                             $r->print('<html>');
         }
   # ------------------------------------------------------------------------ Head
                         $r->print("\n<head>\n".$allmeta);
                         $allscript=~
          s/\/\/ BEGIN LON\-CAPA Internal.+\/\/ END LON\-CAPA Internal\s//gs;
                         if ($allscript) {
     $r->print("\n<script language='JavaScript'>\n".
                                      $allscript."\n</script>\n");
                         }
                         $r->print(&Apache::lonxml::registerurl(1,undef));
                         $r->print("\n</head>\n");
   # ------------------------------------------------------------------ Start body
                         if ($isxml) {
                             $r->print($xmlbody);
                         } else {
     $r->print(
    '<body bgcolor="#FFFFFF" onLoad="'.&Apache::lonxml::loadevents.
                        '" onUnload="'.&Apache::lonxml::unloadevents.'">');
                         }
   # ------------------------------------------------------------------ Start form
                         if ($nforms) {
     $r->print('<form method="post" action="'.
       $requrl.'">');
                         }
   # ----------------------------------------------------------------- Start table
                         $r->print('<table cols="'.$lcm.'" border="0">');
                         for ($i=0;$i<=$#rows;$i++) {
    if ($rows[$i]) {
                             $r->print("\n<tr>");
                             my @colcont=split(/\&/,$rows[$i]);
                             my $avespan=$lcm/($#colcont+1);
                             for ($j=0;$j<=$#colcont;$j++) {
                                 my $rid=$colcont[$j];
                                 my $metainfo='<a href="'.
                                       $metalink{$rid}.'" target="LONcatInfo">'.
                             '<img src="/adm/lonMisc/cat_button.gif" border=0>'.
     '</img></a><a href="/adm/evaluate?postdata='.
         &Apache::lonnet::escape(&Apache::lonnet::declutter($hash{'src_'.$rid}))
         .'" target="LONcatInfo">'.
                             '<img src="/adm/lonMisc/eval_button.gif" border=0>'.
                             '</img></a>';
                                 if (
    ($hash{'src_'.$rid}=~/\.(problem|exam|quiz|assess|survey|form)$/) &&
    (&Apache::lonnet::allowed('mgr',$ENV{'request.course.id'}))) {
     my ($mapid,$resid)=split(/\./,$rid);
                                    my $symb=
                   &Apache::lonnet::declutter($hash{'map_id_'.$mapid}).
                   '___'.$resid.'___'.
    &Apache::lonnet::declutter($hash{'src_'.$rid});
                                    $metainfo.=
                     '<a href="/adm/grades?symb='.$symb.
                     '&command=submission" target="LONcatInfo">'.
                             '<img src="/adm/lonMisc/subm_button.gif" border=0>'.
     '</img></a>'.
                     '<a href="/adm/grades?symb='.$symb.
                     '&command=viewgrades" target="LONcatInfo">'.
                             '<img src="/adm/lonMisc/pgrd_button.gif" border=0>'.
     '</img></a>'.
                     '<a href="/adm/parmset?symb='.$symb.'" target="LONcatInfo">'.
                             '<img src="/adm/lonMisc/pprm_button.gif" border=0>'.
         '</img></a>';
                                 }
                                 $metainfo.='<br></br>';
                                 $r->print('<td colspan="'.$avespan.'"');
                                 if ($cellemb{$rid} eq 'ssi') {
     if ($ssibgcolor{$rid}) {
                                        $r->print(' bgcolor="'.
                                                  $ssibgcolor{$rid}.'"');
                                     }
                                     $r->print('>'.$metainfo.'<font');
                                     if ($ssitext{$rid}) {
        $r->print(' text="'.$ssitext{$rid}.'"');
                                     }
                                     if ($ssilink{$rid}) {
        $r->print(' link="'.$ssilink{$rid}.'"');
                                     }
                                     if ($ssitext{$rid}) {
        $r->print(' vlink="'.$ssivlink{$rid}.'"');
                                     }
                                     if ($ssialink{$rid}) {
        $r->print(' alink="'.$ssialink{$rid}.'"');
                                     }
                               
                                     $r->print('>'.$ssibody{$rid}.'</font>');
                                 } elsif ($cellemb{$rid} eq 'img') {
                                     $r->print('>'.$metainfo.'<img src="'.
                                       $hash{'src_'.$rid}.'"></img>');
         } elsif ($cellemb{$rid} eq 'emb') {
                                     $r->print('>'.$metainfo.'<embed src="'.
                                       $hash{'src_'.$rid}.'"></embed>');
                                 }
                                 $r->print('</td>');
                             }
                             $r->print('</tr>');
           }
                         }
                         $r->print("\n</table>");
   # ---------------------------------------------------------------- Submit, etc.
                         if ($nforms) {
                             $r->print(
                     '<input name="all_submit" value="Submit All" type="'.
     (($nforms>1)?'submit':'hidden').'"></input></form>');
                         }
                         $r->print('</body>'.&Apache::lonxml::xmlend());
   # -------------------------------------------------------------------- End page
                     }                  
 # ------------------------------------------------------------- End render page  # ------------------------------------------------------------- End render page
               } else {                } else {
   $r->print("<h2>Page undefined.</h2>");                    $r->content_type('text/html');
                     $r->send_http_header;
     $r->print('<html><body>Page undefined.</body></html>');
               }                }
 # ------------------------------------------------------------------ Untie hash  # ------------------------------------------------------------------ Untie hash
               unless (untie(%hash)) {                unless (untie(%hash)) {
Line 59  sub handler { Line 462  sub handler {
           }            }
       }         } 
   }    }
   $ENV{'user.error.msg'}="$requrl:bre:1:1:Course not initialized";    $ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";
   return HTTP_NOT_ACCEPTABLE;     return HTTP_NOT_ACCEPTABLE; 
 }  }
   
 1;  1;
 __END__  __END__
   
   =head1 NAME
   
   Apache::lonpage - Page Handler
   
   =head1 SYNOPSIS
   
   Invoked by /etc/httpd/conf/srm.conf:
   
    <LocationMatch "^/res/.*\.page$>
    SetHandler perl-script
    PerlHandler Apache::lonpage
    </LocationMatch>
   
   =head1 INTRODUCTION
   
   This module renders a .page resource.
   
   This is part of the LearningOnline Network with CAPA project
   described at http://www.lon-capa.org.
   
   =head1 HANDLER SUBROUTINE
   
   This routine is called by Apache and mod_perl.
   
   =over 4
   
   =item *
   
   set document type for header only
   
   =item *
   
   tie db file
   
   =item *
   
   render page
   
   =item *
   
   add to symb list
   
   =item *
   
   page parms
   
   =item *
   
   Get SSI output, post parameters
   
   =item *
   
   SSI cell rendering
   
   =item *
   
   Deal with Applet codebases
   
   =item *
   
   Build page
   
   =item *
   
   send headers
   
   =item *
   
   start body
   
   =item *
   
   start form
   
   =item *
   
   start table
   
   =item *
   
   submit element, etc, render page, untie hash
   
   =back
   
   =head1 OTHER SUBROUTINES
   
   =over 4
   
   =item *
   
   euclid() : Euclid's method for determining the greatest common denominator.
   
   =item *
   
   tracetable() : Build page table.
   
   =back
   
   =cut
   
   
   

Removed from v.1.1  
changed lines
  Added in v.1.35


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