|
Home About
FAQs
General Admin Assist Student
Docs
Admin Assistant
CGI
Admin Assistant Download Form Student
Packages
AdminInterface Assignments AssistantInterface Form Interface Record Roster StudentInterface SystemVariables Teams VincentFile VincentLog |
|
0 #System Variables Maintenance Package 1 #Copyright 2000 Matt Jadud 2 #This program is free software; you can redistribute it and/or 3 #modify it under the terms of the GNU General Public License 4 #as published by the Free Software Foundation; either version 2 5 #of the License, or (at your option) any later version. 6 # 7 #This program is distributed in the hope that it will be useful, 8 #but WITHOUT ANY WARRANTY; without even the implied warranty of 9 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 #GNU General Public License for more details. 11 # 12 #You should have received a copy of the GNU General Public License 13 #along with this program; if not, write to the Free Software 14 #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 15 16 17 package SystemVariables; 18 $| = 1; 19 20 use Fcntl qw(:flock); # imports LOCK_EX, LOCK_SH, LOCK_NB 21 use English; 22 use VincentLog; 23 use Record; 24 25 my ( $key, 26 $value, 27 %Variables, 28 %ConfigVariables, 29 %StudentDefaults, 30 $localpath, 31 $SYSDEBUG, 32 $ADMINDEBUG, 33 $debuglevel, 34 $user, 35 $dbl 36 ); 37 38 39 #Load the Variables 40 41 #print STDERR "\n$UID - $EUID - $0\n"; 42 $USEBELOW = 1; 43 44 45 46 ($account) = getpwuid($UID); 47 48 loadVariables(%Variables, "/u/$account/.vincent3/config/.vp"); 49 loadVariables(%ConfigVariables, getCourseConfigFile()); 50 loadVariables(%StudentDefaults, getStudentDefaultsFile()); 51 52 return 1; 53 54 sub useDebugging { 55 56 return $SYSDEBUG; 57 58 } 59 60 sub getLogPath { 61 return processVariable($Variables{"LOGPATH"}); 62 } 63 64 sub getAllPostProcessors { 65 66 my(@proc, 67 @trim, 68 $item, 69 $path); 70 $path = getCallbackPath(); 71 @proc = glob($path . "*.vpp"); 72 73 foreach $item (@proc) { 74 $item =~ /.*/(.*).vpp$/; 75 push(@trim, $1); 76 } 77 78 return @trim; 79 } 80 81 82 sub useDoneness { 83 84 my ($done); 85 $done = getStudentDefault("_DONENESS"); 86 chomp $done; 87 88 #This information is stored as a 89 # "YES" or "NO" in the defaults file. 90 # It should be converted into a boolean here, 91 # not somewhere else. 92 if($done eq "YES") { 93 return 1; 94 } else { 95 return 0; 96 } 97 } 98 99 sub useTeams { 100 101 my ($team); 102 $team = getStudentDefault("_USETEAMS"); 103 chomp $team; 104 105 #This information is stored as a 106 # "YES" or "NO" in the defaults file. 107 # It should be converted into a boolean here, 108 # not somewhere else. 109 if($team eq "YES") { 110 return 1; 111 } else { 112 return 0; 113 } 114 } 115 116 ##CONTRACT 117 # getAllGradeMappings : void -> ArrayRef 118 ##PURPOSE 119 # Returns a list of all grade mappings in the system. In particular, 120 # it returns the user's names for the mappings, not the system names. 121 ##DEPENDANCIES 122 # SystemVariables::getCourseConfigPath() 123 sub getAllGradeMappings { 124 125 my($path, 126 @mappings, 127 $file, 128 @mapname); 129 130 #All mappings are stored in the course 131 # config area. 132 $path = getCourseConfigPath(); 133 134 #Grab all files matching the MAPPING* pattern. These 135 # are grade mapping files. 136 @mappings = glob("$path" . "MAPPING*"); 137 138 #For each file found 139 # Open the file, grab the name 140 # (the first line of the file is #NAME: ), 141 # and push it onto an array 142 foreach $file (@mappings) { 143 open(MAP, $file); 144 while(<MAP>) { 145 if(/#NAME: (.*)/) { 146 push(@mapname, $1); 147 } 148 } 149 close(MAP); 150 } 151 152 #Chomp the array 153 chomp(@mapname); 154 155 #SystemVariables::DEBUG("SysVar:", @mapname); 156 157 #Return a reference to the list of mapping names. 158 return @mapname; 159 } 160 161 ##CONTRACT 162 # existInList : scalar(String) ListRef -> boolean 163 ##PURPOSE 164 # If the item passed in (string, or other scalar) 165 # is contained in the list referenced by ListRef, 166 # 1 (true) is returned. Otherwise, a 0 is returned (false). 167 ##DEPENDANCIES 168 # None. 169 sub existInList { 170 171 my($item, $litem, $list); 172 173 ($item, $list) = @_; 174 chomp $item; 175 176 #For each item in the list, if it is 177 # equal to the test item, return one. 178 # This halts the loop. 179 foreach $litem (@{$list}) { 180 chomp $litem; 181 if("$litem" eq "$item") { 182 return 1; 183 } 184 } 185 186 #If no matches were found, return zero. 187 return 0; 188 } 189 190 ##CONTRACT 191 # getDownloadableFileDataPath : String -> String 192 ##PURPOSE 193 # Consumes a string representing the system ID for 194 # a file previously submitted for download by the course 195 # administrator. This is typically of the form "DOWNLOAD\d+", 196 # or "DOWNLOAD0", "DOWNLOAD1", etc. Returns the full path 197 # to the .data file containing information regarding download 198 # permissions and download dates, if applicable. 199 ##DEPENDANCIES 200 # SystemVariables::getCourseConfigPath() 201 sub getDownloadableFileDataPath { 202 203 my ($sysID); 204 $sysID = $_[0]; 205 206 return getCourseConfigPath() . $sysID . ".data"; 207 } 208 209 210 ##CONTRACT 211 # _getAdminIndex : String -> Number 212 ##PURPOSE 213 # Takes a file path for a downloadable 214 # file submitted by the course administrator, 215 # and returns the index of the file. 216 ##EXAMPLE 217 # Given "DOWNLOAD5," it would return '5'. 218 ##DEPENDANCIES 219 # None. 220 sub _getAdminIndex { 221 222 my($name); 223 $name = $_[0]; 224 225 #Pull the index out with a regular expression 226 # and return the result of the match. 227 $name =~ /.*DOWNLOAD(d+)/; 228 return $1; 229 } 230 231 232 ##CONTRACT 233 # getNextAdminFileUploadName : void -> String 234 ##PURPOSE 235 # Returns the next index for files submitted for 236 # download by the course administrator. For example: 237 ##EXAMPLE 238 # If the only file in the system is "DOWNLOAD0", it 239 # should return "DOWNLOAD1," and so on. 240 ##DEPENDANCIES 241 # SystemVariables::_getAdminIndex() 242 # SystemVariables::getCourseConfigPath(); 243 sub getNextAdminFileUploadName { 244 245 my($path, 246 @files, 247 $filename, 248 $filenumber 249 ); 250 251 #Get the path to the course config area, and 252 # glob all files marked as available for download. 253 $path = getCourseConfigPath(); 254 @files = glob($path . "DOWNLOAD*"); 255 256 #If any files were found, sort them by index 257 #Pop the highest number found 258 #Increment the index 259 #Return the next system filename 260 #If no files were found 261 #Return the zeroth index. 262 if(@files) { 263 264 @files = sort { _getAdminIndex($a) <=> _getAdminIndex($b) } @files; 265 $filename = pop(@files); 266 267 $filename =~ /DOWNLOAD(d+)/; 268 $filenumber = $1; 269 270 $filenumber++; 271 272 return "DOWNLOAD$filenumber"; 273 } else { 274 return "DOWNLOAD0"; 275 } 276 277 } 278 279 ##CONTRACT 280 # getAdminList : void -> ArrayRef 281 ##PURPOSE 282 # Returns a list of usernames 283 # allowed to access the administrator script. 284 # Also captures the GODs, who should ALWAYS be present; 285 # The system is installed incorrectly if it is installed 286 # without individuals placed in a GOD field. 287 ##DEPENDANCIES 288 # SystemVariables::getCourseConfigPath(). 289 sub getAdminList { 290 291 my (@admins, 292 @gods, 293 $path); 294 295 296 #Grab a path to the list 297 $listpath = getCourseConfigPath() . "adminassistlist"; 298 299 #If the list exists (which the installer should have handled) 300 #Read the list, grabbing any administrators and gods 301 if(open(LIST, $listpath)) { 302 303 while(<LIST>) { 304 if(/ADMINISTRATORS/) { 305 ($tag, @admins) = (split(/|/)); 306 } 307 if(/GOD/) { 308 ($tag, @gods) = (split(/|/)); 309 } 310 } 311 } 312 313 #Append the gods to the list of valid administrators, 314 # and return a reference to the administrator list. 315 @admins = (@admins, @gods); 316 317 return @admins; 318 319 } 320 321 ##CONTRACT 322 # getGodList : void -> ArrayRef 323 ##PURPOSE 324 # Returns a list of usernames 325 # allowed to access the administrator script as GODS. 326 # These should have been added by the installer, 327 # and cannot be edited from within the system itself. 328 ##DEPENDANCIES 329 # SystemVariables::getCourseConfigPath(). 330 sub getGodList { 331 332 my (@gods, 333 $path); 334 335 336 #Grab a path to the list 337 $listpath = getCourseConfigPath() . "adminassistlist"; 338 339 #If the list exists (which the installer should have handled) 340 #Read the list, grabbing any gods 341 if(open(LIST, $listpath)) { 342 343 while(<LIST>) { 344 345 if(/GOD/) { 346 ($tag, @gods) = (split(/|/)); 347 } 348 } 349 } 350 351 #SystemVariables::DEBUG("SysVar:", "Found Gods: ", @gods); 352 353 #Append the gods to the list of valid administrators, 354 # and return a reference to the administrator list. 355 356 return @gods; 357 358 } 359 360 ##CONTRACT 361 # getGodString : void -> String 362 ##PURPOSE 363 # Take the list of gods in the system, and 364 # turn them into a space-delimited string. 365 ##DEPENDANCIES 366 # SystemVariables::getAdminList() 367 sub getGodString { 368 369 my ($gods, $string); 370 371 $gods = getGodList(); 372 $string = ""; 373 374 #Concatonate each admin in the 375 # list onto an empty string. 376 foreach (@{$gods}) { 377 $string .= $_; 378 $string .= " "; 379 } 380 381 return $string; 382 } 383 384 385 ##CONTRACT 386 # getAdminString : void -> String 387 ##PURPOSE 388 # Take the list of administrators in the system, and 389 # turn them into a space-delimited string. 390 ##DEPENDANCIES 391 # SystemVariables::getAdminList() 392 sub getAdminString { 393 394 my ($admins, $string); 395 396 $admins = getAdminList(); 397 $string = ""; 398 399 #Concatonate each admin in the 400 # list onto an empty string. 401 foreach (@{$admins}) { 402 $string .= $_; 403 $string .= " "; 404 } 405 406 return $string; 407 } 408 409 ##CONTRACT 410 # getAssistList : void : ArrayRef 411 ##PURPOSE 412 # Returns an array reference containing 413 # the usernames of all individuals allowed 414 # to serve as assistants/TAs in the course. 415 ##DEPENDANCIES 416 # SystemVariables::getCourseConfigPath() 417 sub getAssistList { 418 419 my (@assists, 420 $path); 421 422 @assists = (); 423 424 #Grab the path to the file. 425 $listpath = getCourseConfigPath() . "adminassistlist"; 426 427 #If the file can be opened 428 # Grab all the assistants in the list into an array. 429 if(open(LIST, $listpath)) { 430 431 while(<LIST>) { 432 if(/ASSISTANTS/) { 433 ($tag, @assists) = (split(/|/)); 434 } 435 } 436 } 437 438 #Return a reference to the assistants array. 439 return @assists; 440 441 } 442 443 ##CONTRACT 444 # getAssistString : void -> String 445 ##PURPOSE 446 # Return the list of assistants in the course 447 # as a space-delimited string. 448 ##DEPENDANCIES 449 # SystemVariables::getAssistList() 450 sub getAssistString { 451 452 my ($assists, $string); 453 454 $assists = getAssistList(); 455 $string = ""; 456 457 #Concatonate each assistant in the 458 # list onto an empty string. 459 foreach (@{$assists}) { 460 $string .= $_; 461 $string .= " "; 462 } 463 464 return $string; 465 } 466 467 ##CONTRACT 468 # updateAdminAssistList : ArrayRef ArrayRef -> void 469 ##PURPOSE 470 # Takes a reference containing an array of username 471 # for administrators, an array of usernames for 472 # assistants, and updates the file 'adminassistlist'. 473 ##DEPENDANCIES 474 # SystemVariables::getCourseConfigPath(); 475 sub updateAdminAssistList { 476 477 my ($listpath, 478 $admins, 479 $assists, 480 $gods); 481 482 #The new list of admins and assistants 483 # should have been passed in as array references. 484 $admins = $_[0]; 485 $assists = $_[1]; 486 $gods = getGodList(); 487 $listpath = getCourseConfigPath() . "adminassistlist"; 488 489 #Open the file for writing, overwrite old data. 490 open(LIST, ">$listpath"); 491 492 #Filelock. There shouldn't be multiple writes, but 493 # better safe than sorry. 494 flock(LIST, LOCK_EX); 495 496 #Update the administrators. 497 print LIST "_ADMINISTRATORS"; 498 foreach (@{$admins}) { 499 print LIST "|$_"; 500 } 501 print LIST "n"; 502 503 #Update the assistants 504 print LIST "_ASSISTANTS"; 505 foreach (@{$assists}) { 506 print LIST "|$_"; 507 } 508 print LIST "n"; 509 510 #Reprint the gods 511 print LIST "_GODS"; 512 foreach (@{$gods}) { 513 print LIST "|$_"; 514 } 515 print LIST "n"; 516 517 518 close(LIST); 519 } 520 521 ##CONTRACT 522 # canStudentDownload : void -> SysValue (string) 523 ##PURPOSE 524 # Returns the system wide variable set by the administrator 525 # determining whether students are or are not allowed to 526 # download their own files. This value is either "YES" or "NO". 527 ##DEPENDANCIES 528 # None. 529 sub canStudentsDownload { 530 return $StudentDefaults{"_STUFILEDOWNLOAD"}; 531 } 532 533 ##CONTRACT 534 # canAssistantEditTeams : void -> boolean 535 ##PURPOSE 536 # If assistants can currently edit teams, returns 1. 537 ##DEPENDANCIES 538 # None. 539 sub canAssistantEditTeams { 540 if($StudentDefaults{"_ASSISTANTEDITTEAMS"} eq "YES") { 541 return 1; 542 } else { 543 return 0; 544 } 545 } 546 547 548 ##CONTRACT 549 # getCallingScript : void -> String 550 ##PURPOSE 551 # Gets the calling script from the environment, 552 # and returns the short form of the script 553 # that is currently executing. 554 ##EXAMPLES 555 # If the admin script is currently executing, it 556 # returns "admin." Student and Assistant are 557 # likewise returned for student.cgi and assistant.cgi 558 ##DEPENDANCIES 559 # Browser Evironment. 560 sub getCallingScript { 561 562 my($string, $script); 563 564 $string = $ENV{SCRIPT_NAME}; 565 566 if($string =~ /student/) { 567 return "student"; 568 } elsif ($string =~ /assistant/) { 569 return "assistant"; 570 } elsif ($string =~ /admin/) { 571 return "admin"; 572 } 573 } 574 575 ##CONTRACT 576 # getCurrentYear : Number -> Number 577 ##PURPOSE 578 # Returns the current year, plus or minus any and 579 # all arguments passed in. 580 ##EXAMPLE 581 # getCurrentYear() returns the current year. 582 # getCurrentYear(1) returns the current year + 1. 583 # getCurrentYear(-1) returns the current year -1. 584 ##DEPENDANCIES 585 # SystemVariables::currentTime(); 586 sub getCurrentYear { 587 my($value, $arg); 588 589 $value = (split(/,/, currentTime()))[0]; 590 foreach $arg (@_) { 591 $value += $arg; 592 } 593 594 #Check for leading zeroness. 595 if(($value !~ /0/) && ($value < 10)) { 596 $value = "0$arg"; 597 } 598 599 return $value; 600 } 601 602 ##CONTRACT 603 # getCurrentMonth : Number -> Number 604 ##PURPOSE 605 # Returns the current year, plus any values passed in. 606 ##EXAMPLE 607 # getCurrentMonth() returns the current month as 01 -> 12 608 # getNextMonth(+1) returns the current month +1, mod 12 609 ##DEPENDANCIES 610 # SystemVariables::currentTime() 611 sub getCurrentMonth { 612 my($value, $arg); 613 614 $value = (split(/,/, currentTime()))[1]; 615 foreach $arg (@_) { 616 $value += $arg; 617 } 618 619 #Check for leading zeroness. 620 if(($value !~ /0/) && ($value < 10)) { 621 $value = "0" . $value; 622 } 623 624 #Nasty, two step process; take the modulo. 625 # if we somehow ended up with 0, add one. 626 # This handles a case where someone wanted 627 # December plus some multiple of 12 months. 628 if($value > 12) { 629 $value = $value%12; 630 } 631 if($value == 0) { 632 $value = 12; 633 } 634 635 return $value; 636 } 637 638 ##CONTRACT 639 # getCurrentTime : void -> VincentDateString 640 ##PURPOSE 641 # currentTime() was named incorrectly. It should 642 # have been named getCurrentTime, in keeping with 643 # all other system 'gets.' Unfortunately, this was 644 # not the case. 'getCurrentTime' is nothing more 645 # than a wrapper. 646 ##DEPENDANCIES 647 # SystemVariables::currentTime() 648 sub getCurrentTime { 649 650 return currentTime(); 651 } 652 653 ############################DANGER 654 # 655 # This function allows the addition 656 # of a number to the current day. However, 657 # there was _no_ checking of the number 658 # based on the current month. This being the 659 # case, things like "2000,01,32" could be 660 # valid dates. 661 # 662 # Given that all date sorting is completely 663 # numeric, this would not be a problem... 664 # the "currentTime" compared to an incorrect 665 # date like this would yield 666 # 667 # 20000201120000 vs. 200001321120000 668 # 669 # Comparing Feb 1, 2000 vs. Jan 32, 2000. 670 # Feb 1 is still "greater," although Jan 32 is 671 # invalid as a date. 672 # 673 # It is currently unknown as to whether this is a problem. 674 # An analysis of what functions depend on this is forthcoming. 675 ##CONTRACT 676 # getCurrentDay : Number -> Number 677 ##PURPOSE 678 # Return the current day, plus any arguments. 679 ##DEPENDANCIES 680 # SystemVariables::currentTime() 681 sub getCurrentDay { 682 my($value, $arg); 683 684 $value = (split(/,/, currentTime()))[2]; 685 foreach $arg (@_) { 686 $value += $arg; 687 } 688 689 if(($value !~ /0/) && ($value < 10)) { 690 $value = "0" . $value; 691 } 692 693 return $value; 694 } 695 696 ##CONTRACT 697 # getCallbackPath : void -> String 698 ##PURPOSE 699 # Returns the path to the directory where callback scripts 700 # should live. 701 ##DEPENDANCIES 702 # None. 703 sub getCallbackPath { 704 return processVariable($Variables{"CALLBACKPATH"}); 705 } 706 707 ##CONTRACT 708 # getJulesPath : void -> String 709 ##PURPOSE 710 # Returns the string to where Jules files should end 711 # up in the system. Currently no longer used. 712 ##DEPENDANCIES 713 # None. 714 sub getJulesPath { 715 return processVariable($Variables{"JULESPATH"}); 716 } 717 718 ##CONTRACT 719 # getStudentRecordPath : String -> $String 720 ##PURPOSE 721 # Takes a username, and returns a path to 722 # that student's personal record space in the system. 723 ##DEPENDANCIES 724 # SystemVariables::getRecordPath() 725 sub getStudentRecordPath { 726 727 my ($username); 728 729 $username = $_[0]; 730 731 return getRecordPath() . $username . "/"; 732 } 733 734 ##CONTRACT 735 # useSlipTime : void -> boolean 736 ##PURPOSE 737 # Returns true if the system uses sliptime; false otherwise. 738 ##DEPENDANCIES 739 # SystemVariables::getStudentDefault() 740 sub useSlipTime { 741 742 my ($slip); 743 $slip = getStudentDefault("_USESLIPTIME"); 744 chomp $slip; 745 746 #This information is stored as a 747 # "YES" or "NO" in the defaults file. 748 # It should be converted into a boolean here, 749 # not somewhere else. 750 if($slip eq "YES") { 751 return 1; 752 } else { 753 return 0; 754 } 755 756 } 757 758 759 ##CONTRACT 760 # showAverage : void -> boolean 761 ##PURPOSE 762 # Returns 1 if the administrator 763 # would like students to see the class average 764 # along with their grades. 765 ##DEPENDANCIES 766 # SystemVariables::getStudentDefault() 767 sub showAverage { 768 769 my ($avg); 770 $avg = getStudentDefault("_SHOWAVERAGE"); 771 chomp $avg; 772 773 774 #This information is stored as a 775 # "YES" or "NO" in the defaults file. 776 # It should be converted into a boolean here, 777 # not somewhere else. 778 if($avg eq "YES") { 779 return 1; 780 } else { 781 return 0; 782 } 783 784 } 785 786 787 ##CONTRACT 788 # getEarlierDate : string string -> string 789 ##PURPOSE 790 # Takes two strings of the format "YYYY,MM,DD,HH:MM:SS" and 791 # returns the earlier of the two. 792 # Uses string comparison to find the earlier of the two. 793 ##DEPENDANCIES 794 # None. 795 sub getEarlierDate { 796 797 my ( $date1, 798 $date2, 799 $y1, 800 $y2, 801 $m1, 802 $m2, 803 $d1, 804 $d2, 805 $t1, 806 $t2, 807 @earlier, 808 $fix, 809 $index, 810 $earlier 811 ); 812 813 #The two dates should both be strings in VincentDate format. 814 ($date1, $date2) = @_; 815 chomp $date1; 816 chomp $date2; 817 818 SystemVariables::DEBUG("SysVar:", "Comparing $date1 and $date2"); 819 820 #Split the strings into their various components. 821 ($y1, $m1, $d1, $t1) = (split(/,/, $date1)); 822 ($y2, $m2, $d2, $t2) = (split(/,/, $date2)); 823 824 #Now, fix the months and days 825 @fix = ($m1, $m2, $d1, $d2); 826 $index = 0; 827 foreach (@fix) { 828 if(($_ < 10) && ($_ !~ /^0/)) { 829 $fix[$index] = "0$_"; 830 } 831 $index++; 832 } 833 834 #Place values back in variables 835 ($m1, $m2, $d1, $d2) = @fix; 836 837 #Repack the date strings 838 $date1 = "$y1,$m1,$d1,$t1"; 839 $date2 = "$y2,$m2,$d2,$t2"; 840 841 #For cleanup and comparison 842 $d1 = $date1; 843 $d2 = $date2; 844 845 #Strip all commas, colons 846 # from both strings. This converts 847 # 848 # 2000,01,31,12:00:00 849 # to 850 # 20000131120000 851 # 852 # which can be compared numerically. 853 $d1 =~ s/,//g; 854 $d1 =~ s/://g; 855 $d2 =~ s/,//g; 856 $d2 =~ s/://g; 857 858 #Return the smaller of the two dates. 859 if($d1 < $d2) { 860 #SystemVariables::DEBUG("SysVar:", $d1, " ", $d2, " ", "$date1 is the earlier date."); 861 return $date1; 862 } else { 863 #SystemVariables::DEBUG("SysVar:", $d1, " ", $d2, " ", "$date2 is the earlier date."); 864 return $date2; 865 } 866 867 868 } 869 870 871 #Returns difference between first and second time submitted 872 sub deltaTime { 873 874 my( $stamp1, 875 $stamp2, 876 $year1, 877 $year2, 878 $month1, 879 $month2, 880 $day1, 881 $day2, 882 $time1, 883 $time2, 884 $hours1, 885 $hours2, 886 $minutes1, 887 $minutes2, 888 $seconds1, 889 $seconds2, 890 $delta 891 ); 892 893 $stamp1 = $_[0]; 894 $stamp2 = $_[1]; 895 896 ($year1, $month1, $day1, $time1) = (split(/,/, $stamp1)); 897 ($year2, $month2, $day2, $time2) = (split(/,/, $stamp2)); 898 899 ($hours1, $minutes1, $seconds1) = (split(/:/, $time1)); 900 ($hours2, $minutes2, $seconds2) = (split(/:/, $time2)); 901 902 #Convert everything to seconds 903 $seconds1 += 60 * $minutes1; 904 $seconds1 += 60 * 60 * $hours1; 905 $seconds1 += 24 * 60 * 60 * $day1; 906 #Assume all months have 30 days. 907 $seconds1 += 30 * 24 * 60 * 60 * $month1; 908 $seconds1 += 365 * 24 * 60 * 60 * $year1; 909 910 #Convert everything to seconds 911 $seconds2 += 60 * $minutes2; 912 $seconds2 += 60 * 60 * $hours2; 913 $seconds2 += 24 * 60 * 60 * $day2; 914 #Assume all months have 30 days. 915 $seconds2 += 30 * 24 * 60 * 60 * $month2; 916 $seconds2 += 365 * 24 * 60 * 60 * $year2; 917 918 $delta = $seconds1 - $seconds2; 919 920 return $delta; 921 } 922 923 sub addMinutes { 924 925 my($date, 926 $addmin, 927 $year, 928 $month, 929 $day, 930 $hours, 931 $minutes, 932 $seconds, 933 $string); 934 935 $date = $_[0]; 936 $addmin = $_[1]; 937 938 ($year, $month, $day, $time) = (split(/,/, $date)); 939 940 ($hours, $minutes, $seconds) = (split(/:/, $time)); 941 942 $minutes += $addmin; 943 944 #If we are over 60 minutes, take the mod60 and 945 # bump hours by one. 946 if($minutes >= 60) { 947 $minutes = $minutes%60; 948 949 $hours += 1; 950 951 #If hours broke 24, take the mod24, and bump days. 952 # If someone is permitting files over a month boundary, 953 # this will break. 954 if($hours >= 24) { 955 $hours = $hours%24; 956 $day += 1; 957 } 958 } 959 960 if(($minutes < 10) && ($minutes !~ /^0/)) { 961 $minutes = "0$minutes"; 962 } 963 964 if(($hours < 10) && ($hours !~ /^0/)) { 965 $hours = "0$hours"; 966 } 967 968 if(($day < 10) && ($day !~ /^0/)) { 969 $day = "0$day"; 970 } 971 972 $string = $year . "," . $month . "," . $day . "," . 973 $hours . ":" . $minutes . ":" . "00"; 974 975 return $string; 976 } 977 978 979 ##CONTRACT 980 # currentTime : void -> string 981 ##PURPOSE 982 # Returns the current time in YYYY,MM,DD,HH:MM:SS format. 983 ##DEPENDANCIES 984 # SystemVariables::vincentDate() 985 sub currentTime { 986 return vincentDate(scalar localtime); 987 } 988 989 ##CONTRACT 990 # vincentDate : string -> string 991 ##PURPOSE 992 # Takes a date in the string format returned by the "date" command 993 # in Perl, and returns it in a YYYY,MM,DD,HH:MM:SS format. 994 ##DEPENDANCIES 995 # None. 996 sub vincentDate { 997 998 my ($date, 999 %Months, 1000 $month, 1001 $day, 1002 $year, 1003 $time); 1004 1005 #The current date in Perl (scalar, or string) date format. 1006 $date = $_[0]; 1007 1008 %Months = ("Jan", "01", 1009 "Feb", "02", 1010 "Mar", "03", 1011 "Apr", "04", 1012 "May", "05", 1013 "Jun", "06", 1014 "Jul", "07", 1015 "Aug", "08", 1016 "Sep", "09", 1017 "Oct", "10", 1018 "Nov", "11", 1019 "Dec", "12"); 1020 1021 1022 ($month, $day, $year, $time) = (split(/s+/, $date))[1,2,4,3]; 1023 chomp $month; 1024 chomp $day; 1025 chomp $year; 1026 chomp $time; 1027 1028 1029 $month = $Months{$month}; 1030 1031 # HACK ALERT ***************** robh 1032 # '0' pad the date if 1-9 1033 $day = "0$day" if ($day < 10); 1034 1035 $date = "$year,$month,$day,$time"; 1036 return $date; 1037 } 1038 1039 ##CONTRACT 1040 # getStudentDefaultsFile : void -> string 1041 ##PURPOSE 1042 # Returns the full path to the file containing 1043 # defaults for all students in the system. 1044 ##DEPENDANCIES 1045 # SystemVariables::processVariable() 1046 sub getStudentDefaultsFile { 1047 return processVariable($Variables{"STUDENTDEFAULTS"}); 1048 } 1049 1050 ##CONTRACT 1051 # getStudentDefaults : void -> REF(hash) 1052 ##PURPOSE 1053 # Returns a hash reference to a hash containing all the defaults 1054 # for all students in the system. 1055 ##DEPENDANCIES 1056 # None. 1057 sub getStudentDefaults { 1058 return %StudentDefaults; 1059 } 1060 1061 ##CONTRACT 1062 # getStudentDefault : string -> string 1063 ##PURPOSE 1064 # Looks up the given key in the student default 1065 # file and returns the value found. 1066 ##DEPENDANCIES 1067 # SystemVariables::getStudentDefaults() 1068 sub getStudentDefault { 1069 my ($variable, 1070 $defaults); 1071 1072 $variable = $_[0]; 1073 1074 $defaults = getStudentDefaults(); 1075 1076 return $$defaults{$variable}; 1077 } 1078 1079 ##CONTRACT 1080 # writeStudentDefaults : REF(hash) -> void 1081 ##PURPOSE 1082 # Takes a hash reference containing student defaults, and 1083 # writes those defaults to the system-wide defaults file. 1084 # Old defaults are overwritten. 1085 # 1086 # THIS DOES NOT UPDATE ALL STUDENTS. 1087 ##DEPENDANCIES 1088 # SystemVariables::getStudentDefaultsFile() 1089 sub writeStudentDefaults { 1090 1091 my ($file, 1092 $defaults, 1093 $param, 1094 %StuUpdate 1095 ); 1096 %StuUpdate = (); 1097 1098 $file = getStudentDefaultsFile(); 1099 chomp $file; 1100 $defaults = $_[0]; 1101 1102 SystemVariables::DEBUG("SysVar:", "Writing defaults."); 1103 1104 open(DEFAULTS, ">$file") || 1105 die("Can't open defaults at $file."); 1106 1107 foreach $param (keys %{$defaults}) { 1108 if($param =~ /^_/) { 1109 print DEFAULTS $param, "|", $$defaults{$param}, "n"; 1110 SystemVariables::DEBUG("SysVar:", $param, "::", $$defaults{$param}); 1111 1112 #Build an update hash. This hash will 1113 # filter out sliptime, unless it is explicitly 1114 # tagged to be updated by the course administrator. 1115 if($param eq "_SLIPTIME") { 1116 if(defined($$defaults{"resetsliptime"}) 1117 && 1118 $$defaults{"resetsliptime"} eq "1") { 1119 SystemVariables::DEBUG("SysVar:", "<STRONG>Resetting sliptime.</STRONG>"); 1120 $StuUpdate{$param} = $$defaults{$param}; 1121 } 1122 } elsif($param eq "_CLASSEXPIRATION") { 1123 if(defined($$defaults{"updateallexp"}) 1124 && 1125 $$defaults{"updateallexp"} eq "1") { 1126 SystemVariables::DEBUG("SysVar:", "<STRONG>Setting expiration to </STRONG>", $$defaults{"_CLASSEXPIRATION"}); 1127 $StuUpdate{"_EXPIRATION"} = $$defaults{"_CLASSEXPIRATION"}; 1128 } 1129 } else { 1130 $StuUpdate{$param} = $$defaults{$param}; 1131 } 1132 } 1133 } 1134 1135 close(DEFAULTS); 1136 1137 1138 1139 #Update all the student records with this data. 1140 1141 Record::updateAllStudentRecords(%StuUpdate); 1142 } 1143 1144 ##CONTRACT 1145 # getStudentWebPath : void -> string 1146 ##PURPOSE 1147 # Returns a string representing the full http:// URL to the 1148 # student-side script. 1149 ##DEPENDANCIES 1150 # SystemVariables::processVariable() 1151 sub getStudentWebPath { 1152 return processVariable($Variables{"STUDENTWEBPATH"}); 1153 } 1154 1155 ##CONTRACT 1156 # getStudentRealPath : void -> String 1157 ##PURPOSE 1158 # Returns a path to the student script, in terms 1159 # of the filesystem, not the WWW (URL). 1160 ##DEPENDANCIES 1161 # SystemVariables::processVariable() 1162 sub getStudentRealPath { 1163 return processVariable($Variables{"STUDENTREALPATH"}); 1164 } 1165 1166 ########################DEPRECATED 1167 # 1168 # This function should not be used anymore. This 1169 # predates when downloads were handled by download.cgi. 1170 # This function is useless, but remains until it is 1171 # known that it can be safely removed. 1172 ##CONTRACT 1173 # getDownloadWebPath : void -> String 1174 ##PURPOSE 1175 # Returns the URL to the download area of the script 1176 ##DEPENDANCIES 1177 # SystemVariables::processVariable() 1178 sub getDownloadWebPath { 1179 return processVariable($Variables{"DOWNLOADWEBPATH"}); 1180 } 1181 1182 sub getFormWebPath { 1183 return processVariable($Variables{"FORMWEBPATH"}); 1184 } 1185 1186 ##CONTRACT 1187 # getImageWebPath : void -> String 1188 ##PURPOSE 1189 # Returns the URL to the system images directory. 1190 ##DEPENDANCIES 1191 # SystemVariables::processVariable() 1192 sub getImageWebPath { 1193 return processVariable($Variables{"IMAGEWEBPATH"}); 1194 } 1195 1196 ########################DEPRECATED 1197 # 1198 # This function should not be used anymore. This 1199 # predates when downloads were handled by download.cgi. 1200 # This function is useless, but remains until it is 1201 # known that it can be safely removed. 1202 ##CONTRACT 1203 # getLinkRealPath : void -> String 1204 ##PURPOSE 1205 # Returns the path to where links for the system 1206 # should be created and destroyed 1207 ##DEPENDANCIES 1208 # SystemVariables::processVariable() 1209 sub getLinkRealPath { 1210 return processVariable($Variables{"LINKREALPATH"}); 1211 } 1212 1213 ########################DEPRECATED 1214 # 1215 # This function should not be used anymore. This 1216 # predates when downloads were handled by download.cgi. 1217 # This function is useless, but remains until it is 1218 # known that it can be safely removed. 1219 ##CONTRACT 1220 # getLinkWWWPath : void -> String 1221 ##PURPOSE 1222 # Returns the system path to where softlinks should 1223 # be created and destroyed. 1224 ##DEPENDANCIES 1225 # SystemVariables::processVariable() 1226 sub getLinkWWWPath { 1227 return processVariable($Variables{"LINKWEBPATH"}); 1228 } 1229 1230 1231 ##CONTRACT 1232 # getAdminWebPath : void -> string 1233 ##PURPOSE 1234 # Returns a string representing the full http:// URL to 1235 # the admin-side script. 1236 ##DEPENDANCIES 1237 # SystemVariables::processVariable() 1238 sub getAdminWebPath { 1239 1240 return processVariable($Variables{"ADMINWEBPATH"}); 1241 } 1242 1243 ##CONTRACT 1244 # getAdminRealPath : void -> String 1245 ##PURPOSE 1246 # Returns the system path to where the administrator 1247 # script lives. 1248 ##DEPENDANCIES 1249 # SystemVariables::processVariable() 1250 sub getAdminRealPath { 1251 return processVariable($Variables{"ADMINREALPATH"}); 1252 } 1253 1254 ##CONTRACT 1255 # getAssistantWebPath : void -> String 1256 ##PURPOSE 1257 # Returns the URL to where the assistant script lives. 1258 ##DEPENDANCIES 1259 # SystemVariables::processVariable() 1260 sub getAssistantWebPath { 1261 return processVariable($Variables{"ASSISTANTWEBPATH"}); 1262 } 1263 1264 ##CONTRACT 1265 # getAssistantRealPath : void -> String 1266 ##PURPOSE 1267 # Returns the system path to where the assistant script lives. 1268 ##DEPENDANCIES 1269 # SystemVariables::processVariable() 1270 sub getAssistantRealPath { 1271 return processVariable($Variables{"ASSISTANTREALPATH"}); 1272 } 1273 1274 ##CONTRACT 1275 # getClassTagline : void -> string 1276 ##PURPOSE 1277 # Returns the description of the course as set by the 1278 # course administrator. 1279 ##DEPENDANCIES 1280 # SystemVariables::getVariable() 1281 sub getClassTagline { 1282 return getVariable("TAGLINE"); 1283 } 1284 1285 ##CONTRACT 1286 # setClassTagline : string -> void 1287 ##PURPOSE 1288 # Sets the class tagline. 1289 ##DEPENDANCIES 1290 # SystemVariables::setVariable() 1291 sub setClassTagline { 1292 1293 my ($value); 1294 $value = $_[0]; 1295 chomp $value; 1296 1297 setVariable("TAGLINE", $value); 1298 } 1299 1300 ##CONTRACT 1301 # getClassID : void -> string 1302 ##PURPOSE 1303 # Returns the course ID as set by the administrator. 1304 ##DEPENDANCIES 1305 # SystemVariables::getVariable() 1306 sub getClassID { 1307 return getVariable("CLASSID"); 1308 } 1309 1310 1311 ##CONTRACT 1312 # setClassID : string -> void 1313 ##PURPOSE 1314 # Sets the class ID. 1315 ##DEPENDANCIES 1316 # SystemVariables::setVariable() 1317 sub setClassID { 1318 1319 my ($value); 1320 $value = $_[0]; 1321 chomp $value; 1322 1323 setVariable("CLASSID", $value); 1324 } 1325 1326 ##CONTRACT 1327 # getVariable : string -> string 1328 ##PURPOSE 1329 # Takes a string representing a DB key for the desired 1330 # value, and returns the value of the system variable associated 1331 # with that key. 1332 ##DEPENDANCIES 1333 # None. 1334 sub getVariable { 1335 1336 my ($variable); 1337 $variable = $_[0]; 1338 chomp $variable; 1339 1340 return $ConfigVariables{$variable}; 1341 } 1342 1343 ##CONTRACT 1344 # setVariable : string string -> void. 1345 ##PURPOSE 1346 # Takes a record key and a value, and writes them into 1347 # the system config variables. 1348 ##DEPENDANCIES 1349 # SystemVariables::writeConfigVariables() 1350 sub setVariable { 1351 1352 1353 my ( %config, 1354 $record, 1355 $value 1356 ); 1357 1358 $record = $_[0]; 1359 $value = $_[1]; 1360 1361 #Take the hashtable currently loaded into memory 1362 # and modify the keyed value. 1363 $ConfigVariables{$record} = $value; 1364 1365 #webErrOut("Setting ", $record, " to ", $value); 1366 1367 #Write it to disc. 1368 writeConfigVariables(); 1369 1370 } 1371 1372 ##CONTRACT 1373 # writeConfigVariables : void -> void 1374 ##PURPOSE 1375 # Takes no arguments; writes the current system config 1376 # variable hash to disk. 1377 ##DEPENDANCIES 1378 # SystemVariables::getCourseConfigFile() 1379 sub writeConfigVariables { 1380 1381 my ($config); 1382 1383 $config = getCourseConfigFile(); 1384 1385 #webErrOut("Write to: ", $config); 1386 1387 open(CONFIG, ">$config") 1388 || 1389 die("No config file at $config"); 1390 1391 #LOCK THE FILE 1392 flock(CONFIG, LOCK_EX); 1393 1394 foreach $key (keys %ConfigVariables) { 1395 print CONFIG "$key|", $ConfigVariables{$key}, "n"; 1396 } 1397 1398 #FREE THE FILE 1399 close(CONFIG); 1400 1401 } 1402 1403 ##CONTRACT 1404 # loadVariables : REF(hash) string -> REF(hash) 1405 ##PURPOSE 1406 # Takes a hash reference and a string representing the path to a 1407 # config file, and reads those values into the hash passed in. 1408 # This hash is then returned. 1409 # 1410 ##NOTICE 1411 # The installer must put the .vp file in the root 1412 # of the administrator's home directory. The .vp 1413 # file dictates where everything else can be 1414 # found, and that is unique to each user. Hence, 1415 # if it cannot be assumed to be in the root of the user's 1416 # home directory, then the install script must be modified accordingly, 1417 # as must this module. 1418 ##DEPENDANCIES 1419 # None. 1420 sub loadVariables { 1421 1422 my ($hash, $file); 1423 1424 $hash = $_[0]; 1425 $file = $_[1]; 1426 1427 open(VARIABLES, $file) 1428 || 1429 die("No $file file in SystemVariables.pm"); 1430 1431 #LOCK THE FILE 1432 flock(VARIABLES, LOCK_EX); 1433 1434 while(<VARIABLES>) { 1435 1436 #Allow for comments and spaces 1437 if(!(/^#/) && !(/^$/)) { 1438 ($key, $value) = (split(/|/)); 1439 1440 chomp $key; 1441 chomp $value; 1442 1443 ${%$hash}\{$key} = $value; 1444 } 1445 } 1446 1447 #FREE THE FILE 1448 close(VARIABLES); 1449 1450 return $hash; 1451 } 1452 1453 ##CONTRACT 1454 # loadConfigVariables : void -> REF(hash) 1455 ##PURPOSE 1456 # Takes no arguments; returns a hash reference pointing 1457 # to a hash containing the system-wide config variables. 1458 ##DEPENDANCIES 1459 # SystemVariables::getCourseConfigFile() 1460 sub loadConfigVariables { 1461 1462 my ( $config, 1463 ); 1464 1465 $config = getCourseConfigFile(); 1466 1467 open(VARIABLES, $config) 1468 || 1469 die("No $config file in SystemVariables.pm"); 1470 1471 while(<VARIABLES>) { 1472 1473 ($key, $value) = (split(/|/)); 1474 1475 chomp $key; 1476 chomp $value; 1477 1478 $ConfigVariables{$key} = $value; 1479 } 1480 1481 return %ConfigVariables; 1482 } 1483 1484 ##CONTRACT 1485 # processVariable : string -> string 1486 ##PURPOSE 1487 # Takes a variable as defined in a config file, and 1488 # expands any variable references embedded in it 1489 # inside of < .... >'s. This way, variables 1490 # can depend on each-other. 1491 ##DEPENDANCIES 1492 # Self-referential. 1493 sub processVariable { 1494 1495 my ( $variable, 1496 $temp, 1497 $orig 1498 ); 1499 1500 $variable = $_[0]; 1501 1502 if($variable =~ /.*(<.*>).*/) { 1503 $temp = $1; 1504 $orig = $1; 1505 1506 #DEBUGGING 1507 #errOut($temp); 1508 #errOut(); 1509 1510 $temp =~ s/<//g; 1511 $temp =~ s/>//g; 1512 $temp = processVariable($Variables{$temp}); 1513 $variable =~ s/$orig/$temp/; 1514 } 1515 1516 return $variable; 1517 } 1518 1519 ##CONTRACT 1520 # getRecordPath : void -> string 1521 ##PURPOSE 1522 # Returns a string representing a path to the 1523 # records directory in the system. 1524 ##DEPENDANCIES 1525 # SystemVariables::processVariable() 1526 sub getRecordPath { 1527 1528 #errOut("SV: ", $Variables{"RECORDPATH"\}, "n"); 1529 #foreach $key (keys %AssignmentHash) { 1530 #print "$key::", $AssignmentHash{$key}, "<P>"; 1531 #} 1532 1533 return processVariable($Variables{"RECORDPATH"}); 1534 } 1535 1536 ##CONTRACT 1537 # getCourseConfigFile : void -> string 1538 ##PURPOSE 1539 # Returns a string representing the path 1540 # to the course config file. 1541 ##DEPENDANCIES 1542 # SystemVariables::processVariable() 1543 sub getCourseConfigFile { 1544 return processVariable($Variables{"CONFIGFILE"}); 1545 } 1546 1547 ##CONTRACT 1548 # getCourseConfigPath : void -> string 1549 ##PURPOSE 1550 # Returns a string representing the path to the system 1551 # config directory. 1552 ##DEPENDANCIES 1553 # SystemVariables::processVariable() 1554 sub getCourseConfigPath { 1555 return processVariable($Variables{"CONFIGPATH"}); 1556 } 1557 1558 ##CONTRACT 1559 # getCourseCorrellationFile : void -> string 1560 ##PURPOSE 1561 # Returns the path to the system-wide correllation file 1562 # that associates usernames with other student data. 1563 ##DEPENDANCIES 1564 # SystemVariables::processVariable() 1565 sub getCourseCorrellationFile { 1566 return processVariable($Variables{"CONFIGPATH"}) . 1567 ".correllation"; 1568 } 1569 1570 ##CONTRACT 1571 # webErrOut : array -> void 1572 ##PURPOSE 1573 # Takes an array, and prints the contents to STDOUT. 1574 ##DEPENDANCIES 1575 # None. 1576 sub webErrOut { 1577 1578 if($DEBUG){ 1579 print STDOUT @_; 1580 print STDOUT "<P>n"; 1581 } 1582 1583 } 1584 1585 ##CONTRACT 1586 # errOut : array -> void 1587 ##PURPOSE 1588 # Writes the contents of the passed array to 1589 # STDERR. 1590 ##DEPENDANCIES 1591 # None. 1592 sub errOut { 1593 1594 if($DEBUG) { 1595 print STDERR @_; 1596 print "n"; 1597 } 1598 } 1599 1600 ##CONTRACT 1601 # DEBUG : array -> void 1602 ##PURPOSE 1603 # Writes the contents of the passed array to STDOUT. 1604 # This is a non-explicit print to STDOUT, and 1605 # Perl CGIs seem to occasionally treat this 1606 # differently than explicitly declaring STDOUT... 1607 # This is not understood. 1608 ##DEPENDANCIES 1609 # None. 1610 sub DEBUG { 1611 my($script, 1612 @args, 1613 $debuglevel, 1614 $user, 1615 $dbl); 1616 1617 ($script, @args) = @_; 1618 chomp $script; 1619 chomp @args; 1620 1621 #Turn debugging on or off for the entire system; 1622 $SYSDEBUG = 0; 1623 $ADMINDEBUG = 0; 1624 1625 1626 1627 $debuglevel = 0; 1628 $user = $ENV{REMOTE_USER}; 1629 1630 if($dbl = Record::getDebugLevel($user)) { 1631 $debuglevel = $dbl; 1632 } else { 1633 $debuglevel = $ADMINDEBUG; 1634 } 1635 1636 1637 #Level 0 is nothing. 1638 #Level 1 prints to the class log 1639 #Level 2 prints to the class log and server log 1640 #Level 3 prints to the class log, server log, and screen 1641 1642 if ($debuglevel == 1) { 1643 VincentLog::clickLog("DEBUG", "$script: @args"); 1644 } elsif ($debuglevel == 2) { 1645 VincentLog::clickLog("DEBUG", "$script: @args"); 1646 print STDERR "VINCENTDEBUG $script: @argsn"; 1647 } elsif ($debuglevel == 3) { 1648 VincentLog::clickLog("DEBUG", "$script: @args"); 1649 print STDERR "VINCENTDEBUG $script: @argsn"; 1650 print "$script: ", @_, "n<P>"; 1651 } else { 1652 #Nothing 1653 } 1654 1655 } 1656 1657 1658 1659 1660 |
|
Last update: 1/6/01; 9:32:38 AM |