Parent Directory
|
Revision Log
Revision 1093 - (view) (download) (as text)
| 1 : | sh002i | 440 | ################################################################################ |
| 2 : | sh002i | 494 | # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project |
| 3 : | sh002i | 440 | # $Id$ |
| 4 : | ################################################################################ | ||
| 5 : | |||
| 6 : | malsyned | 283 | package WeBWorK::CourseEnvironment; |
| 7 : | |||
| 8 : | sh002i | 455 | =head1 NAME |
| 9 : | |||
| 10 : | WeBWorK::CourseEnvironment - Read configuration information from global.conf | ||
| 11 : | and course.conf files. | ||
| 12 : | |||
| 13 : | =cut | ||
| 14 : | |||
| 15 : | sh002i | 319 | use strict; |
| 16 : | use warnings; | ||
| 17 : | malsyned | 283 | use Safe; |
| 18 : | sh002i | 412 | use WeBWorK::Utils qw(readFile); |
| 19 : | malsyned | 1092 | use Opcode qw(empty_opset); |
| 20 : | malsyned | 283 | |
| 21 : | sh002i | 1051 | # new($invocant, $webworkRoot, $webworkURLRoot, $pgRoot, $courseName) |
| 22 : | # $invocant implicitly set by caller | ||
| 23 : | # $webworkRoot directory that contains the WeBWorK distribution | ||
| 24 : | # $webworkURLRoot URL that points to the WeBWorK system | ||
| 25 : | # $pgRoot directory that contains the PG distribution | ||
| 26 : | sh002i | 798 | # $courseName name of the course being used |
| 27 : | malsyned | 283 | sub new { |
| 28 : | sh002i | 319 | my $invocant = shift; |
| 29 : | my $class = ref($invocant) || $invocant; | ||
| 30 : | malsyned | 283 | my $webworkRoot = shift; |
| 31 : | sh002i | 695 | my $webworkURLRoot = shift; |
| 32 : | sh002i | 1051 | my $pgRoot = shift; |
| 33 : | sh002i | 700 | my $courseName = shift || ""; |
| 34 : | sh002i | 319 | my $safe = Safe->new; |
| 35 : | malsyned | 283 | |
| 36 : | sh002i | 319 | # set up some defaults that the environment files will need |
| 37 : | $safe->reval("\$webworkRoot = '$webworkRoot'"); | ||
| 38 : | sh002i | 695 | $safe->reval("\$webworkURLRoot = '$webworkURLRoot'"); |
| 39 : | sh002i | 1051 | $safe->reval("\$pgRoot = '$pgRoot'"); |
| 40 : | sh002i | 319 | $safe->reval("\$courseName = '$courseName'"); |
| 41 : | |||
| 42 : | malsyned | 1092 | # Compile the "include" function with all opcodes available. |
| 43 : | malsyned | 1093 | my $include = 'sub include { |
| 44 : | my ($file) = @_; | ||
| 45 : | my $fullPath = "'.$webworkRoot.'/$file"; | ||
| 46 : | malsyned | 1092 | # This regex matches any string that: |
| 47 : | # : begins with ../ | ||
| 48 : | # : ends with /.. | ||
| 49 : | # : contains /../, or | ||
| 50 : | # : is .. | ||
| 51 : | malsyned | 1093 | if ($fullPath =~ m!(?:^|/)..(?:/|$)!) { |
| 52 : | die "Included file $file has potentially insecure path: contains \"..\""; | ||
| 53 : | malsyned | 1085 | } else { |
| 54 : | malsyned | 1093 | local @INC = (); |
| 55 : | do $fullPath; | ||
| 56 : | malsyned | 1085 | } |
| 57 : | malsyned | 1093 | }'; |
| 58 : | malsyned | 1092 | |
| 59 : | my $maskBackup = $safe->mask; | ||
| 60 : | $safe->mask(empty_opset); | ||
| 61 : | $safe->reval($include); | ||
| 62 : | $safe->mask($maskBackup); | ||
| 63 : | malsyned | 1085 | |
| 64 : | malsyned | 283 | # determine location of globalEnvironmentFile |
| 65 : | my $globalEnvironmentFile = "$webworkRoot/conf/global.conf"; | ||
| 66 : | sh002i | 319 | |
| 67 : | malsyned | 283 | # read and evaluate the global environment file |
| 68 : | my $globalFileContents = readFile($globalEnvironmentFile); | ||
| 69 : | sh002i | 319 | $safe->reval($globalFileContents); |
| 70 : | |||
| 71 : | # if that evaluation failed, we can't really go on... | ||
| 72 : | # we need a global environment! | ||
| 73 : | malsyned | 283 | $@ and die "Could not evaluate global environment file $globalEnvironmentFile: $@"; |
| 74 : | |||
| 75 : | # determine location of courseEnvironmentFile | ||
| 76 : | sh002i | 319 | # pull it out of $safe's symbol table ad hoc |
| 77 : | # (we don't want to do the hash conversion yet) | ||
| 78 : | no strict 'refs'; | ||
| 79 : | my $courseEnvironmentFile = ${*{${$safe->root."::"}{courseFiles}}}{environment}; | ||
| 80 : | use strict 'refs'; | ||
| 81 : | |||
| 82 : | malsyned | 283 | # read and evaluate the course environment file |
| 83 : | sh002i | 319 | # if readFile failed, we don't bother trying to reval |
| 84 : | my $courseFileContents = eval { readFile($courseEnvironmentFile) }; # catch exceptions | ||
| 85 : | $@ or $safe->reval($courseFileContents); | ||
| 86 : | malsyned | 304 | |
| 87 : | sh002i | 319 | # get the safe compartment's namespace as a hash |
| 88 : | no strict 'refs'; | ||
| 89 : | my %symbolHash = %{$safe->root."::"}; | ||
| 90 : | use strict 'refs'; | ||
| 91 : | |||
| 92 : | # convert the symbol hash into a hash of regular variables. | ||
| 93 : | my $self = {}; | ||
| 94 : | foreach my $name (keys %symbolHash) { | ||
| 95 : | # weed out internal symbols | ||
| 96 : | next if $name =~ /^(INC|_|__ANON__|main::)$/; | ||
| 97 : | # pull scalar, array, and hash values for this symbol | ||
| 98 : | my $scalar = ${*{$symbolHash{$name}}}; | ||
| 99 : | my @array = @{*{$symbolHash{$name}}}; | ||
| 100 : | my %hash = %{*{$symbolHash{$name}}}; | ||
| 101 : | # for multiple variables sharing a symbol, scalar takes precedence | ||
| 102 : | # over array, which takes precedence over hash. | ||
| 103 : | if (defined $scalar) { | ||
| 104 : | $self->{$name} = $scalar; | ||
| 105 : | } elsif (@array) { | ||
| 106 : | $self->{$name} = \@array; | ||
| 107 : | } elsif (%hash) { | ||
| 108 : | $self->{$name} = \%hash; | ||
| 109 : | } | ||
| 110 : | } | ||
| 111 : | |||
| 112 : | malsyned | 283 | bless $self, $class; |
| 113 : | return $self; | ||
| 114 : | } | ||
| 115 : | |||
| 116 : | 1; | ||
| 117 : | sh002i | 440 | |
| 118 : | __END__ | ||
| 119 : | |||
| 120 : | =head1 SYNOPSIS | ||
| 121 : | |||
| 122 : | use WeBWorK::CourseEnvironment; | ||
| 123 : | $courseEnv = WeBWorK::CourseEnvironment->new($webworkRoot, $courseName); | ||
| 124 : | |||
| 125 : | $timeout = $courseEnv->{sessionKeyTimeout}; | ||
| 126 : | $mode = $courseEnv->{pg}->{options}->{displayMode}; | ||
| 127 : | # etc... | ||
| 128 : | |||
| 129 : | =head1 DESCRIPTION | ||
| 130 : | |||
| 131 : | The WeBWorK::CourseEnvironment module reads the system-wide F<global.conf> and | ||
| 132 : | course-specific F<course.conf> files used by WeBWorK to calculate and store | ||
| 133 : | settings needed throughout the system. The F<.conf> files are perl source files | ||
| 134 : | that can contain any code allowed under the default safe compartment opset. | ||
| 135 : | After evaluation of both files, any package variables are copied out of the | ||
| 136 : | safe compartment into a hash. This hash becomes the course environment. | ||
| 137 : | |||
| 138 : | =head1 CONSTRUCTION | ||
| 139 : | |||
| 140 : | =over | ||
| 141 : | |||
| 142 : | =item new (ROOT, COURSE) | ||
| 143 : | |||
| 144 : | The C<new> method finds the file F<conf/global.conf> relative to the given ROOT | ||
| 145 : | directory. After reading this file, it uses the C<$courseFiles{environment}> | ||
| 146 : | variable, if present, to locate the course environment file. If found, the file | ||
| 147 : | is read and added to the environment. | ||
| 148 : | |||
| 149 : | =back | ||
| 150 : | |||
| 151 : | =head1 ACCESS | ||
| 152 : | |||
| 153 : | There are no formal accessor methods. However, since the course environemnt is | ||
| 154 : | a hash of hashes and arrays, is exists as the self hash of an instance | ||
| 155 : | variable: | ||
| 156 : | |||
| 157 : | $courseEnvironment->{someKey}->{someOtherKey}; | ||
| 158 : | |||
| 159 : | =head1 AUTHOR | ||
| 160 : | |||
| 161 : | Written by Sam Hathaway, sh002i (at) math.rochester.edu. | ||
| 162 : | |||
| 163 : | =cut |
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |