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 = "XML-RPC param node template.
*/ +XmlRpc.PARAM = "\nXML-RPC array node template.
*/ +XmlRpc.ARRAY = "XML-RPC struct node template.
*/ +XmlRpc.STRUCT = "XML-RPC member node template.
*/ +XmlRpc.MEMBER = "XML-RPC name node template.
*/ +XmlRpc.NAME = "XML-RPC value node template.
*/ +XmlRpc.VALUE = "XML-RPC scalar node template (int, i4, double, string, boolean, base64, dateTime.iso8601).
*/ +XmlRpc.SCALAR = "<${TYPE}>${DATA}${TYPE}>\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