Assignment Solutions Request via PHP

There are actually several PHP files that work in conjunction with WaterMarkScript. They should be together in the same subdirectory of public_html.

TODO: cond_include, the contents of permissions.php, and auto-detection of the course account name are all very useful, and will likely be distributed to many different php programs. They should be moved to a library of generally-useful PHP functions.

.htaccess

Either in the same directory or a parent directory, there must be a .htaccess file with contents combining the requirements of HtaccessForPHP and RequireUseridsForSecureWebAccess.

permissions.php

See RestrictingWebAccessToCourse.

requestAssgnSolnCommon.php

This just defines some functions and variables common to both index.php and requestAssgnSolnGet.php.

The file list array has to be populated with all files available to WaterMarkScript currently; see the commented example for what to pattern. A relatively straightforward enhancement should be just to read all subdirectories of the watermark script directory, since that script is hardcoded to look there anyway; this would save a step whenever updating available solutions.

Note that to allow feeding of special file types (such as PDF), there cannot be any whitespace in this file. Otherwise, PHP will immediately and automatically feed appropriate headers for an HTML page, messing up the delivery of PDF data.

<?php
require('permissions.php');

function control_access($user) {
   ensure_permissions($user, array('student', 'ta', 'ia', 'tutor', 'isc', 'instructor'));
}
function cond_include($path_minus_ext) {
   if (file_exists($path_minus_ext.'.php')) {
      include($path_minus_ext.'.php');
   } else if (file_exists($path_minus_ext.'.shtml')) {
      include($path_minus_ext.'.shtml');
   }
}


$stuserid=$_SERVER['REMOTE_USER']; // The userid of whoever is logged on

# Get userid of the account too.
$me=posix_getpwuid(posix_getuid());
$me=$me['name'];

$filesdir="/u/$me/protectPDF";


$file_list=array( // An associative array of filename => description
   #'f06final'=>'Final Exam: Fall 2006',
);
?>

Potential improvement

It should be possible for $file_list to be built automatically. It could scan the same directory as WaterMarkScript (so this directory may as well be provided by this include also) and add every directory to this list. There should be no clear disadvantage to doing this, and the advantage is that nobody has to remember to update this separate file every time there's a new PDF uploaded.

index.php

The entry point for the page. It displays to students the conditions for downloading the file, and displays a table which allows them to select any files they wish to download.

#!/usr/bin/env php-cgi

<?php require("requestAssgnSolnCommon.php"); ?>

   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
   <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
   <head>
   <meta http-equiv="Content-type" content="text/html;charset=UTF-8" />

<style type="text/css">
<!--
th      {text-align: left;}
-->
</style>

        <title><?php echo $me ?>: Assignment Solution Request</title>
<?php cond_include('/u/' . $me . '/public_html/standard_style'); ?>
   </head>

   <body>
<?php cond_include('/u/' . $me . '/public_html/standard_init'); ?>

<?php control_access($stuserid); ?>

<p>The files listed below are "protected", meaning that they are not
to be shared. By clicking on one of the links below, you agree to the
following statements:</p>

<ul>
<li>My userid is <code><?php echo "$stuserid"; ?></code>.</li>
<li>I am a student in CS 135 in the Winter 2010 term.</li>
<li>I will not share these files with anyone else, and I will delete all my
copies of them at the end of the Winter 2010 term. It is my responsibility
to ensure that no one else has access to these files.</li>
<li>I agree to the collection of my userid, IP address, and the current time.
</li>
</ul>
<br />

<?php
echo "<table width=75%><tr><th>Description</th>
                <th>Filename</th>
      <th>Last updated</th></tr>";
foreach($file_list as $fname=>$desc) {
  echo "<tr><td>$desc</td>
        <td><a href='requestAssgnSolnGet.php?f=$fname'>$fname.pdf</a></td>
        <td>".date('g:ia F j',filemtime("$filesdir/$fname/$fname.pdf"))."</td></tr>";
}
echo "</table>";

#foot();
?>

<br />
<p>Generating your PDF file takes some time;  please be patient.</p>

<?php cond_include('/u/' . $me . '/public_html/standard_fini'); ?>
   </body>
   </html>

Potential improvement

This page currently serves up quite invalid XHTML 1, and this should be fixed by anybody who has the time.

requestAssgnSolnGet.php

This file actually feeds the PDF file, attempting to die gracefully if it cannot. This is the script that's dependent on the WaterMarkScript to generate the PDF for it. Note that the PDF generation is not done on the web server; as a general rule, heavy work should not be done on the web server to try to help ensure good response to all requests.

#!/usr/bin/env php-cgi
<?php
require("requestAssgnSolnCommon.php");
control_access($stuserid);

function begin_msg () {
   echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
   echo "\n";
   echo '<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">';
   echo '<head><meta http-equiv="Content-type" content="text/html;charset=UTF-8" /><title>File not available</title></head>' . "\n";
   echo '<body>';

   cond_include('/u/' . $me . '/public_html/standard_style');

   cond_include('/u/' . $me . '/standard_init');
}

function end_msg () {
   cond_include('/u/' . $me . '/standard_fini');
   echo '</body></html>';
}

$fname=$_GET['f'];
if (!array_key_exists($fname,$file_list)) {
   begin_msg();
   echo "<p>Sorry, no file with the name <code>".htmlspecialchars($fname)."</code> is available.</p>";
   echo "<p><a href='https://www.student.cs.uwaterloo.ca/~$me/requestAssgnSoln'>Return to the solutions request page</a>.</p>";
   end_msg();
}
else {
   $pdffile=exec("ssh linux.student.cs.uwaterloo.ca \"$filesdir/watermarkalt.sh $fname $stuserid\"");
   if (file_exists("$pdffile")) {
      header('Content-Description: File Transfer');
      header('Content-Type: application/pdf');
      header('Content-Disposition: attachment; filename='.$fname.'.pdf');
      header('Content-Transfer-Encoding: binary');
      header('Expires: 0');
      header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
      header('Content-Length: ' . filesize("$pdffile"));
      readfile("$pdffile");

      # Remove our temporary file
      system("rm -f $pdffile");

      # Log what happened
      system("echo \"$stuserid $fname ".$_SERVER['REMOTE_ADDR'].' '
         .date('r')."\" >> \"$filesdir/log.txt\"");
   } else {
      begin_msg();
      echo "<p>An error has occurred in trying to fetch the file <code>"
         .htmlspecialchars($fname).
         ".pdf (" .htmlspecialchars($pdffile). ")</code>. Please try again in a few minutes. 
         If it still doesn't work, contact the tutor at <tt>" .htmlspecialchars("$me@student.cs.uwaterloo.ca").
         '</tt>.</p>';
      end_msg();
   }
}
?>
Topic revision: r7 - 2010-10-05 - TerryVaskor
 
This site is powered by the TWiki collaboration platform Powered by PerlCopyright © 2008-2019 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback