diff --git a/.gitignore b/.gitignore index 831eaae24c..f4cef05b70 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,7 @@ .svn .DS_Store .* +*.save htdocs/tmp/* tmp/* logs/* diff --git a/conf/README b/conf/README new file mode 100644 index 0000000000..eb23902b1d --- /dev/null +++ b/conf/README @@ -0,0 +1,34 @@ +Use the prelocal.conf and postlocal.conf files to make modifications. + +The prelocal.conf file is read before the global.conf.dist file is processed. Non-local variables in this file +are then available for use in global.conf.dist. + +The postlocal.conf file is read after the global.conf.dist file is processed and will overright configurations in global.conf.dist + +This new configuration system should greatly simplify the process of +updating webwork2 since it is less likely +that one will need to modify the config files when upgrading. Default configurations or permissions for +new features will be defined in global.conf.dist and will allow automatic upgrades. + +Overrides for these new features can be added later to postlocal.conf + +FIRST TIME RECONFIGURATION + +COPY prelocal.conf.dist to prelocal.conf. +COPY postlocal.conf.dist to postlocal.conf. + +MODIFY prelocal.conf using the data from your global.conf file. +In particular you will need to fill in the server name, the +password for the database and any modifications you have made as to the +location of the temporary files directory. Notice that the location of the temporary files directory +is used to define several other related subdirectories, so this modification needs to be made +in prelocal.conf BEFORE the standard global.conf.dist file is read. + +RENAME global.conf to global.save in order to make sure that the global.conf.dist is read. +Otherwise the global.conf file will be read instead of global.conf.dist and the behavior will be +as with the old system. + +INSPECT and possibly modify postlocal.conf to add any further local modifications that you had +made to your global.conf file. + + diff --git a/conf/global.conf.dist b/conf/global.conf.dist index f9af763b4b..6f6d4dfdf3 100644 --- a/conf/global.conf.dist +++ b/conf/global.conf.dist @@ -24,26 +24,13 @@ # addition, the $courseName variable holds the name of the current course. ################################################################################ -# Seed variables -################################################################################ - -# Set these variables to correspond to your configuration and preferences. You -# will need to restart the webserver to reset the variables in this section. - -# URL of WeBWorK handler. If WeBWorK is to be on the web server root, use "". Note -# that using "" may not work so we suggest sticking with "/webwork2". -$webwork_url = "/webwork2"; - -$server_root_url = ""; # e.g. http://webwork.yourschool.edu -$server_userID = ""; # e.g. www-data -$server_groupID = ""; # e.g. wwdata - - -# In the apache configuration file (often called httpd.conf) you will find -# User wwadmin --- this is the $server_userID -- of course it may be wwhttpd or some other name -# Group wwdata --- this is the $server_groupID -- this will have different names also +include("conf/prelocal.conf"); +################################################################################ +# prelocal.conf should contain basic information about +# certain directories on your server +################################################################################ # Root directory of PG. $pg_dir = "/opt/webwork/pg"; @@ -56,47 +43,6 @@ $webwork_htdocs_dir = "$webwork_dir/htdocs"; $webwork_courses_url = "/webwork2_course_files"; $webwork_courses_dir = "/opt/webwork/courses"; #(a typical place to put the course directory -################################################################################ -# Paths to external programs -################################################################################ - -# system utilities -$externalPrograms{mv} = "/bin/mv"; -$externalPrograms{cp} = "/bin/cp"; -$externalPrograms{rm} = "/bin/rm"; -$externalPrograms{mkdir} = "/bin/mkdir"; -$externalPrograms{tar} = "/bin/tar"; -$externalPrograms{gzip} = "/bin/gzip"; - -# equation rendering/hardcopy utiltiies -$externalPrograms{latex} = "/usr/bin/latex"; -$externalPrograms{pdflatex} = "/usr/bin/pdflatex --shell-escape"; -$externalPrograms{dvipng} = "/usr/bin/dvipng"; -$externalPrograms{tth} = "/usr/bin/tth"; - -#################################################### -# NetPBM - basic image manipulation utilities -# Most sites only need to configure $netpbm_prefix. -#################################################### -my $netpbm_prefix = "/usr/bin"; -$externalPrograms{giftopnm} = "$netpbm_prefix/giftopnm"; -$externalPrograms{ppmtopgm} = "$netpbm_prefix/ppmtopgm"; -$externalPrograms{pnmtops} = "$netpbm_prefix/pnmtops"; -$externalPrograms{pnmtopng} = "$netpbm_prefix/pnmtopng"; -$externalPrograms{pngtopnm} = "$netpbm_prefix/pngtopnm"; - -# url checker -$externalPrograms{checkurl} = "/usr/bin/lwp-request -d -mHEAD "; # or "/usr/local/bin/w3c -head " - -# image conversions utiltiies -# the source file is given on stdin, and the output expected on stdout. -$externalPrograms{gif2eps} = "$externalPrograms{giftopnm} | $externalPrograms{ppmtopgm} | $externalPrograms{pnmtops} -noturn 2>/dev/null"; -$externalPrograms{png2eps} = "$externalPrograms{pngtopnm} | $externalPrograms{ppmtopgm} | $externalPrograms{pnmtops} -noturn 2>/dev/null"; -$externalPrograms{gif2png} = "$externalPrograms{giftopnm} | $externalPrograms{pnmtopng}"; - -# mysql clients -$externalPrograms{mysql} = "/usr/bin/mysql"; -$externalPrograms{mysqldump} = "/usr/bin/mysqldump"; ################################################################################ # Mail settings @@ -178,6 +124,11 @@ $mail{editor_window_columns} = 100; # Customizing the action of the "Email your instructor" button ################################################### +# This is best done by copying the lines below, entering them +# in the postlocal.conf file and making the desired modifications. +# Then you will not need to update these modifications +# when you download a new version of WeBWorK. + # Use this to customize the text of the feedback button. $feedback_button_name = "Email instructor"; @@ -263,8 +214,11 @@ $webworkDirs{htdocs} = "$webwork_htdocs_dir" || "$webworkDirs{root}/htdoc $webworkURLs{htdocs} = "$webwork_htdocs_url"; # Location of web-accessible temporary files, such as equation images. -$webworkDirs{htdocs_temp} = "$webworkDirs{htdocs}/tmp"; -$webworkURLs{htdocs_temp} = "$webworkURLs{htdocs}/tmp"; +# These two should be set in prelocal.conf -- not here since this can be overwritten by new versions. +$webworkDirs{htdocs_temp} = (defined $webworkDirs{htdocs_temp} ) ? $webworkDirs{htdocs_temp} :"$webworkDirs{htdocs}/tmp"; +$webworkURLs{htdocs_temp} = (defined $webworkURLs{htdocs_temp} ) ? $webworkURLs{htdocs_temp} :"$webworkURLs{htdocs}/tmp"; + +#$webworkURLs{htdocs_temp} = "$webworkURLs{htdocs}/tmp"; # Location of cached equation images. $webworkDirs{equationCache} = "$webworkDirs{htdocs_temp}/equations"; @@ -498,20 +452,18 @@ $default_status = "Enrolled"; # GRANT SELECT ON webwork.* TO webworkRead@localhost IDENTIFIED BY 'passwordRO'; # GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, INDEX, LOCK TABLES ON webwork.* TO webworkWrite@localhost IDENTIFIED BY 'passwordRW'; -$database_dsn = "dbi:mysql:webwork"; -$database_username = "webworkWrite"; -$database_password = ""; -$database_debug = 0; +################################################################################ +# set these variables in prelocal.conf +# +# $database_dsn = "dbi:mysql:webwork"; +# $database_username = "webworkWrite"; +# #$database_password = ""; #set this in prelocal.conf +################################################################################ -# Variables for sql_moodle database layout. -$moodle_dsn = "dbi:mysql:moodle"; -$moodle_username = $database_username; -$moodle_password = $database_password; -$moodle_table_prefix = "mdl_"; -$moodle17 = 0; +# $database_debug = 0; -# Several database are defined in the file conf/database.conf and stored in the -# hash %dbLayouts. +# Database schemas are defined in the file conf/database.conf and stored in the +# hash %dbLayouts. The standard schema is called "sql_single"; include "conf/database.conf"; # Select the default database layout. This can be overridden in the course.conf @@ -547,8 +499,6 @@ $problemLibrary_db = { # Logs ################################################################################ -# FIXME: take logs out of %webworkFiles/%courseFiles and give them their own -# top-level hash. # Logs data about how long it takes to process problems. (Do not confuse this # with the /other/ timing log which can be set by WeBWorK::Timing and is used @@ -576,7 +526,7 @@ $courseFiles{logs}{login_log} = "$courseDirs{logs}/login.log"; $courseFiles{logs}{activity_log} = ''; ################################################################################ -# Site defaults (FIXME: what other things could be "site defaults"?) +# Site defaults (Usually overridden in postlocal.conf) ################################################################################ # Set the default timezone of courses on this server. To get a list of valid @@ -616,7 +566,7 @@ $siteDefaults{default_templates_course} ="modelCourse"; # current database layout is found. # $authen{user_module} = { - sql_moodle => "WeBWorK::Authen::Moodle", + # sql_moodle => "WeBWorK::Authen::Moodle", # sql_ldap => "WeBWorK::Authen::LDAP", "*" => "WeBWorK::Authen", }; @@ -627,15 +577,12 @@ $authen{user_module} = { # $authen{proctor_module} = "WeBWorK::Authen::Proctor"; +################################################################################ # Options for particular authentication modules +################################################################################ -# $authen{moodle_options} = { -# dsn => $moodle_dsn, -# username => $moodle_username, -# password => $moodle_password, -# table_prefix => $moodle_table_prefix, -# moodle17 => $moodle17, -# }; +# If you are using ldap this next snippet should be copied and entered into postlocal.conf. +# Make modifications there so that it works with your local LDAP protocol $authen{ldap_options} = { # hosts to attempt to connect to, in order. For example: @@ -686,7 +633,7 @@ $authen{ldap_options} = { }; ################################################################################ -# Authorization system +# Authorization system (Make local overrides in postlocal.conf ) ################################################################################ # this section lets you define which groups of users can perform which actions. @@ -703,6 +650,7 @@ $authen{ldap_options} = { grade_proctor => 3, ta => 5, professor => 10, + admin => 20, ); # this hash maps operations to the roles that are allowed to perform those @@ -1082,3 +1030,29 @@ $webworkRoot = $webworkDirs{root}; $webworkURLRoot = $webworkURLs{root}; $pgRoot = $pg{directories}{root}; +################################################################################ +# Temporary hack for displaying the different versions of the editors +################################################################################ +# These behaviors can be overridden in postlocal.conf +# These configurations can be placed in CourseConfig to tune the behavior for individual courses +%showeditors = ( + classlisteditor1 => 1, + classlisteditor2 => 0, + + homeworkseteditor1 => 1, + homeworkseteditor2 => 0, + + librarybrowser1 => 1, + librarybrowser2 => 0, + librarybrowser3 => 1, + + pgproblemeditor1 => 1, + pgproblemeditor2 => 0, +); +################################################################################ +# Site wide overrides are entered into the file postlocal.conf +################################################################################ + +include("conf/postlocal.conf"); + +1; #final line of the file to reassure perl that it was read properly. diff --git a/conf/postlocal.conf.dist b/conf/postlocal.conf.dist new file mode 100755 index 0000000000..86819694ca --- /dev/null +++ b/conf/postlocal.conf.dist @@ -0,0 +1,282 @@ +#!perl +################################################################################ +# WeBWorK Online Homework Delivery System +# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ +# $CVSHeader: webwork2/conf/global.conf.dist,v 1.225 2010/05/18 18:03:31 apizer Exp $ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of either: (a) the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version, or (b) the "Artistic License" which comes with this package. +# +# This program 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 either the GNU General Public License or the +# Artistic License for more details. +################################################################################ + +# This file is used to set up the default WeBWorK course environment for all +# requests. Values may be overwritten by the course.conf for a specific course. +# All package variables set in this file are added to the course environment. +# If you wish to set a variable here but omit it from the course environment, +# use the "my" keyword. The $webwork_dir variable is set in the WeBWorK Apache +# configuration file (webwork.apache-config) and is available for use here. In +# addition, the $courseName variable holds the name of the current course. + +################################################################################ +# postlocal.conf -- this file +################################################################################ + +# prelocal.conf and postlocal.conf contain the local modifications commonly made +# when installing WeBWorK on a new site. The configurations in global.conf.dist +# and in database.conf can usually remain untouched. +# +# postlocal.conf is the appropriate place to override permission settings, +# paths to macros and other customizations that are specific to your +# WeBWorK site + + +################################################################################ +# Mail settings +################################################################################ + +################################################################################ +# These configurations must be defined in order for the mailing capabilities +# of webwork to work +################################################################################ + +# Mail sent by the PG system and the mail merge and feedback modules will be +# sent via this SMTP server. +$mail{smtpServer} ="mail.yourschool.edu"; + +# When connecting to the above server, WeBWorK will send this address in the +# MAIL FROM command. This has nothing to do with the "From" address on the mail +# message. It can really be anything, but some mail servers require it contain +# a valid mail domain, or at least be well-formed. +$mail{smtpSender} = 'webwork@yourserver.yourschool.edu'; + + +################################################################################ +# Additional mail settings in global.conf can be overridden here +################################################################################ +$mail{feedbackRecipients} = [ + #'prof1@yourserver.yourdomain.edu', + #'prof2@yourserver.yourdomain.edu', +]; + + + + + +################################################################################ +# Theme +################################################################################ + +$defaultTheme = "math3"; +$defaultThemeTemplate = "system"; + +################################################################################ +# Language +################################################################################ + +$language = "en"; # tr = turkish en=english + + +################################################################################ +# Default screen header files +################################################################################ + +# The setHeader preceeds each set in hardcopy output. It is a PG file. +# This is the default file which is used if a specific files is not selected + +$webworkFiles{hardcopySnippets}{setHeader} = "$webworkDirs{conf}/snippets/ASimpleCombinedHeaderFile.pg"; + +#$webworkFiles{hardcopySnippets}{setHeader} = "$courseDirs{templates}/ASimpleHardCopyHeaderFile.pg"; # An alternate default hardcopy only header file +#$webworkFiles{hardcopySnippets}{setHeader} = "$courseDirs{templates}/ASimpleCombinedHeaderFile.pg"; + +# The set header is displayed on the problem set page. It is a PG file. +# One of these default files which is used if a specific files is not selected + +$webworkFiles{screenSnippets}{setHeader} = "$webworkDirs{conf}/snippets/ASimpleCombinedHeaderFile.pg"; + +# $webworkFiles{screenSnippets}{setHeader} = "$courseDirs{templates}/ASimpleScreenHeaderFile.pg"; # An alternate default screen HTML only header file +# $webworkFiles{screenSnippets}{setHeader} = "$courseDirs{templates}/ASimpleCombinedHeaderFile.pg"; + + +################################################################################ +# National Problem Library +################################################################################ + + +# For configuration instructions, see: +# http://webwork.maa.org/wiki/National_Problem_Library +# The directory containing the natinal problem library files. Set to "" if no problem +# library is installed. +$problemLibrary{root} ="/opt/webwork/libraries/NationalProblemLibrary"; + +# Additional library buttons can be added to the Library Browser (SetMaker.pm) +# by adding the libraries you want to the following line. For each key=>value +# in the list, if a directory (or link to a directory) with name 'key' appears +# in the templates directory, then a button with name 'value' will be placed at +# the top of the problem browser. (No button will appear if there is no +# directory or link with the given name in the templates directory.) For +# example, +# +# $courseFiles{problibs} = {rochester => "Rochester", asu => "ASU"}; +# +# would add two buttons, one for the Rochester library and one for the ASU +# library, provided templates/rochester and templates/asu exists either as +# subdirectories or links to other directories. The "NPL Directory" button +# activated below gives access to all the directories in the National +# Problem Library. +# +$courseFiles{problibs} = { + Library => "NPL Directory", +# rochesterLibrary => "Rochester", +# unionLibrary =>"Union", +# asuLibrary => "Arizona State", +# dcdsLibrary => "Detroit CDS", +# dartmouthLibrary => "Dartmouth", +# indianaLibrary => "Indiana", +# osuLibrary => "Ohio State", +# capaLibrary => "CAPA", +}; + + +################################################################################ +# Site defaults +################################################################################ + +# Set the default timezone of courses on this server. To get a list of valid +# timezones, run: +# +# perl -MDateTime::TimeZone -e 'print join "\n", DateTime::TimeZone::all_names' +# +# To get a list of valid timezone "links" (deprecated names), run: +# +# perl -MDateTime::TimeZone -e 'print join "\n", DateTime::TimeZone::links' +# +# If left blank, the system timezone will be used. This is usually what you +# want. You might want to set this if your server is NOT in the same timezone as +# your school. If just a few courses are in a different timezone, set this in +# course.conf for the affected courses instead. +# +$siteDefaults{timezone} = "America/New_York"; + + +################################################################################ +# Permission levels (see global.conf for list of items to give permissions on ) +################################################################################ +# User roles in order of increasing permissions. Each level has all of the privileges of +# the lower levels. +# guest +# student +# login_proctor +# grade_proctor +# ta +# professor +# admin + +# To modify permission levels use this syntax: +# $permissionLevels{login} = "guest"; + + +################################################################################ +# PG subsystem options +################################################################################ + +# List of enabled display modes. Comment out any modes you don't wish to make +# available for use. +$pg{displayModes} = [ +# "plainText", # display raw TeX for math expressions +# "formattedText", # format math expressions using TtH + "images", # display math expressions as images generated by dvipng + "jsMath", # render TeX math expressions on the client side using jsMath + "MathJax", # render TeX math expressions on the client side using MathJax --- we strongly recommend people install and use MathJax +# "asciimath", # render TeX math expressions on the client side using ASCIIMathML + "LaTeXMathML", # render TeX math expressions on the client side using LaTeXMathML +]; + +################################################################################ +# The macro file search path. (Check with entries in global.conf before overriding) +################################################################################ +# Each directory in this list is seached +# (in this order) by loadMacros() when it looks for a .pl file. +# +# $pg{directories}{macrosPath} = [ +# ".", # search the problem file's directory +# $courseDirs{macros}, +# $pg{directories}{macros}, +# "$courseDirs{templates}/Library/macros/Union", +# "$courseDirs{templates}/Library/macros/Michigan", +# "$courseDirs{templates}/Library/macros/CollegeOfIdaho", +# "$courseDirs{templates}/Library/macros/FortLewis", +# "$courseDirs{templates}/Library/macros/TCNJ", +# "$courseDirs{templates}/Library/macros/NAU", +# "$courseDirs{templates}/Library/macros/Dartmouth", +# "$courseDirs{templates}/Library/macros/WHFreeman", +# ]; + +################################################################################ +# The applet search path. (Check with entries in global.conf before overriding) +################################################################################ + +# If a full URL is given, it is used unmodified. If an +# absolute path is given, the URL of the local server is prepended to it. +# +# For example, if an item is "/math/applets", +# and the local server is "https://math.yourschool.edu", +# then the URL "https://math.yourschool.edu/math/applets" will be used. +# + +# $pg{directories}{appletPath} = [ # paths to search for applets (requires full url) +# "$webworkURLs{htdocs}/applets", +# "$webworkURLs{htdocs}/applets/geogebra_stable", +# "$courseURLs{html}/applets", +# "$webworkURLs{htdocs}/applets/Xgraph", +# "$webworkURLs{htdocs}/applets/PointGraph", +# "$webworkURLs{htdocs}/applets/Xgraph", +# "$webworkURLs{htdocs}/applets/liveJar", +# "$webworkURLs{htdocs}/applets/Image_and_Cursor_All", +# +# ]; + +################################################################################ +# Problem creation defaults +################################################################################ + +# The default weight (also called value) of a problem to use when using the +# Library Browser, Problem Editor or Hmwk Sets Editor to add problems to a set +# or when this value is left blank in an imported set definition file. + +$problemDefaults{value} = 1; + +# The default max_attempts for a problem to use when using the +# Library Browser, Problem Editor or Hmwk Sets Editor to add problems to a set +# or when this value is left blank in an imported set definition file. Note that +# setting this to -1 gives students unlimited attempts. + +$problemDefaults{max_attempts} = -1; + +################################################################################ +# Temporary hack for displaying the different versions of the editors +################################################################################ +# These configurations can be placed in CourseConfig to tune the behavior for individual courses +# The items below can be used to override the settings in global.conf.dist +# One can also use $showeditors{classlisteditor1}=0; to override +# %showeditors = ( +# classlisteditor1 => 1, +# classlisteditor2 => 1, +# +# homeworkseteditor1 => 1, +# homeworkseteditor2 => 1, +# +# librarybrowser1 => 1, +# librarybrowser2 => 1, +# librarybrowser3 => 1, +# +# pgproblemeditor1 => 1, +# pgproblemeditor2 => 1, +# ); + +1; #final line of the file to reassure perl that it was read properly. diff --git a/conf/prelocal.conf.dist b/conf/prelocal.conf.dist new file mode 100755 index 0000000000..018503f97b --- /dev/null +++ b/conf/prelocal.conf.dist @@ -0,0 +1,154 @@ +#!perl +################################################################################ +# WeBWorK Online Homework Delivery System +# Copyright © 2000-2007 The WeBWorK Project, http://openwebwork.sf.net/ +# $CVSHeader: webwork2/conf/global.conf.dist,v 1.225 2010/05/18 18:03:31 apizer Exp $ +# +# This program is free software; you can redistribute it and/or modify it under +# the terms of either: (a) the GNU General Public License as published by the +# Free Software Foundation; either version 2, or (at your option) any later +# version, or (b) the "Artistic License" which comes with this package. +# +# This program 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 either the GNU General Public License or the +# Artistic License for more details. +################################################################################ + +# This file is used to set up the default WeBWorK course environment for all +# requests. Values may be overwritten by the course.conf for a specific course. +# All package variables set in this file are added to the course environment. +# If you wish to set a variable here but omit it from the course environment, +# use the "my" keyword. The $webwork_dir variable is set in the WeBWorK Apache +# configuration file (webwork.apache-config) and is available for use here. In +# addition, the $courseName variable holds the name of the current course. + +################################################################################ +# prelocal.conf -- this file +################################################################################ + +# prelocal.conf and postlocal.conf contain the local modifications commonly made +# when installing WeBWorK on a new site. The configurations in global.conf.dist +# and in database.conf can usually remain untouched. + +################################################################################ +# Seed variables +################################################################################ + +# Set these variables to correspond to your configuration and preferences. You +# will need to restart the webserver to reset the variables in this section. + +# URL of WeBWorK handler. If WeBWorK is to be on the web server root, use "". Note +# that using "" may not work so we suggest sticking with "/webwork2". +$webwork_url = "/webwork2"; +$server_root_url = ""; +$server_userID = "wwadmin"; +$server_groupID = "wwdata"; + +# In the apache configuration file (often called httpd.conf) you will find +# User wwadmin --- this is the $server_userID -- of course it may be wwhttpd or some other name +# Group wwdata --- this is the $server_groupID -- this will have different names also + + +################################################################################ +# Paths to external programs +################################################################################ + +# These applications are often found in /bin, but sometimes in /usr/bin +# or even in /opt/local/bin. +# You can use "which tar" for example to find out where the "tar" program is located + +#################################################### +# system utilities +#################################################### +$externalPrograms{mv} = "/bin/mv"; +$externalPrograms{cp} = "/bin/cp"; +$externalPrograms{rm} = "/bin/rm"; +$externalPrograms{mkdir} = "/bin/mkdir"; +$externalPrograms{tar} = "/bin/tar"; +$externalPrograms{gzip} = "/bin/gzip"; + +#################################################### +# equation rendering/hardcopy utiltiies +#################################################### +$externalPrograms{latex} ="/usr/bin/latex"; +$externalPrograms{pdflatex} ="/usr/bin/pdflatex --shell-escape"; +$externalPrograms{dvipng} ="/usr/bin//dvipng"; +$externalPrograms{tth} ="/usr/bin/tth"; + +#################################################### +# NetPBM - basic image manipulation utilities +# Most sites only need to configure $netpbm_prefix. +#################################################### +my $netpbm_prefix = "/usr/bin"; +$externalPrograms{giftopnm} = "$netpbm_prefix/giftopnm"; +$externalPrograms{ppmtopgm} = "$netpbm_prefix/ppmtopgm"; +$externalPrograms{pnmtops} = "$netpbm_prefix/pnmtops"; +$externalPrograms{pnmtopng} = "$netpbm_prefix/pnmtopng"; +$externalPrograms{pngtopnm} = "$netpbm_prefix/pngtopnm"; + +#################################################### +# url checker +#################################################### + +$externalPrograms{checkurl} = "/usr/bin/lwp-request -d -mHEAD "; # or "/usr/local/bin/w3c -head " + +#################################################### +# image conversions utiltiies +# the source file is given on stdin, and the output expected on stdout. +#################################################### + +$externalPrograms{gif2eps} = "$externalPrograms{giftopnm} | $externalPrograms{ppmtopgm} | $externalPrograms{pnmtops} -noturn 2>/dev/null"; +$externalPrograms{png2eps} = "$externalPrograms{pngtopnm} | $externalPrograms{ppmtopgm} | $externalPrograms{pnmtops} -noturn 2>/dev/null"; +$externalPrograms{gif2png} = "$externalPrograms{giftopnm} | $externalPrograms{pnmtopng}"; + +#################################################### +# mysql clients +#################################################### + +$externalPrograms{mysql} ="/usr/bin/mysql"; +$externalPrograms{mysqldump} ="/usr/bin/mysqldump"; + + +#################################################### +# End paths to external utilities. +#################################################### + +################################################################################ +# Database options +################################################################################ + + +# Standard permissions command used to initialize the webwork database +# GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, ALTER, DROP, INDEX, LOCK TABLES ON webwork.* TO webworkWrite@localhost IDENTIFIED BY 'passwordRW'; + +################################################################################ +# these variables are used by database.conf. we define them here so that editing +# database.conf isn't necessary. + +# You must initialize the database and set the password for webworkWrite +# The other parameters are set as defaults in global.conf but you can modify them +# here if for example you want to use a mysql database on a remote machine. +################################################################################ +$database_dsn ="dbi:mysql:webwork"; +$database_username ="webworkWrite"; +#$database_password ="passwordRW"; + +################################################################################ +# Directory for temporary files +################################################################################ +# Location of web-accessible temporary files, such as equation images. +Default: +#$webworkDirs{htdocs_temp} = "$webworkDirs{htdocs}/tmp"; +#$webworkURLs{htdocs_temp} = "$webworkURLs{htdocs}/tmp"; + +# Alternate locations -- this allows you to place temporary files +# in a location that is not backed up. +#For example. +#$webworkDirs{htdocs_temp} = "/opt/htdocs/wwtmp"; +#$webworkURLs{htdocs_temp} = "/wwtmp"; + +################################################################################ + +1; #final line of the file to reassure perl that it was read properly. + diff --git a/conf/snippets/ASimpleCombinedHeaderFile.pg b/conf/snippets/ASimpleCombinedHeaderFile.pg new file mode 100644 index 0000000000..14cc26995c --- /dev/null +++ b/conf/snippets/ASimpleCombinedHeaderFile.pg @@ -0,0 +1,88 @@ +# ASimpleCombinedHeaderFile.pg +# This header file can be used for both the screen and hardcopy output + + +DOCUMENT(); + +loadMacros( + "PG.pl", + "PGbasicmacros.pl", + "PGcourse.pl", +); + +TEXT($BEGIN_ONE_COLUMN); + +#################################################### +# +# The item below printed out only when a hardcopy is made. +# +#################################################### + + + +TEXT(MODES(TeX =>EV3(<<'EOT'),HTML=>"")); + +\noindent {\large \bf $studentName} +\hfill +{\large \bf {\{protect_underbar($courseName)\}}} +% Uncomment the line below if this course has sections. Note that this is a comment in TeX mode since this is only processed by LaTeX +% {\large \bf { Section: \{protect_underbar($sectionName)\} } } +\par +\noindent{\large \bf {Assignment \{protect_underbar($setNumber)\} due $formatedDueDate}} +\par\noindent \bigskip +% Uncomment and edit the line below if this course has a web page. Note that this is a comment in TeX mode. +%See the course web page for information http://yoururl/yourcourse + +EOT + +#################################################### +# +# End of hardcopy only output. +# +#################################################### + + +#################################################### +# +# The items below are printed out only when set is displayed on screen +# +#################################################### +TEXT(MODES(TeX =>"",HTML=>EV3(<<'EOT'))); + +$BBOLD WeBWorK Assignment \{ protect_underbar($setNumber) \} is due : $formattedDueDate. $EBOLD +$PAR +Here's the list of +\{ htmlLink(qq!http://webwork.maa.org/wiki/Available_Functions!,"functions and symbols") \} + which WeBWorK understands. +$BR +EOT + +#################################################### +# Uncomment and edit the lines below if this course has a web page. Note that this is comment in Perl mode. +# IMPORTANT: Make sure the EOT at the bottom is at the beginning of a line with no spaces preceeding it. +#TEXT(MODES(TeX =>"",HTML=>EV3(<<'EOT'))); +#See the course web page for information \{ htmlLink(qq!http://yoururl/yourcourse!,"your course name") \} +#EOT +#################################################### + +#################################################### +# +# End of screen only output. +# +#################################################### + +#################################################### +# +# Anything between the BEGIN_TEXT AND END_TEXT lines +# will be printed in both screen and hardcopy output +# +#################################################### + +BEGIN_TEXT + +END_TEXT + + +TEXT($END_ONE_COLUMN); + +ENDDOCUMENT(); # This should be the last executable line in the problem. diff --git a/htdocs/js/ajax_reload.js b/htdocs/js/ajax_reload.js new file mode 100644 index 0000000000..dba3924a23 --- /dev/null +++ b/htdocs/js/ajax_reload.js @@ -0,0 +1,40 @@ +/* This is the javascript that creates the AJAX object and attaches it to the reload button*/ +/* Reference: w3schools.com, http://www.w3schools.com/ajax/ajax_examples.asp*/ + +function ajax_Reload() { + var xmlhttp; + + if(window.XMLHttpRequest){ + xmlhttp = new XMLHttpRequest(); + } + else{ + xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); + } + + xmlhttp.onreadystatechange=function() { + if (xmlhttp.readyState==4 && xmlhttp.status==200){ + document.getElementById("problem_viewer_content").innerHTML=xmlhttp.responseText; + } + }; + + var tempEditFileDirectory = document.getElementById("temp_url_id").getAttribute("value"); + alert(location.protocol+"//"+location.host+tempEditFileDirectory+"/temp_body.txt"); + xmlhttp.open("GET", location.protocol+"//"+location.host+tempEditFileDirectory+"/temp_body.txt", true); + xmlhttp.send(); +} + +/*This method of adding to the onload event listener is taken from tabber.js, which in turn takes from http://simon.incutio.com/archive/2004/05/26/addLoadEvent*/ + +// var oldonload; + +// oldonload = window.onload; + +// if(typeof window.onload != "function"){ + // window.onload = function() { document.getElementById("reload_button").onclick = ajax_Reload; }; +// } +// else{ + // window.onload = function() { + // oldonload(); + // document.getElementById("reload_button").onclick = ajax_Reload; + // }; +// } \ No newline at end of file diff --git a/htdocs/js/classlist_handlers.js b/htdocs/js/classlist_handlers.js new file mode 100644 index 0000000000..0f901c2662 --- /dev/null +++ b/htdocs/js/classlist_handlers.js @@ -0,0 +1,32 @@ +/*This is the Javascript which applies some handlers to various input elements*/ + +function classlist_add_filter_elements() { + var filter_select = document.getElementById("filter_select"); + var filter_elements = document.getElementById("filter_elements"); + + if(filter_select.selectedIndex == 3){ + filter_elements.style.display = "block"; + } + else{ + filter_elements.style.display = "none"; + } +} + +function classlist_add_export_elements() { + var export_select_target = document.getElementById("export_select_target"); + var export_elements = document.getElementById("export_elements"); + + if(export_select_target.selectedIndex == 0){ + export_elements.style.display = "block"; + } + else{ + export_elements.style.display = "none"; + } +} + +addOnLoadEvent(function() { + document.getElementById("filter_select").onchange = classlist_add_filter_elements; + classlist_add_filter_elements(); + document.getElementById("export_select_target").onchange = classlist_add_export_elements; + classlist_add_export_elements(); + }); \ No newline at end of file diff --git a/htdocs/js/form_checker_hmwksets.js b/htdocs/js/form_checker_hmwksets.js new file mode 100644 index 0000000000..6f0bcab1d9 --- /dev/null +++ b/htdocs/js/form_checker_hmwksets.js @@ -0,0 +1,18 @@ +/*This is the javascript which checks the forms for errors on the Hmwksets editor page.*/ + +function check_form_hmwk_sets() { + var filter_text = document.getElementById("filter_text"); + var filter_select = document.getElementById("filter_select"); + var filter_err_msg = document.getElementById("filter_err_msg"); + var filter_radio = document.getElementById("filter_id"); + + if(filter_radio.checked && filter_select.selectedIndex == 3 && filter_text.value == ""){ + filter_err_msg.style.display = "inline"; + return false; + } +} + + +addOnLoadEvent(function (){ + document.getElementById("take_action").onclick = check_form_hmwk_sets; +}); \ No newline at end of file diff --git a/htdocs/js/getInputTable.js b/htdocs/js/getInputTable.js new file mode 100644 index 0000000000..51efca3c48 --- /dev/null +++ b/htdocs/js/getInputTable.js @@ -0,0 +1,23 @@ +/*This gets the input table for the XMLRPC call*/ + +function getInputTable(){ + var problem_viewer = document.getElementById("problem_viewer_form"); + var inputElems = problem_viewer.getElementsByTagName("input"); + + var inputTable = new Array(); + + var type,name,value; + for(i in inputElems){ + type = inputElems[i].getAttribute("type"); + name = inputElems[i].getAttribute("name"); + value = inputElems[i].getAttribute("value"); + if(type == "submit" || type == "button" || type == "reset"){ + continue; + } + else{ + inputTable[name] = value; + } + } + + return inputTable; +} \ No newline at end of file diff --git a/htdocs/js/hmwksets_handlers.js b/htdocs/js/hmwksets_handlers.js new file mode 100644 index 0000000000..2b9b6b0a6d --- /dev/null +++ b/htdocs/js/hmwksets_handlers.js @@ -0,0 +1,18 @@ +/*This contains the Javascripts for the handlers on the hmwk sets page.*/ + +function hmwksets_add_filter_elements() { + var filter_select = document.getElementById("filter_select"); + var filter_elements = document.getElementById("filter_elements"); + + if(filter_select.selectedIndex == 3){ + filter_elements.style.display = "block"; + } + else{ + filter_elements.style.display = "none"; + } +} + +addOnLoadEvent(function() { + document.getElementById("filter_select").onchange = hmwksets_add_filter_elements; + hmwksets_add_filter_elements(); +}); \ No newline at end of file diff --git a/htdocs/js/java_init.js b/htdocs/js/java_init.js new file mode 100644 index 0000000000..ea4ed5d320 --- /dev/null +++ b/htdocs/js/java_init.js @@ -0,0 +1,9 @@ +/*This is the file where the proper functions are initialized for the problem applets which use them.*/ + +function initWW(){ + if (typeof(initializeWWquestion) == 'function') { + initializeWWquestion(); + } +} + +addOnLoadEvent(initWW); \ No newline at end of file diff --git a/htdocs/js/mimic.js b/htdocs/js/mimic.js new file mode 100644 index 0000000000..61872487a4 --- /dev/null +++ b/htdocs/js/mimic.js @@ -0,0 +1,490 @@ +/* +* Mimic (XML-RPC Client for JavaScript) v2.0.1 +* Copyright (C) 2005-2009 Carlos Eduardo Goncalves (cadu.goncalves@gmail.com) +* +* Mimic is dual licensed under the MIT (http://opensource.org/licenses/mit-license.php) +* and GPLv3 (http://opensource.org/licenses/gpl-3.0.html) licenses. +*/ + + +/** + * XmlRpc + */ + function XmlRpc(){ + + }; + +/**

