[system] / trunk / webwork2 / lib / WeBWorK / ContentGenerator / Instructor / FileXfer.pm Repository:
ViewVC logotype

View of /trunk/webwork2/lib/WeBWorK/ContentGenerator/Instructor/FileXfer.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3377 - (download) (as text) (annotate)
Thu Jul 14 13:15:27 2005 UTC (7 years, 10 months ago) by glarose
File size: 14573 byte(s)
Preliminary commit of changes to add Gateway module.
This adds to WeBWorK
 - the ability to create versioned, timed problem sets ("gateway tests")
   for which all problems are displayed on a single page ("versioned"
   means that students can get multiple versions of the problem set),
 - the ability to create sets that draw problems from groups of
   problems, and
 - the ability to create sets that require a proctor login to start
   and grade.
Sets can be defined as gateway tests or proctored gateway tests from
the ProblemSetDetail page.

Not quite bug-free yet.  Known bugs include handling of problem values
on the Student Progress page (I think this may be a problem with
changing from sql database format where all entries were 'text' to
sql_single in ver 2.1, where they are integer), and a division by zero
error on the grades page (which may be the same problem).

Tests with a number of attempts per version greater than one haven't
been carefully tested, nor has scoring of gateway tests.

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader: webwork2/lib/WeBWorK/ContentGenerator/Instructor/FileXfer.pm,v 1.9 2004/08/19 15:45:52 toenail Exp $
    5 #
    6 # This program is free software; you can redistribute it and/or modify it under
    7 # the terms of either: (a) the GNU General Public License as published by the
    8 # Free Software Foundation; either version 2, or (at your option) any later
    9 # version, or (b) the "Artistic License" which comes with this package.
   10 #
   11 # This program is distributed in the hope that it will be useful, but WITHOUT
   12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   13 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
   14 # Artistic License for more details.
   15 ################################################################################
   16 
   17 package WeBWorK::ContentGenerator::Instructor::FileXfer;
   18 use base qw(WeBWorK::ContentGenerator::Instructor);
   19 
   20 =head1 NAME
   21 
   22 WeBWorK::ContentGenerator::Instructor::FileXfer - transfer course files from/to
   23 client
   24 
   25 =cut
   26 
   27 use strict;
   28 use warnings;
   29 use Apache::Constants qw(:common REDIRECT DONE);
   30 use CGI qw();
   31 
   32 sub pre_header_initialize {
   33   my ($self) = @_;
   34   my $r = $self->r;
   35   my $ce = $r->ce;
   36   my $authz = $r->authz;
   37 
   38   my $userID = $r->param("user");
   39 
   40   my ($type, $action) = ("", "");
   41   if (defined $r->param("deleteDef"))           { $type = "def";         $action = "delete";   }
   42   if (defined $r->param("downloadDef"))         { $type = "def";         $action = "download"; }
   43   if (defined $r->param("uploadDef"))           { $type = "def";         $action = "upload";   }
   44   if (defined $r->param("deleteClasslist"))     { $type = "classlist";   $action = "delete";   }
   45   if (defined $r->param("downloadClasslist"))   { $type = "classlist";   $action = "download"; }
   46   if (defined $r->param("uploadClasslist"))     { $type = "classlist";   $action = "upload";   }
   47   if (defined $r->param("deleteScoringFile"))   { $type = "scoringFile"; $action = "delete";   }
   48   if (defined $r->param("downloadScoringFile")) { $type = "scoringFile"; $action = "download"; }
   49   if (defined $r->param("uploadScoringFile"))   { $type = "scoringFile"; $action = "upload";   }
   50   if (defined $r->param("deleteTemplateFile"))  { $type = "templateFile"; $action = "delete";   }
   51   if (defined $r->param("downloadTemplateFile")){ $type = "templateFile"; $action = "download"; }
   52   if (defined $r->param("uploadTemplateFile"))  { $type = "templateFile"; $action = "upload";   }
   53 
   54 
   55   # make sure we have permission to do what we want to do
   56   if ($type eq "def") {
   57     unless ($authz->hasPermissions($userID, "modify_set_def_files")) {
   58       $self->addbadmessage(CGI::p("You are not authorized to modify the list of set definition files."));
   59       return;
   60     }
   61   } elsif ($type eq "classlist") {
   62     unless ($authz->hasPermissions($userID, "modify_classlist_files")) {
   63       $self->addbadmessage(CGI::p("You are not authorized to modify the list of classlist files."));
   64       return;
   65     }
   66   } elsif ($type eq "scoringFile") {
   67     unless ($authz->hasPermissions($userID, "modify_scoring_files")) {
   68       $self->addbadmessage(CGI::p("You are not authorized to modify the list of scoring files."));
   69       return;
   70     }
   71   } elsif ($type eq "templateFile") {
   72     unless ($authz->hasPermissions($userID, "modify_problem_template_files")) {
   73       $self->addbadmessage(CGI::p("You are not authorized to modify the list of problem template files."));
   74       return;
   75     }
   76   }
   77 
   78   # call handler for the action we want to perform
   79   if ($action eq "delete") {
   80     $self->handleDelete($type);
   81   } elsif ($action eq "download") {
   82     $self->handleDownload($type);
   83   } elsif ($action eq "upload") {
   84     $self->handleUpload($type);
   85   }
   86 }
   87 
   88 sub handleDelete {
   89   my ($self, $type) = @_;
   90   my $r = $self->r;
   91   my $ce = $r->ce;
   92 
   93   my (@fileList, $selectParam, $dir);
   94   if ($type eq "classlist") {
   95     @fileList = $self->getCSVList;
   96     $selectParam = "classlist";
   97     $dir = $ce->{courseDirs}->{templates};
   98   } elsif ($type eq "def") {
   99     @fileList = $self->getDefList;
  100     $selectParam = "def";
  101     $dir = $ce->{courseDirs}->{templates};
  102   } elsif ($type eq "scoringFile") {
  103     @fileList = $self->getScoringFileList;
  104     $selectParam = "scoringFile";
  105     $dir = $ce->{courseDirs}->{scoring};
  106   } elsif ($type eq "templateFile") {
  107       my $templateSubDir    = $r->param("templateSubDir");
  108     @fileList = $self->getTemplateFileList($templateSubDir);
  109     $selectParam = "templateFile";
  110     $dir = $ce->{courseDirs}->{templates}."/$templateSubDir";
  111   } else {
  112     die "handleDelete() doesn't know what to do with file type $type!";
  113   }
  114 
  115   # get file name
  116   my $fileToDelete = $r->param($selectParam);
  117   unless ($fileToDelete) {
  118     $self->addbadmessage(CGI::p("No file selected for deletion."));
  119     return;
  120   }
  121 
  122   # FIXME: FOR THE LOVE OF GOD, ADD SECURITY CHECKS!!!!!!
  123   # (actually I think it's not such a big deal, since we're checking the
  124   # tainted input against a finite set of files that we know are okay to
  125   # delete)
  126 
  127   # make sure it's in the file list
  128   unless (grep { $_ eq $fileToDelete } @fileList) {
  129     $self->addbadmessage(CGI::p("File \"$fileToDelete\" not found in file list."));
  130     return;
  131   }
  132 
  133   # (at this point we know the filename isn't dangerous)
  134 
  135   # delete it
  136   unlink "$dir/$fileToDelete";
  137   $self->addgoodmessage("$dir/$fileToDelete has been deleted.");
  138 }
  139 
  140 sub handleDownload {
  141   my ($self, $type) = @_;
  142   my $r = $self->r;
  143   my $ce = $r->ce;
  144 
  145   my (@fileList, $selectParam, $dir);
  146   if ($type eq "classlist") {
  147     @fileList = $self->getCSVList;
  148     $selectParam = "classlist";
  149     $dir = $ce->{courseDirs}->{templates};
  150   } elsif ($type eq "def") {
  151     @fileList = $self->getDefList;
  152     $selectParam = "def";
  153     $dir = $ce->{courseDirs}->{templates};
  154   } elsif ($type eq "scoringFile") {
  155     @fileList = $self->getScoringFileList;
  156     $selectParam = "scoringFile";
  157     $dir = $ce->{courseDirs}->{scoring};
  158   } elsif ($type eq "templateFile") {
  159       my $templateSubDir    = $r->param("templateSubDir");
  160     @fileList = $self->getTemplateFileList($templateSubDir);
  161     $selectParam = "templateFile";
  162     $dir = $ce->{courseDirs}->{templates};
  163     $dir = $ce->{courseDirs}->{templates}."/$templateSubDir";
  164   } else {
  165     die "handleDownload() doesn't know what to do with file type $type!";
  166   }
  167 
  168   # get file name
  169   my $fileToDownload = $r->param($selectParam);
  170   unless ($fileToDownload) {
  171     $self->addbadmessage(CGI::p("No file selected for download."));
  172     return;
  173   }
  174 
  175   # make sure it's in the file list
  176   unless (grep { $_ eq $fileToDownload } @fileList) {
  177     $self->addbadmessage(CGI::p("File \"$fileToDownload\" not found in file list."));
  178     return;
  179   }
  180 
  181   # set the file to sent:
  182   $self->reply_with_file("text/plain", "$dir/$fileToDownload", $fileToDownload, 0);
  183 }
  184 
  185 sub handleUpload {
  186   my ($self, $type) = @_;
  187   my $r = $self->r;
  188   my $ce = $r->ce;
  189 
  190   my (@fileList, $uploadParam, $uploadNameParam, $ext, $destDir);
  191   if ($type eq "classlist") {
  192     @fileList = $self->getCSVList;
  193     $uploadParam = "newClasslist";
  194     $uploadNameParam = "newClasslistName";
  195     $ext = ".lst";
  196     $destDir = $ce->{courseDirs}->{templates};
  197   } elsif ($type eq "def") {
  198     @fileList = $self->getDefList;
  199     $uploadParam = "newDef";
  200     $uploadNameParam = "newDefName";
  201     $ext = ".def";
  202     $destDir = $ce->{courseDirs}->{templates};
  203   } elsif ($type eq "scoringFile") {
  204     @fileList = $self->getScoringFileList;
  205     $uploadParam = "newScoringFile";
  206     $uploadNameParam = "newScoringFileName";
  207     $ext = ".csv";
  208     $destDir = $ce->{courseDirs}->{scoring};
  209   } elsif ($type eq "templateFile") {
  210       my $templateSubDir    = $r->param("templateSubDir");
  211     @fileList = $self->getTemplateFileList($templateSubDir);
  212     $uploadParam = "newTemplateFile";
  213     $uploadNameParam = "newTemplateFileName";
  214     $ext = ".pg";
  215     $destDir = $ce->{courseDirs}->{templates}."/$templateSubDir";
  216   }
  217 
  218   # get upload ID and hash
  219   my $uploadIDHash = $r->param($uploadParam);
  220   unless ($uploadIDHash) {
  221     $self->addbadmessage(CGI::p("No file selected for upload."));
  222     return;
  223   }
  224   my ($id, $hash) = split /\s+/, $uploadIDHash;
  225 
  226   #warn "upload param contains $uploadIDHash\n";
  227   #warn "upload ID is $id\n";
  228   #warn "upload hash is $hash\n";
  229 
  230   # retrieve upload from upload cache
  231   my $upload = WeBWorK::Upload->retrieve($id, $hash,
  232     dir => $ce->{webworkDirs}->{uploadCache}
  233   );
  234 
  235   # determine what to call the resulting file
  236   my $fileName = $r->param($uploadNameParam) || $upload->filename;
  237 
  238   # tack on the file extension if it's not already there
  239   $fileName .= $ext unless $fileName =~ m/$ext$/;
  240 
  241   # does the file name have the path separator in it?
  242   die "illegal character in upload name: \"/\". (no hacking!)" if $fileName =~ m|/|;
  243 
  244   # does a file already exist with that name?
  245   if (grep { $_ eq $fileName } @fileList) {
  246     $self->addbadmessage(CGI::p("A file named \"$fileName\" exists. Either remove it, or chose a different name for your upload."));
  247     return;
  248   }
  249 
  250   $upload->disposeTo("$destDir/$fileName");
  251   $self->addgoodmessage("$destDir/$fileName has been uploaded.");
  252 }
  253 
  254 sub body {
  255   my ($self) = @_;
  256   my $r = $self->r;
  257   my $authz = $r->authz;
  258 
  259   my $userID = $r->param("user");
  260 
  261   return CGI::div({class=>"ResultsWithError"}, "You are not authorized to access the Instructor tools.")
  262     unless $authz->hasPermissions($r->param("user"), "access_instructor_tools");
  263 
  264   # if we needed to get either of these lists earlier, use the cached copy
  265   # otherwise, get them from the filesystem
  266   #my $classlistsRef = $self->{classlists} || [ $self->getCSVList ];
  267   #my $setDefsRef    = $self->{setDefs}    || [ $self->getDefList ];
  268 
  269   my $templateSubDir    = $r->param("templateSubDir");
  270   $templateSubDir = "" if $templateSubDir and $templateSubDir eq ' Top'; #deal with special value for top directory
  271   my $classlistsRef     = [ $self->getCSVList         ];
  272   my $setDefsRef        = [ $self->getDefList         ];
  273   my $scoringFileRef    = [ $self->getScoringFileList ];
  274   my $templateDirRef    = [ $self->getTemplateDirList ];
  275   my $templateFileRef   = [ $self->getTemplateFileList($templateSubDir) ];
  276 
  277 
  278 
  279   print CGI::p(<<EOT);
  280 Use the tools below to modify course files. Set definition files and classlist
  281 files are only used for importing and exporting set and user data.
  282 EOT
  283 
  284   print CGI::table({-border=>1, -nowrap=>1},
  285     CGI::Tr({-valign=>"top"},
  286       $authz->hasPermissions($userID, "modify_set_def_files") ?
  287       CGI::td({},
  288         CGI::p("Set Definition Files"),
  289         CGI::startform("POST", $r->uri, "multipart/form-data"),
  290         $self->hidden_authen_fields,
  291         CGI::scrolling_list(
  292           -name => "def",
  293           -values => $setDefsRef,
  294           -size => 8,
  295           -multiple => 0,
  296         ), CGI::br(),
  297         CGI::submit("deleteDef", "Delete"),
  298         CGI::font({-color=>"red"}, CGI::em("Delete is not undoable!")),
  299         CGI::br(),
  300         CGI::submit("downloadDef", "Download"),
  301         CGI::br(),
  302         CGI::p("Upload New Set Definition File:"),
  303         CGI::filefield(
  304           -name => "newDef",
  305           -size => 30,
  306         ), CGI::br(),
  307         "Use name:", CGI::textfield("newDefName", "", 30), CGI::br(),
  308         CGI::submit("uploadDef", "Upload Set Definition File"),
  309         CGI::endform(),
  310       ) : CGI::td({}, CGI::div({class=>"ResultsWithError"}, CGI::p("You are not authorized to modify the list of set definition files."))),
  311       $authz->hasPermissions($userID, "modify_classlist_files") ?
  312         CGI::td({},
  313           CGI::p("Classlist Files"),
  314           CGI::startform("POST", $r->uri, "multipart/form-data"),
  315           $self->hidden_authen_fields,
  316           CGI::scrolling_list(
  317             -name => "classlist",
  318             -values => $classlistsRef,
  319             -size => 8,
  320             -multiple => 0,
  321           ), CGI::br(),
  322           CGI::submit("deleteClasslist", "Delete"),
  323           CGI::font({-color=>"red"}, CGI::em("Delete is not undoable!")),
  324           CGI::br(),
  325           CGI::submit("downloadClasslist", "Download"), CGI::br(),
  326           CGI::p("Upload New Classlist File:"),
  327           CGI::filefield(
  328             -name => "newClasslist",
  329             -size => 30,
  330           ), CGI::br(),
  331           "Use name:", CGI::textfield("newClasslistName", "", 30), CGI::br(),
  332           CGI::submit("uploadClasslist", "Upload Classlist File"),
  333           CGI::endform(),
  334         ) : CGI::td({}, CGI::div({class=>"ResultsWithError"}, CGI::p("You are not authorized to modify the list of classlist files."))),
  335     ),
  336     CGI::Tr({-valign=>"top"},
  337       $authz->hasPermissions($userID, "modify_scoring_files") ?
  338         CGI::td({},
  339           CGI::p("Scoring Files"),
  340           CGI::startform("POST", $r->uri, "multipart/form-data"),
  341           $self->hidden_authen_fields,
  342           CGI::scrolling_list(
  343             -name => "scoringFile",
  344             -values => $scoringFileRef,
  345             -size => 8,
  346             -multiple => 0,
  347           ), CGI::br(),
  348           CGI::submit("deleteScoringFile", "Delete"),
  349           CGI::font({-color=>"red"}, CGI::em("Delete is not undoable!")),
  350           CGI::br(),
  351           CGI::submit("downloadScoringFile", "Download"),
  352           CGI::br(),
  353           CGI::p("Upload New Scoring File:"),
  354           CGI::filefield(
  355             -name => "newScoringFile",
  356             -size => 30,
  357           ), CGI::br(),
  358           "Use name:", CGI::textfield("newScoringFileName", "", 30), CGI::br(),
  359           CGI::submit("uploadScoringFile", "Upload Scoring File"),
  360           CGI::endform(),
  361         ) : CGI::td({}, CGI::div({class=>"ResultsWithError"}, CGI::p("You are not authorized to modify the list of scoring files."))),
  362        $authz->hasPermissions($userID, "modify_problem_template_files") ?
  363         CGI::td({},
  364           CGI::p("Problem Template Files"),
  365           CGI::startform("POST", $r->uri, "multipart/form-data"),
  366           $self->hidden_authen_fields,
  367           CGI::popup_menu(
  368             -name => "templateSubDir",
  369             -values => $templateDirRef,
  370             -default => ( defined($templateSubDir) )?  $templateSubDir:' Top',
  371           ),CGI::br(),
  372           CGI::submit('UpdateList','Update List'),CGI::br(),
  373           CGI::scrolling_list(
  374             -name => "templateFile",
  375             -values => $templateFileRef,
  376             -size => 8,
  377             -multiple => 0,
  378           ), CGI::br(),
  379           CGI::submit("deleteTemplateFile", "Delete"),
  380           CGI::font({-color=>"red"}, CGI::em("Delete is not undoable!")),
  381           CGI::br(),
  382           CGI::submit("downloadTemplateFile", "Download"),
  383           CGI::br(),
  384           CGI::p("Upload New Problem Template File:"),
  385           CGI::filefield(
  386             -name => "newTemplateFile",
  387             -size => 30,
  388           ), CGI::br(),
  389           "Use name:", CGI::textfield("newTemplateFileName", "", 30), CGI::br(),
  390           CGI::submit("uploadTemplateFile", "Upload Problem Template File"),
  391           CGI::endform(),
  392         ) : CGI::td({}, CGI::div({class=>"ResultsWithError"}, CGI::p("You are not authorized to modify the list of problem template files."))),
  393 
  394     ),
  395 
  396   );
  397 
  398   return "";
  399 }
  400 
  401 1;
  402 
  403 __END__
  404 
  405 =head1 AUTHOR
  406 
  407 Written by Sam Hathaway, sh002i (at) math.rochester.edu
  408 
  409 =cut

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9