XML-RPC document prolog.

*/ +XmlRpc.PROLOG = "\n"; + +/**

XML-RPC methodCall node template.

*/ +XmlRpc.REQUEST = "\n${METHOD}\n\n${DATA}\n"; + +/**

XML-RPC param node template.

*/ +XmlRpc.PARAM = "\n\n${DATA}\n\n"; + +/**

XML-RPC array node template.

*/ +XmlRpc.ARRAY = "\n\n${DATA}\n\n"; + +/**

XML-RPC struct node template.

*/ +XmlRpc.STRUCT = "\n${DATA}\n"; + +/**

XML-RPC member node template.

*/ +XmlRpc.MEMBER = "\n${DATA}\n"; + +/**

XML-RPC name node template.

*/ +XmlRpc.NAME = "${DATA}\n"; + +/**

XML-RPC value node template.

*/ +XmlRpc.VALUE = "\n${DATA}\n"; + +/**

XML-RPC scalar node template (int, i4, double, string, boolean, base64, dateTime.iso8601).

*/ +XmlRpc.SCALAR = "<${TYPE}>${DATA}\n"; + +/** +*

Get the tag name used to represent a JavaScript +* object in the XMLRPC protocol.

+* @param data +* A JavaScript object. +* @return +* String with XMLRPC object type. +*/ +XmlRpc.getDataTag = function(data) { + try { + var tag = typeof data; + switch(tag.toLowerCase()) { + case "number": + tag = (Math.round(data) == data) ? "int" : "double"; + break; + case "object": + if(data.constructor == Base64) + tag = "base64"; + else + if(data.constructor == String) + tag = "string"; + else + if(data.constructor == Boolean) + tag = "boolean"; + else + if(data.constructor == Array) + tag = "array"; + else + if(data.constructor == Date) + tag = "dateTime.iso8601"; + else + if(data.constructor == Number) + tag = (Math.round(data) == data) ? "int" : "double"; + else + tag = "struct"; + break; + } + return tag; + } + catch(e) { + Engine.reportException(null, e); + } +}; + +/** +*

Get JavaScript object type represented by +* XMLRPC protocol tag.

+* @param tag +* A XMLRPC tag name. +* @return +* A JavaScript object. +*/ +XmlRpc.getTagData = function(tag) { + var data = null; + switch(tag) { + case "struct": + data = new Object(); + break; + case "array": + data = new Array(); + break; + case "datetime.iso8601": + data = new Date(); + break; + case "boolean": + data = new Boolean(); + break; + case "int": + case "i4": + case "double": + data = new Number(); + break; + case "string": + data = new String(); + break; + case "base64": + data = new Base64(); + break; + } + return data; +}; + +/** + * XmlRpcRequest + * @param url + * Server url. + * @param method + * Server side method do call. + */ +function XmlRpcRequest(url, method) { + this.serviceUrl = url; + this.methodName = method; + this.params = []; +}; + +/** + *

Add a new request parameter.

+ * @param data + * New parameter value. + */ +XmlRpcRequest.prototype.addParam = function(data) { + var type = typeof data; + switch(type.toLowerCase()) { + case "function": + return; + case "object": + if(!data.constructor.name) return; + } + this.params.push(data); +}; + +/** + *

Clear all request parameters.

+ * @param data + * New parameter value. + */ +XmlRpcRequest.prototype.clearParams = function() { + this.params.splice(0, this.params.length); +}; + +/** + *

Execute a synchronous XML-RPC request.

+ * @return + * XmlRpcResponse object. + */ +XmlRpcRequest.prototype.send = function() { + var xml_params = ""; + for(var i = 0; i < this.params.length; i++) + xml_params += XmlRpc.PARAM.replace("${DATA}", this.marshal(this.params[i])); + var xml_call = XmlRpc.REQUEST.replace("${METHOD}", this.methodName); + xml_call = XmlRpc.PROLOG + xml_call.replace("${DATA}", xml_params); + var xhr = Builder.buildXHR(); + xhr.open("POST", this.serviceUrl, false); + xhr.send(Builder.buildDOM(xml_call)); + return new XmlRpcResponse(xhr.responseXML); +}; + +/** + *

Marshal request parameters.

+ * @param data + * A request parameter. + * @return + * String with XML-RPC element notation. + */ +XmlRpcRequest.prototype.marshal = function(data) { + var type = XmlRpc.getDataTag(data); + var scalar_type = XmlRpc.SCALAR.replace(/\$\{TYPE\}/g, type); + var xml = ""; + switch(type) { + case "struct": + var member = ""; + for(var i in data) { + var value = ""; + value += XmlRpc.NAME.replace("${DATA}", i); + value += XmlRpc.VALUE.replace("${DATA}", this.marshal(data[i])); + member += XmlRpc.MEMBER.replace("${DATA}", value); + } + xml = XmlRpc.STRUCT.replace("${DATA}", member); + break; + case "array": + var value = ""; + for(var i = 0; i < data.length; i++) { + value += XmlRpc.VALUE.replace("${DATA}", this.marshal(data[i])); + } + xml = XmlRpc.ARRAY.replace("${DATA}", value); + break; + case "dateTime.iso8601": + xml = scalar_type.replace("${DATA}", data.toIso8601()); + break; + case "boolean": + xml = scalar_type.replace("${DATA}", (data == true) ? 1 : 0); + break; + case "base64": + xml = scalar_type.replace("${DATA}", data.encode()); + break; + default : + xml = scalar_type.replace("${DATA}", data); + break; + } + return xml; +}; + +/** + * XmlRpcResponse + * @param xml + * Response XML document. + */ +function XmlRpcResponse(xml) { + this.xmlData = xml; +}; + +/** + *

Indicate if response is a fault.

+ * @return + * Boolean flag indicating fault status. + */ +XmlRpcResponse.prototype.isFault = function() { + return this.faultValue; +}; + +/** + *

Parse XML response to JavaScript.

+ * @return + * JavaScript object parsed from XML-RPC document. + */ +XmlRpcResponse.prototype.parseXML = function() { + this.faultValue = undefined; + this.currentIsName = false; + this.propertyName = ""; + this.params = []; + for(var i = 0; i < this.xmlData.childNodes.length; i++) + this.unmarshal(this.xmlData.childNodes[i], 0); + return this.params[0]; +}; + +/** + *

Unmarshal response parameters.

+ * @param node + * Current document node under processing. + * @param parent + * Current node' parent node. + */ +XmlRpcResponse.prototype.unmarshal = function(node, parent) { + if(node.nodeType == 1) { + var obj = null; + var tag = node.tagName.toLowerCase(); + switch(tag) { + case "fault": + this.faultValue = true; + break; + case "name": + this.currentIsName = true; + break; + default: + obj = XmlRpc.getTagData(tag); + break; + } + if(obj != null) { + this.params.push(obj); + if(tag == "struct" || tag == "array") { + if(this.params.length > 1) { + switch(XmlRpc.getDataTag(this.params[parent])) { + case "struct": + this.params[parent][this.propertyName] = this.params[this.params.length - 1]; + break; + case "array": + this.params[parent].push(this.params[this.params.length - 1]); + break; + } + } + var parent = this.params.length - 1; + } + } + for(var i = 0; i < node.childNodes.length; i++) { + this.unmarshal(node.childNodes[i], parent); + } + } + if( (node.nodeType == 3) && (/[^\t\n\r ]/.test(node.nodeValue)) ) { + if(this.currentIsName == true) { + this.propertyName = node.nodeValue; + this.currentIsName = false; + } + else { + switch(XmlRpc.getDataTag(this.params[this.params.length - 1])) { + case "dateTime.iso8601": + this.params[this.params.length - 1] = Date.fromIso8601(node.nodeValue); + break; + case "boolean": + this.params[this.params.length - 1] = (node.nodeValue == "1") ? true : false; + break; + case "int": + case "double": + this.params[this.params.length - 1] = new Number(node.nodeValue); + break; + case "string": + this.params[this.params.length - 1] = new String(node.nodeValue); + break; + case "base64": + this.params[this.params.length - 1] = new Base64(node.nodeValue); + break; + } + if(this.params.length > 1) { + switch(XmlRpc.getDataTag(this.params[parent])) { + case "struct": + this.params[parent][this.propertyName] = this.params[this.params.length - 1]; + break; + case "array": + this.params[parent].push(this.params[this.params.length - 1]); + break; + } + } + } + } +}; + +/** + * Builder + */ +function Builder(){ + +}; + +/** + *

Build a valid XMLHttpRequest object

+ * @return + * XMLHttpRequest object. + */ +Builder.buildXHR = function() { + return (typeof XMLHttpRequest != "undefined") ? new XMLHttpRequest() : new ActiveXObject("Microsoft.XMLHTTP"); +}; + +/** + *

Build a valid XML document from string markup.

+ * @param xml + * Document markup. + * @return + * XMLDocument object. + */ +Builder.buildDOM = function(xml) { + if(typeof DOMParser != "undefined") { + var w3c_parser = new DOMParser(); + return w3c_parser.parseFromString(xml, "text/xml"); + } + else { + var names = ["Microsoft.XMLDOM", "MSXML2.DOMDocument", "MSXML.DOMDocument"]; + for(var i = 0; i < names.length; i++) { + try{ + var atx_parser = new ActiveXObject(names[i]); + atx_parser.loadXML(xml); + return atx_parser; + } + catch (e) {/* ignore */ } + } + } + return null; +}; + +/** + * Date + */ + + /** +*

Convert a GMT date to ISO8601.

+* @return +* String with an ISO8601 date. +*/ +Date.prototype.toIso8601 = function() { + year = this.getYear(); + if (year < 1900) year += 1900; + month = this.getMonth() + 1; + if (month < 10) month = "0" + month; + day = this.getDate(); + if (day < 10) day = "0" + day; + time = this.toTimeString().substr(0,8); + return year + month + day + "T" + time; +}; + +/** +*

Convert ISO8601 date to GMT.

+* @param value +* ISO8601 date. +* @return +* GMT date. +*/ +Date.fromIso8601 = function(value) { + year = value.substr(0,4); + month = value.substr(4,2); + day = value.substr(6,2); + hour = value.substr(9,2); + minute = value.substr(12,2); + sec = value.substr(15,2); + return new Date(year, month - 1, day, hour, minute, sec, 0); +}; + +/** + * Base64 + */ +function Base64(value) { + Base64.prototype.bytes = value; +}; + +/**

Base64 characters map.

*/ +Base64.CHAR_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; + +/** +*

Encode the object bytes using base64 algorithm.

+* @return +* Encoded string. +*/ +Base64.prototype.encode = function() { + if(typeof btoa == "function") + this.bytes = btoa(this.bytes); + else { + var _byte = new Array(), _char = new Array(), _result = new Array(); + var j = 0; + for (var i = 0; i < this.bytes.length; i += 3) { + _byte[0] = this.bytes.charCodeAt(i); + _byte[1] = this.bytes.charCodeAt(i + 1); + _byte[2] = this.bytes.charCodeAt(i + 2); + _char[0] = _byte[0] >> 2; + _char[1] = ((_byte[0] & 3) << 4) | (_byte[1] >> 4); + _char[2] = ((_byte[1] & 15) << 2) | (_byte[2] >> 6); + _char[3] = _byte[2] & 63; + if(isNaN(_byte[1])) + _char[2] = _char[3] = 64; + else + if(isNaN(_byte[2])) + _char[3] = 64; + _result[j++] = Base64.CHAR_MAP.charAt(_char[0]) + Base64.CHAR_MAP.charAt(_char[1]) + + Base64.CHAR_MAP.charAt(_char[2]) + Base64.CHAR_MAP.charAt(_char[3]); + } + this.bytes = _result.join(""); + } + return this.bytes; +}; + +/** +*

Decode the object bytes using base64 algorithm.

+* @return +* Decoded string. +*/ +Base64.prototype.decode = function() { + if(typeof atob == "function") + this.bytes = atob(this.bytes); + else { + var _byte = new Array(), _char = new Array(), _result = new Array(); + var j = 0; + while ((this.bytes.length % 4) != 0) + this.bytes += "="; + for (var i = 0; i < this.bytes.length; i += 4) { + _char[0] = Base64.CHAR_MAP.indexOf(this.bytes.charAt(i)); + _char[1] = Base64.CHAR_MAP.indexOf(this.bytes.charAt(i + 1)); + _char[2] = Base64.CHAR_MAP.indexOf(this.bytes.charAt(i + 2)); + _char[3] = Base64.CHAR_MAP.indexOf(this.bytes.charAt(i + 3)); + _byte[0] = (_char[0] << 2) | (_char[1] >> 4); + _byte[1] = ((_char[1] & 15) << 4) | (_char[2] >> 2); + _byte[2] = ((_char[2] & 3) << 6) | _char[3]; + _result[j++] = String.fromCharCode(_byte[0]); + if(_char[2] != 64) + _result[j++] = String.fromCharCode(_byte[1]); + if(_char[3] != 64) + _result[j++] = String.fromCharCode(_byte[2]); + } + this.bytes = _result.join(""); + } + return this.bytes; +}; \ No newline at end of file diff --git a/htdocs/js/removeDuplicates.js b/htdocs/js/removeDuplicates.js new file mode 100644 index 0000000000..5989c620e7 --- /dev/null +++ b/htdocs/js/removeDuplicates.js @@ -0,0 +1,20 @@ +/*This defines a function which removes duplicate javascript files from the page*/ + +function removeDuplicates(){ + var scripts = document.getElementsByTagName("script"); + + var src; + var i,j,x + for(i=0; i{%args}, systemlink_args=>\%systemlink_args); print CGI::start_ul(); - print CGI::li(&$makelink("${pfx}UserList", urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)); - print CGI::li(&$makelink("${pfx}UserList2", urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)); + print CGI::li(&$makelink("${pfx}UserList", urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)) + if $ce->{showeditors}->{classlisteditor1}; + print CGI::li(&$makelink("${pfx}UserList2", urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)) + if $ce->{showeditors}->{classlisteditor2};; print CGI::start_li(); # Homework Set Editor - print &$makelink("${pfx}ProblemSetList", urlpath_args=>{%args}, systemlink_args=>\%systemlink_args); + print &$makelink("${pfx}ProblemSetList", urlpath_args=>{%args}, systemlink_args=>\%systemlink_args) + if $ce->{showeditors}->{homeworkseteditor1}; print "
"; - print &$makelink("${pfx}ProblemSetList2", urlpath_args=>{%args}, systemlink_args=>\%systemlink_args); + print &$makelink("${pfx}ProblemSetList2", urlpath_args=>{%args}, systemlink_args=>\%systemlink_args) + if $ce->{showeditors}->{homeworkseteditor2};; ## only show editor link for non-versioned sets if (defined $setID && $setID !~ /,v\d+$/ ) { @@ -722,12 +726,14 @@ sub links { if (defined $problemID) { print CGI::start_ul(); - print CGI::li(&$makelink("${pfx}PGProblemEditor", text=>"$problemID", urlpath_args=>{%args,setID=>$setID,problemID=>$problemID}, systemlink_args=>\%systemlink_args, target=>"WW_Editor")); + print CGI::li(&$makelink("${pfx}PGProblemEditor", text=>"$problemID", urlpath_args=>{%args,setID=>$setID,problemID=>$problemID}, systemlink_args=>\%systemlink_args, target=>"WW_Editor")) + if $ce->{showeditors}->{pgproblemeditor1}; print CGI::end_ul(); } if (defined $problemID) { print CGI::start_ul(); - print CGI::li(&$makelink("${pfx}PGProblemEditor2", text=>"--$problemID", urlpath_args=>{%args,setID=>$setID,problemID=>$problemID}, systemlink_args=>\%systemlink_args, target=>"WW_Editor2")); + print CGI::li(&$makelink("${pfx}PGProblemEditor2", text=>"--$problemID", urlpath_args=>{%args,setID=>$setID,problemID=>$problemID}, systemlink_args=>\%systemlink_args, target=>"WW_Editor2")) + if $ce->{showeditors}->{pgproblemeditor2};; print CGI::end_ul(); } @@ -736,9 +742,12 @@ sub links { } print CGI::end_li(); # end Homework Set Editor - print CGI::li(&$makelink("${pfx}SetMaker", text=>$r->maketext("Library Browser"), urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)); - print CGI::li(&$makelink("${pfx}SetMaker2", text=>$r->maketext("Library Browser 2"), urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)); - print CGI::li(&$makelink("${pfx}SetMaker3", text=>$r->maketext("Library Browser 3"), urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)); + print CGI::li(&$makelink("${pfx}SetMaker", text=>$r->maketext("Library Browser"), urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)) + if $ce->{showeditors}->{librarybrowser1}; + print CGI::li(&$makelink("${pfx}SetMaker2", text=>$r->maketext("Library Browser 2"), urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)) + if $ce->{showeditors}->{librarybrowser2}; + print CGI::li(&$makelink("${pfx}SetMaker3", text=>$r->maketext("Library Browser 3"), urlpath_args=>{%args}, systemlink_args=>\%systemlink_args)) + if $ce->{showeditors}->{librarybrowser3}; print CGI::start_li(); # Stats print &$makelink("${pfx}Stats", urlpath_args=>{%args}, systemlink_args=>\%systemlink_args); if ($userID ne $eUserID or defined $setID) { @@ -1058,7 +1067,7 @@ The implementation in this package checks for a note in the request named sub warnings { my ($self) = @_; my $r = $self->r; - + print CGI::p("Entering ContentGenerator::warnings"); print "\n\n"; my $warnings = MP2 ? $r->notes->get("warnings") : $r->notes("warnings"); print $self->warningOutput($warnings) if $warnings; @@ -1940,7 +1949,7 @@ problem rendering. sub errorOutput($$$) { my ($self, $error, $details) = @_; my $r = $self->{r}; - + print "Entering ContentGenerator::errorOutput subroutine
"; my $time = time2str("%a %b %d %H:%M:%S %Y", time); my $method = $r->method; my $uri = $r->uri; @@ -1998,7 +2007,7 @@ and content generation. sub warningOutput($$) { my ($self, $warnings) = @_; my $r = $self->{r}; - + print "Entering ContentGenerator::warningOutput subroutine
"; my @warnings = split m/\n+/, $warnings; foreach my $warning (@warnings) { #$warning = escapeHTML($warning); # this would prevent using tables in output from answer evaluators diff --git a/lib/WeBWorK/ContentGenerator/Problem.pm b/lib/WeBWorK/ContentGenerator/Problem.pm index a82756f04e..ec8046e579 100644 --- a/lib/WeBWorK/ContentGenerator/Problem.pm +++ b/lib/WeBWorK/ContentGenerator/Problem.pm @@ -726,12 +726,14 @@ sub pre_header_initialize { # because the PG file is never run # if (defined ($pg->{pgcore}) ) { - my @debug_msgs = @{ $pg->{pgcore}->get_debug_messages}; - $self->addmessage(join(CGI::br(),@debug_msgs) ) if @debug_msgs; + my $debug_msg = CGI::br().join( CGI::br(), @{ $pg->{pgcore}->get_debug_messages}); + $self->addmessage($debug_msg ) if $debug_msg; $self->{pgdebug} = $pg->{pgcore}->get_debug_messages; $self->{pgwarning} = $pg->{pgcore}->get_warning_messages; $self->{pginternalerrors} = $pg->{pgcore}->get_internal_debug_messages ; - $self->{pgerrors} = @{$self->{pgdebug}} || @{$self->{pgwarning}} || @{$self->{pginternalerrors}}; + $self->{pgerrors} = @{$self->{pgdebug}} || @{$self->{pgwarning}} || @{$self->{pginternalerrors}}||0; + } else { + $self->{pgerrors}=undef; # unable to obtain errors } debug("end pg processing"); @@ -752,23 +754,30 @@ sub pre_header_initialize { } sub warnings { my $self = shift; - $self->SUPER::warnings(); - my $r = $self->r; - my $pg = $self->{pg}; - - my @pgdebug = @{ $self->{pgdebug} }; - my @pgwarning = @{ $self->{pgwarning} }; - my @pginternalerrors = @{ $self->{pginternalerrors} }; -# my $pgerrordiv = $pgdebug||$pgwarning||$pginternalerrors; # is 1 if any of these are non-empty + # print "entering warnings() subroutine internal messages = ", $self->{pgerrors},CGI::br(); + my $r = $self->r; +# my $pg = $self->{pg}; +# warn "type of pg is ",ref($pg); +# my $pgerrordiv = $pgdebug||$pgwarning||$pginternalerrors; # is 1 if any of these are non-empty # print warning messages - if ( $self->{pgerrors} ) { + if (not defined $self->{pgerrors} ) { + print CGI::start_div(); + print CGI::h3({style=>"color:red;"}, $r->maketext("PG question failed to render")); + print CGI::p($r->maketext("Unable to obtain error messages from within the PG question." )); + print CGI::end_div(); + } elsif ( $self->{pgerrors} > 0 ) { + my @pgdebug = @{ $self->{pgdebug} }; + my @pgwarning = @{ $self->{pgwarning} }; + my @pginternalerrors = @{ $self->{pginternalerrors} }; print CGI::start_div(); - print CGI::h3({style=>"color:red;"}, $r->maketext("Additional Error Messages")); - print CGI::p(CGI::h3("PG debug messages"), CGI::br(), @pgdebug ) if @pgdebug ; - print CGI::p(CGI::h3("PG warning messages"), CGI::br(), @pgwarning ) if @pgwarning ; - print CGI::p(CGI::h3("PG internal errors"), CGI::br(), @pginternalerrors ) if @pginternalerrors; + print CGI::h3({style=>"color:red;"}, $r->maketext("PG question processing error messages")); + print CGI::p(CGI::h3($r->maketext("PG debug messages" ) ), CGI::br(), join(CGI::br(), @pgdebug ) ) if @pgdebug ; + print CGI::p(CGI::h3($r->maketext("PG warning messages" ) ), CGI::br(), join(CGI::br(), @pgwarning) ) if @pgwarning ; + print CGI::p(CGI::h3($r->maketext("PG internal errors" ) ), CGI::br(), join(CGI::br(), @pginternalerrors )) if @pginternalerrors; print CGI::end_div(); - } + } + # print "proceeding to SUPER::warnings"; + $self->SUPER::warnings(); ""; } @@ -924,7 +933,7 @@ sub body { my $set = $self->{set}; my $problem = $self->{problem}; my $pg = $self->{pg}; - + print CGI::p("Entering Problem::body subroutine. This indicates an older style system.template file -- consider upgrading. "); my $valid = WeBWorK::ContentGenerator::ProblemUtil::ProblemUtil::check_invalid($self); unless($valid eq "valid"){ return $valid; @@ -1048,10 +1057,13 @@ sub output_editorLink{ if ($pg->{flags}->{error_flag}) { if ($authz->hasPermissions($user, "view_problem_debugging_info")) { + print "Call errorOutput
"; print $self->errorOutput($pg->{errors}, $pg->{body_text}); + print $editorLink; } else { print $self->errorOutput($pg->{errors}, $r->maketext("You do not have permission to view the details of this error.")); } + print ""; } else{ diff --git a/lib/WeBWorK/CourseEnvironment.pm b/lib/WeBWorK/CourseEnvironment.pm index c87c7a7612..eb4865a376 100644 --- a/lib/WeBWorK/CourseEnvironment.pm +++ b/lib/WeBWorK/CourseEnvironment.pm @@ -149,7 +149,12 @@ sub new { $safe->mask($maskBackup); # determine location of globalEnvironmentFile - my $globalEnvironmentFile = "$seedVars{webwork_dir}/conf/global.conf"; + my $globalEnvironmentFile; + if (-r "$seedVars{webwork_dir}/conf/global.conf") { + $globalEnvironmentFile = "$seedVars{webwork_dir}/conf/global.conf"; + } elsif (-r "$seedVars{webwork_dir}/conf/global.conf.dist") { # default version + $globalEnvironmentFile = "$seedVars{webwork_dir}/conf/global.conf.dist"; + } # read and evaluate the global environment file my $globalFileContents = readFile($globalEnvironmentFile); @@ -157,7 +162,7 @@ sub new { # if that evaluation failed, we can't really go on... # we need a global environment! - $@ and die "Could not evaluate global environment file $globalEnvironmentFile: $@"; + $@ and croak "Could not evaluate global environment file $globalEnvironmentFile: $@"; # determine location of courseEnvironmentFile and simple configuration file # pull it out of $safe's symbol table ad hoc