diff options
283 files changed, 32819 insertions, 0 deletions
diff --git a/boca-1.5.0/README b/boca-1.5.0/README new file mode 100644 index 0000000..ee99235 --- /dev/null +++ b/boca-1.5.0/README @@ -0,0 +1 @@ +Please find the documentation (including the license) in the doc/ folder. diff --git a/boca-1.5.0/doc/.htaccess b/boca-1.5.0/doc/.htaccess new file mode 100644 index 0000000..3a42882 --- /dev/null +++ b/boca-1.5.0/doc/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/boca-1.5.0/doc/ADMIN.txt b/boca-1.5.0/doc/ADMIN.txt new file mode 100644 index 0000000..ed76a16 --- /dev/null +++ b/boca-1.5.0/doc/ADMIN.txt @@ -0,0 +1,319 @@ +How to create a contest +----------------------- +(Last updated: 10/Oct/2011 by cassio@ime.usp.br) + +1) Log in as "system", empty password. + +2) Click on "Options" and change the password of +the user "system" to something secret and safe. + +3a) (Most likely you don't) +If you have an import file, click on "Import", +choose the file, click to Send it and go to step 4. +Note that many follow steps will be already complete. +However, take a time to look at them and verify if +everything is ok. + +3b) Click on "Contest" and create a new contest +(do it by choosing the "new" item of the combo). + +4) Change/Verify the information of the new created +contest and click on "Send". Then click on +"Activate" to make the new contest activated +(after that you will be automatically logged off). +Here some explanation about available fields: +* Name: name of the contest +* Start date: when the contest will begin +* Duration: how many minutes the contest have +* Stop answering: number of minutes from which +teams don't receive the information if their +runs were accepted or not. Usually choose 285 +for fifteen minutes without answers to teams. +* Stop scoreboard: number of minutes from which +the scoreboard becomes frozen (to keep the winner +secret :-). Usual value: 240. +* Penalty: number of minutes a team is penalized +for each time it submits a code that is not +accepted (this minutes are counted only if the +team receives an YES for the corresponding problem, +as done in ACM-ICPC like contests). Usual value: 20. +* Max file size allowed for teams: for security reasons. +If you know that source code files are larger, choose +another value. +* Contest main site number: which is the main site +of the contest (in case of multi-site contests). Usually 1. +IF RUNNING MULTIPLE SITES, BE SURE TO USE THE CORRECT +NUMBERS HERE ASSIGNED BY WHOEVER IS COORDINATING +THE MULTI-SITE CONTEST!! +* Contest local site number: which is the number of the +current site of the contest (in case of multi-site contests). +IF RUNNING MULTIPLE SITES, BE SURE TO USE THE CORRECT +NUMBERS HERE ASSIGNED BY WHOEVER IS COORDINATING +THE MULTI-SITE CONTEST!! + +5) Log in as "admin", empty password. + +6) Click on "Options" and change the password of +the user "admin" to something secret and SAFE!! + +7) (This can be probably skipped if they are already included) +Include any answers for submissions that you might +like to have in addition to the standard ones. +Click on "Answers" and use the two fields to input +the answers. Already pre-included are: +1 YES +2 NO - Compilation error +3 NO - Runtime error +4 NO - Time limit exceeded +5 NO - Presentation error +6 NO - Wrong answer +7 NO - If possible, contact staff +Even the pre-included ones can be changed, but that is not +recommended. + +If you make some mistake, you can re-insert the answer +even without deleting it. Just fill up the fields again, +repeating the answer number (first field). In this case +the database record will be updated. But take care: any +changes with the contest running will affect all records +of the contest. Do not delete any record during the contest +unless you really know what you are doing. The updates +cascade on the database, removing or updating everywhere +needed. + +8) Include the contest languages. Use the "Languages" +item for it. Each language is defined by a number, +a name and two scripts: one for compiling and running +the submitted codes and one for verifying if the +output generated is equilavent to the judge's output. +The scripts should be any executable file permitted +in the computer that will run the autojudging +environment (pay attetion on CRs or CRLFs for EOLs. +This causes problems in some systems). +It's also possible to import the language +information from a file. +The scripts are available together with BOCA in the +"bits" example directory of the documentation. Usually +values are: +1 C C.run compare.sh +2 C++ Cpp.run compare.sh +3 Java Java.run compare.sh + +Remember, all these scripts are available on "bits" directory. +Take some minutes to look into those script files, because +they have path specifications for some executables, such as gcc, +g++, javac, etc. These paths must be fixed (if needed) before +uploading the file to BOCA. Usually the default values work +just fine. If you find any trouble with the scripts, let me +know. +If you make some mistake, you can re-insert the language +even without deleting it. Just fill up the fields again, +repeating the language number (first field). In this case +the database record will be updated. But take care: any +changes with the contest running will affect all records +of the contest. Do not delete any record during the contest +unless you really know what you are doing. The updates +cascade on the database, removing or updating everywhere +necessary. + + +9) Include the problems. Click on "Problems" and +use the form available there. The fields are: +* Number: number of the problem. Start with 1. +* Name: nickname of the problem. Good choices are +problem letters: A, B, C, D, etc. +Problem fullname: the complete name of the problem. +Problem basename: the name of the sourcecode file +expected, without the extension. This is essential +for Java programmers, who must use this name as the +main class name. +* Descfile: a file containing the description of the +problem. It can be a html file, pdf file, etc. It +will become available to the teams during the contest. +You may leave this field empty. +* Inputfile: file with the input to be used when +judging the submission of this problem +(it's possible to have troubles with CRs and CRLFs +for EOLs when using multiple OSes). +* Solfile: file with the correct output for this problem +when executed with the inputfile. This is the file +that will be compared with the output generated by +the team's code (again, it's possible to have problems +with CRs and CRLFs for EOLs when using multiple OSes). +* Time-limit: maximum number of seconds the code should +spend trying to solve this problem. +* Color name: name of the color for this problem. It will +be used if the balloon figure cannot be displayed. +* Color (RGB): enter the rgb value, in the standard HTML +format for colors, for this problem. E.g. 000000 is black, +FFFFFF is white, FF0000 is red, 00FF00 is green and so on. +Colors are interesting because BOCA presents the balloons +with the problem colors. Nevertheless, they are not essential. + +If you make some mistake, you can re-insert the problem +even without deleting it. Just fill up the fields again, +repeating the problem number (first field). In this case +the database record will be updated. But take care: any +changes with the contest running will affect all records +of the contest. Do not delete any record during the contest +unless you really know what you are doing. The updates +cascade on the database, removing or updating everywhere +needed. + + +10) Include the users. There are five types of users +that can be used: admin, team, judge, staff and score. +admin: manage the contest. He(she) has access to every +clarification, run, logs, tasks, etc of the contest. +It is him(her) that starts and ends the competition +(although it can be done automaticly by the system). +You don't need to have more than one or two admin accounts. +judge: responsible for judging the submission and +answering the clarification. It's used to have from +three to eight judges. Note that admins, judges and +staff must have well formed passwords. +staff: responsible for printing files, delivery +balloons, helping teams with hardware problems, etc. +Normally one staff account (for the chief staff person) +is enough. +score: account with the scoreboard. It has no other +privilegies. This account is good for making the coachs +informed about the results and for making the results +available to remote people. A few score accounts are +enough. +team: here is where the contest happens. These accounts +are for the teams. The passwords are not so important +if we restrict the access of each team by IP addresses. +The same thing may be done for the other users too +(and it's a good practice to improve security). +The users can be imported by a text file too. See +IMPORT.txt for details. +The fields presented in the "Users" item are: +* User site number: number of the site of the user. Usually 1. +* User number: number of the user (used internally +by the system). Usually equals the team number. +* Username: nickname of the user. Used to be +team1, team2, team30, judge1, judge2, admin1, staff1, etc. +It's possible to have the same usernumber and username +in different sites. In a single site contest, all user numbers +and usernames must be distinct. +* ICPC ID: ID Number of team in the ICPC System. +* Type: type of the user (team, judge, staff, admin, score) +* Enabled: is the user enabled? +* Multilogins: can the user make more than one connection +at the same time? It's not a problem to allow that if +the users are restricted by IP numbers. +* User full name: complete name of the user. In case of teams, +it's convinient to put the institution name plus the team +nickname here. +* User description: some detail about the user, like students names. +This field is optional. +* User IP: if set, it restricts from where the user can log in +the system. It is recommended to restrict the logins by IP numbers. +If using Maratona Linux, the IP number is 10.0.99.X for the +team numbered X. +* Password: password of the user. You may leave it blank for the +team users as each team user is restricted by IP. Choose good +password for admins, judges and staff. + +If you make some mistake, you can alter the user fields. +Click on the user number in the table and proceed to its +fields below in the page. Edit them and resubmit. Note that, +if you do not fill a new password, the old password is kept. +IMPORTANT WARNING: for users, it is possible to click on +a number for editting the information. All other admin flips +regarding problems, answers, languages, etc do not follow the +same idea. If you click on those number, the corresponding +record will be removed, together with all database information +related to that record. So DO NOT REMOVE ANYTHING DURING +THE CONTEST. + + +11) Configure the site data in the "Site" item. The fields +are: +* Site number: number of the site, with a "new" item to create +new sites. This is not necessary for single contests. +* Name: name of the site +* Public IP: internet IP address of this site for communicating +with the others. Not needed for single contests. +* Start date, End date, stop answering, stop score: equivalent +to admin's contest page. Usually the default values are enough. +* Runs/clars that will be judged here: for multi-site contest, +it defines which runs/clars will be judged in this site. It +is a list of site numbers, separated by commas. For a single +site contest, just leave the site number here. +* Tasks that will be treated here: same meaning of the +previous field. For single contests or multi-site contest +it's used to have each site treating its tasks. So leave here +* the number of the site. +* Active: is the site active? I hope yes. +* Autoend: should the contest ends automaticly at the defined +* time? Usually yes. +* Globalscore: should the scoreboard be propagated to all sites? +Not needed for single contests. +* Autojudge: do not use this option for a contest. It is under +development/test. +* Scorelevel: detail level of information on the scoreboard. +0 means no details while 4 means maximum detail. 2 is a good +choice, although, for single contests, 3 and 4 are also ok and +more informative. A negative number means the same as its +absolute value counterpart, but keeps the problem names hidden +(useful when the same problem set is used in sites with very +distinct start times). + +Furthermore, there are buttons for: start the contest, +end the contest, delete completely (and without undo) the +runs, clarifications and tasks of the site, disable logins, +enable logins and force all users to log off. + +The start and stop buttons should not be used as the contest +start and stop are automatic. They are just for special +purpose, like a energy fault. In this case, you may, when +energy supply become stable again, use the "Stop at" field and +button to indicate when the contest should have stopped and +then the "start now" button to re-start the contest. This will +make the BOCA see this interval time as they never happened, +and all penalty and time calculations will be made correctly. + +The "delete all" fields (delete all clars, delete all runs and +delete all tasks, delete all bkps) are useful (AND IMPORTANT!) +for cleaning everything up just after finished the warmup. +Between the warmup and the real contest, you +do not need to create another BOCA contest. Just erase all warmup +problems, all clars, all tasks and all runs (keeping the languages, +users and answers). Now, reenter the contest information (start +date and duration, insert the real contest problems and you are +ready. + +12) It's all done. + +Important Note +-------------- +Any deletion of problems, languages, answers, users, etc will +promptly delete all records related. So deleting an answer +will remove all runs with that answer. Deleting a problem +will delete all clarifications and runs related to that +problem. This way, it's not recommended to remove any of these +things during the contest. + +Contacts and Copyrights +----------------------- +BOCA Copyright (c) 2003- Cassio Polpo de Campos (cassio@ime.usp.br) +http://www.ime.usp.br/~cassio/boca + +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// diff --git a/boca-1.5.0/doc/AUTOJUDGING.txt b/boca-1.5.0/doc/AUTOJUDGING.txt new file mode 100644 index 0000000..5e89cb1 --- /dev/null +++ b/boca-1.5.0/doc/AUTOJUDGING.txt @@ -0,0 +1,169 @@ +(Last updated 18/oct/2011 by cassio@ime.usp.br. See copyright notice below.) + +AUTOJUDGING.txt +--------------- + +To help the process of judging, the BOCA system provides +a php script that is able to execute some user defined +script in order to compile, execute and compare the output +generated by teams with the correct output. This procedure +is not essential to the system, since each judge is capable +to download from BOCA all the files needed to evaluate a +submission. + +The propose here is not to have a automated scheme for +submission evaluation, but a supporting system that can +help judges to do their job. In this way, the autojudging +provides to the judge the data generated by the scripts +when trying to compile, to execute and to compare the results. +This data is presented in a formatted way during the judging +process inside the BOCA web interface, and can help the +judge to evaluate the submission. If the autojudging is +not enabled in the contest, the judges will see just some +"unavailable" texts when judging a submission, and they +will have to execute the whole process by theirselves. + +To start the autojudging procedure, the only thing needed +is to run the autojudging.php script from some commandline +shell. Note that it may be necessary to change the permissions +of private/conf.php file to something more readable and the php.ini +file to turn safe_mode off (on the computer running the +autojudging scheme). Furthermore, verify whether the private/conf.php +options are correctly pointing to the postgresql server/users +and if the current working directory (ie, ".") is included +in the PATH environment variable. + +$ sudo /bin/bash +# cd /var/www/boca +# php private/autojudging.php + +or alternatively +$ sudo /var/www/boca/tools/autojudge.sh + +The autojudging.php will stay running until CRTL+C is +pressed or it's killed by some other way. Autojudging waits +for a new submission, takes it and executes the +compiling/running script defined in BOCA for the +corresponding language/problem (this script should be +defined during language insertions). The following five +arguments are passed to the compiling/running script: + +$1 base_filename +$2 source_file +$3 input_file +$4 languagename +$5 problemname + +Then, this script must perform the desired steps +(commonly it compiles and runs the source code for +the given input/language/problem) and: + +* the output of the execution should be directed to + the standard output +* the standard error may be used to print anything +* the return code of the script shows what happened + during the script execution, following the rules: + FROM SAFEEXEC +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error + other_codes are unknown to BOCA: in this case BOCA + will present an unknown error status + +After the compiling/running script is executed, the +autojudging calls the comparing script to verify if +the output generated is correct. Now the arguments +passed to comparing script are: + +$1 team_output +$2 sol_output +$3 languagename +$4 problemname + +Basicly the comparing script compares the team +output with the solution (correct) output. The last +line of the standard output of the comparing script +is read by BOCA which transmits it to judges (in +fact this information is available when the judge +takes a submission to evaluate). Moreover, the compare +script send the following codes to BOCA: + 4 - YES, files match + 5 - Presentation error + 6 - Wrong answer + +As long as the autojudging php script will execute +code from teams, these codes may contain malicious +procedures. Thus it is essential that a dedicated +computer be allocated only for the autojudging +scheme. Furthermore, users with shell on this computer +could eventually see important data which they should not +be allowed. This computer must have the same requirements +as the one running the BOCA web interface (but it +does not need postgresql neither a running web server), +and it need to be configured properly. All the steps +described in INSTALL.txt applies to this new computer, +but three important things should be noted: + +1) the computer must have a kind of firewall that +only permits connections between it and the main BOCA +server (this is an important security issue). + +2) the private/conf.php file must be configure properly +with the correct location of the boca database +(probably it will be needed tcp/ip connection to +the postgresql at the main BOCA server), the +correct user/password for database access, the +local IP number and the current contest number. + +3) the postgresql running at the main BOCA server +will have to be configured to accept connections +from the IP of the autojudging server. This can +be achieved inserting the line + +host all all IPAUTOJUDGING 255.255.255.255 md5 + +in the pg_hba.conf file at the main BOCA server. + +Talking a little bit more about the compiling/running +script, it will be responsible for running the executable +code generated from the team's source. This is exactly +where the danger lives. To decrease the risk and to have +control over the time spent by the team's code, the C +source code safeexec.c (tools directory) should be used. +It was designed to execute other programs with lower +privilegies and with a time limit set. It is enough to +"gcc -o safexec safexec.c" for compiling and it is +necessary to make a setuid root: "chown root.root safexec" +and "chmod 4555 safeexec" for running. The files run.sh +and compare.sh are good examples. + + + +Contacts and Copyrights +----------------------- +BOCA Copyright (c) 2003- Cassio Polpo de Campos (cassio@ime.usp.br) +http://www.ime.usp.br/~cassio/boca + +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// diff --git a/boca-1.5.0/doc/INSTALL.txt b/boca-1.5.0/doc/INSTALL.txt new file mode 100644 index 0000000..a9d3bc3 --- /dev/null +++ b/boca-1.5.0/doc/INSTALL.txt @@ -0,0 +1,159 @@ +(Last modified 13/oct/2011 by cassio@ime.usp.br. See Copyright note below.) + +Requirements +------------ +The system was tested with: +* postgresql 7.4+ / 8.2+ +* apache 2.2+ +* php 5.3+ (and some extensions) + +Installation +------------ + +Before following the steps, you must be sure of: +* your php are integrated with your web server, +* the php extension module for the postgresql (php_pgsql.so or +php_pgsql.dll) is installed and configured, +* the postgresql database management system is running. + +Usually that is true if you have installed the following +ubuntu/debian packages: +postgresql, postgresql-contrib, postgresql-client, apache2, +libapache2-mod-php5, php5, php5-cli, php5-cgi, php5-gd, +php5-mcrypt, php5-pgsql + +It may be needed to configure some parameters in php.ini, +postgresql.conf and pg_hba.conf files. The following lines +show some important attributes for BOCA: + +********* apache boca config file (to be included in /etc/apache2/conf.d/): ********** +<Directory /var/www/boca> + AllowOverride Options AuthConfig Limit + Order Allow,Deny + Allow from all + AddDefaultCharset utf-8 +</Directory> +<Directory /var/www/boca/private> + AllowOverride Options AuthConfig Limit + Deny from all +</Directory> +<Directory /var/www/boca/doc> + AllowOverride Options AuthConfig Limit + Deny from all +</Directory> +<Directory /var/www/boca/tools> + AllowOverride Options AuthConfig Limit + Deny from all +</Directory> + + +********* postgresql.conf: ********* +tcpip_socket = true #if using tcp to connect to database (older postgresql's) +listen_addresses = '*' #newer postgresql's + +# THE FOLLOWING MAY BE GOOD FOR PERFORMANCE +max_connections = 100 +maintenance_work_mem = 64MB +shared_buffers = 32MB +work_mem = 3MB + + +********* pg_hba.conf: ********* +#this is the access control file +#restricting connections from unixsocket or localhost is +#the best choice, but it could not enough if the +#database is not in the same machine. +host all all 127.0.0.1 255.255.255.255 md5 +host all all 0.0.0.0 0.0.0.0 md5 +# this last line will allow connection from everywhere. If you +# know the IP address of the machines that will serve as autojudging, +# then you may restrict the access to only such machine. Anyway, +# if you have a good password, that should not be a problem. + + + +Steps for installing boca: + +1) Unpack the boca file into a internet world readable directory, +e.g.: +> mkdir -p /var/www/boca +> cd /var/www/boca +> tar xvzf boca-x.y.z.tar.gz + +2) create a postgresql account with permission to create new +databases (you need database admin privilegies to do that), +e.g.: +> psql -h 127.0.0.1 -U postgres -d template1 +template1=# create user bocauser with password 'boca' createdb; +template1=# \q + +3) edit the file private/conf.php (placed where you unpacked boca), +setting up the correct values. Ex: + $conf["dblocal"]="true"; // use unix socket to connect? + $conf["dbhost"]="localhost"; // ip address of the db + $conf["dbname"]="bocadb"; // name of the boca database + // it should be any name + + $conf["dbuser"]="bocauser"; // unpriviligied boca user + $conf["dbpass"]="boca"; // unpriviligied boca password + $conf["dbsuperuser"]="bocauser"; // priviligied boca user + $conf["dbsuperpass"]="boca"; // priviligied boca password + // note that it is just fine to use the same user for + // unpriv and priv access, but you can separate them + // for increasing local security + + // secret key to be used in HTTP headers + // you MUST set it with any random large enough sequence + // DONT LEAVE IT AS YOU GOT WHEN UNPACKED THE SOFTWARE + // CHOOSE ANOTHER NUMBER/STRING AND REPLACE BELOW + $conf["key"]="secretKey:23894091237589234759234723489"; + + // the following field is used by the autojudging script + // set it with IP address (or other short description) + // of the computer allocated for + // autojudging during the competition + $conf["ip"]='10.10.10.10'; + +4) run the php script to initialize the boca database +> cd /var/www/boca/ +> php private/createdb.php + +5) It's all done. Now you have to manage the contest with a +browser and boca. Proceed to the ADMIN.TXT file. + +Security Issues +--------------- +It is strongly recommended that BOCA be installed on a computer +with no other users. If the computer where you are installing BOCA +is used by others (with command line shells), it is essential +that you change the permission of the file private/conf.php to be +readable just by the user which the apache server runs and set +safe_mode=On in the php.ini file (furthermore, the database access +must be strictly restricted by passwords). Do it before configuring the +private/conf.php file, so no one will be able to see your passwords. +Moreover, the private/conf.php file must be in a directory owned by the +bocauser or www-data or apache (all this combination implies that the only +way to read the private/conf.php is from a php script owned by bocauser in +the same directory). + +Contacts and Copyrights +----------------------- +BOCA Copyright (c) 2003- Cassio Polpo de Campos (cassio@ime.usp.br) +http://www.ime.usp.br/~cassio/boca + +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// diff --git a/boca-1.5.0/doc/LICENSE.txt b/boca-1.5.0/doc/LICENSE.txt new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/boca-1.5.0/doc/LICENSE.txt @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + 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 the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + <program> Copyright (C) <year> <name of author> + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +<http://www.gnu.org/licenses/>. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +<http://www.gnu.org/philosophy/why-not-lgpl.html>. diff --git a/boca-1.5.0/doc/READMEubuntu.txt b/boca-1.5.0/doc/READMEubuntu.txt new file mode 100644 index 0000000..09994a8 --- /dev/null +++ b/boca-1.5.0/doc/READMEubuntu.txt @@ -0,0 +1,33 @@ +ICPC Linux installation script +---------------------------------- +Copyright (c) 2009 C. P. de Campos. +Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". +--------------------------------- +File last modified: 11/oct/2011 + +==> The installv2.sh script is not necessary if you are using the virtual machine version. This is intended to those that +want to install the system as the host of a computer, or desire to create again the virtual machine version from the beginning. + +The script installv2.sh available here was used to create the "ICPC Linux" image after a standard installation +of the ubuntu (or xubuntu) distribution. This is well-suitable in case you do not want to +use the virtualized version, for example, in the server of the contest. After using the installv2.sh script over a fresh +install of the ubuntu, you reach the exactly same content of the virtual machine version that is available. +Take care with the following points during the installation of the ubuntu: +1) Use the name "icpcadmin" and password "icpcadmin" (no quotes obviously) as the standard user during the installation. +2) Call the machine "icpc" (in the same screen where you set up the username above). +3) Use the simplest partitioning option (that is, everything in a single partition) and choose at least 10GB for it. + +After installing ubuntu, the system reboots. Download the script installv2.sh to the home directory of icpcadmin, +make it executable by chmod 755 installv2.sh, and run it as root: sudo ./installv2.sh +and reboot the system to finish the configuration (such as setting passwords, IPs, etc). +Note this is going to give you a system just like you would get from the box (the virtual machine version). If you +want it to become a server, you must follow the same procedure that is indicated in the READMEvm.txt. This +mainly means that you need to run the script /etc/icpc/becomeserver.sh + +The most recent installv2.sh script is available at http://www.ime.usp.br/~cassio/boca/ link named installv2.sh +In case of any questions, do not hesitate to contact me: bocasystem@gmail.com. Have fun! diff --git a/boca-1.5.0/doc/READMEvm.txt b/boca-1.5.0/doc/READMEvm.txt new file mode 100644 index 0000000..e78fca8 --- /dev/null +++ b/boca-1.5.0/doc/READMEvm.txt @@ -0,0 +1,163 @@ +READMEvm.txt file of the ICPC Linux VM (release 2011) +================================= +Copyright (c) 2009-2011 C. P. de Campos. +Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". +================================= +Last modified: 10/Oct/2011 + +This file concerns the ICPC Linux image available in this directory. It is a vmware-type +hard-disk image with a system built up over a ubuntu (or xubuntu) distribution. This is +also relevant if you have used the installv2.sh script to build the server natively, as the +system will have the exactly same characteristics of the VM version mentioned here. + +- You need the vmplayer from www.vmware.com to use this image. As far as I know, vmplayer is +free-of-charge for linux and windows hosts. Check it. There is another version based on virtualbox, +which is just a translation from the image here. virtualbox is free and works pretty well too. + +- Internet access is restricted inside the box. By default, users can only access +bombonera.ime.usp.br, the home of BOCA. During the first boot time, you are able to choose a +different IP address of your server instead of bombonera. If you are going to run a contest, +you must do that! The system inside the virtual machine (or just VM) will +only be able to access such server and nothing else. An alias with the name boca is created +for such IP, so it is possible to connect to it using the name boca instead of typing the +IP address. So, during the first initialization of each VM you should configure the IP address +of your BOCA server. The image provided here can be used as a BOCA server too. See next bullets +on how to do that. In the team machines, check if the internet is really blocked. If not, the +initialization scripts might be malfunctioning, or the computer might be mistakenly set to be +a server (this can be easily checked by verifying whether the file /etc/icpc/.isserver exists or not). + +- There are two linux users in the box: icpcadmin, which has right to become root using +sudo, and the user icpc. The latter has password icpc, and more restricted access. The user +icpc is intended to be used by the teams, judges, staff, or anyone else. The icpcadmin is +an administrative account and the password must be known only by the sysadmin, director of the +contest, and so on. During the first boot time, you are able to change the password of the icpcadmin +account. DO IT and keep it safe! The default password is icpcadmin. Note that such +users (icpcadmin and icpc) have nothing to do with users of the BOCA web system. Each +team must have a distinct user to login on BOCA, which are configured through the BOCA web interface. +Still, each team will logon into the linux box using the same user: icpc. As mentioned, this is +not a security problem because the user icpc is just a local account in the linux system without +any privileges. + +- To run a contest using a virtual machine, you probably need at least 384MB of RAM inside a +"good" computer (then you can configure the VM to run with 256MB). I have tested the vm image +configured to use 512MB. If your host has for example 1GB, you may change the vmplayer +to use 768MB, although 512 should be fine too. Just keep some room for the underlying operating +system. Using more memory inside the vm is better for the teams, so they can run heavier tools. + +- Unzipped, the image takes around 12 GB of your hard disk. You need this space in the hard +disk of each computer. If this is a problem for you, it is possible to rebuild the vm system +with less space (8GB for clients is enough, the server has to have more). + +- It is possible to maximize the VM window so as it uses the whole screen area. The current +image is set to 800x600 or 1024x768 pixels, but that can probably be increased depending on your +video card and monitor settings. The keyboard config can also be changed +inside the x-window system configurations. + +- During the first startup, an script will ask you for the BOCA database password (after +asking the BOCA server IP address and password of the icpcadmin). YOU MUST ONLY FILL +SUCH PASSWORD IN THERE IF the machine being configured is NOT going to be used by a team. With +this password, it will be possible to access the database directly (instead of by web). Teams +shall access the system only by using the web interface. This password is intended to be used +in the machine that will have the autojudging system, as the autojudging script needs to +connect to the database directly (see next item about the autojudge). In fact only the +autojudging machine (or machines, if you have more than one) need this password to be set. + +- An autojugding machine is used to automatically compile and execute the codes submitted +by the teams. DO NOT run it on the same computer as the BOCA server (the web server and the database +server). Because teams may submit malicious code, it is safe to run it on a separate computer. +The worst scenario (in case a team's code hangs the computer) will require to reboot such +computer. About the configuration, the only difference between the autojudge computer and +team's computers is the setup of the database password, as mentioned before. You must set up +the database password during the initialization of the autojudging computer. Then, to run the +autojudging system, you need to login as icpcadmin (privileged user), open a command-line +terminal (it is inside accessories), and run "sudo /var/www/boca/tools/autojudge.sh" (without quotes). +If everything is fine, some dots will appear on the screen while the script runs an infinite +loop waiting for submissions. Ctrl-C stops the autojudge. The autojudging shall be started +after configuring the server to run the contest, otherwise it will eventually output an error or +freeze. If you see the dots happening every few seconds, you are in the correct track. + +- With old versions of ICPC Linux, all the team files were kept in the server. Now this is +NOT true anymore. Everything is stored locally. So, after a warmup and before the real +contest, it is necessary to go to each team computer, open a command-line shell (you do not +need to change to the privileged user, the unprivilegied icpc user is enough) and run +the command +/etc/icpc/cleandisk.sh +After that, reboot the system inside the virtual machine (not the host computer itself!) and you +are done. All files belonging to the icpc user have been erased. + +- Because the files are stored in the local team computers, now BOCA (by web) has an option +to make file backups, where teams can save their files on the server. Currently this must be done +manually by the teams (using the web interface of BOCA). There is a script available inside the +ICPC linux (and inside the BOCA package) that teams may use to backup their files. To +do that, they can just run "makebkp.sh". If they want to save other files, it is possible to use +the web interface of the teams. Note that teams should submit backup files with small size only, but +that is not a problem because source codes are really small. The script makebkp.sh is available +(but not very tested) which sends files .c, .cpp, .java and .in (it looks for these files in the +current directory) to the server. IT IS IMPORTANT TO LET THE TEAMS KNOW ABOUT THIS SITUATION AND +THE POSSIBILITY OF SAVING FILES TO THE SERVER, EITHER BY USING THE makebkp.sh IN THE COMMAND-LINE, +OR BY DIRECTLY UPLOADING THE FILES IN THE WEB INTERFACE. + +- The most complicated thing to run the contest using a VM is that you need to restrict the +use of the host operating system. For example, it would be possible for a team to switch +the window (from the VM to another program), and then use the internet (in case you have +internet available in the host, which is usually true). I believe that the simplest approach +to restrict the system is to impose a set of packet filtering rules in the host system, using +a firewall solution. That would make the host system useless for the team. The only permission +that the host must have is to allow connections to the BOCA server and (possibly) to the +authentication server of your network (in case it is needed to keep the host running. Better +if that can be avoided too). If your host is linux, then it is easy: you just need to include some +rules in the iptables (certainly a sysadmin knows how to do it). +For windows (which is probably more usual and easy to deal with), there are many free-of-charge +solutions. I do not know them well, but let me cite some: www.r-firewall.com, +www.personalfirewall.comodo.com, tiny personal firewall (it is possible to find it online), +perhaps the windows firewall can be enough (in some windows versions). NOW THE MOST COMMON / +PRACTICAL WAY TO SOLVE THE PROBLEM: keep an eye on the teams all the time. Have some volunteers +looking the teams work on the computers during the whole contest. No one is allowed to leave the +VM and use the underlying system. If they do that, then simply expel them from the contest! +Give a warn of the possible penalty to everyone before starting and that is it. Quick and clean :D + +- Any vm can become a server for the contest, which in this case will be a BOCA server running +inside a virtual machine system. To do that, you just need to login as user +icpcadmin, become root using the command "sudo /bin/bash" +and execute the script /etc/icpc/becomeserver.sh +READ THE FULL TEXT BEFORE RUNNING THIS SCRIPT. THE VM MUST BE IN BRIDGE MODE (see explanation +below). At this moment, you will be prompted to define the DB password or use a random one. After +that, the IP address of this computer must be used to configure all other VMs (during those +startup questions). +Some considerations about a server: more memory must be used for the server. Have a computer +with enough memory and increase the memory of the VM. Also take care with the +disk space. The current image has only around 1.6GB free (still, that must be more than enough). +Finally, note that to run the VM as the server, it must be configured to run in BRIDGE mode +with respect to the network interface, otherwise it will not be possible for other computers +to reach it. BRIDGE mode means that you must look in your vmplayer (whatever player you are using) +to configure the network as in BRIDGE mode). You may need to reboot the VM. If after rebooting it +and running the command-line program "ifconfig" you can see that the IP address of your computer +is the same inside the VM and outside, you are done. Besides that, the underlying operating +system must have NO apache or postgresql running, nor +any other TCP server in the ports 80 (http), 443 (https) and 5432 (postgres). +Yet I point out that running the BOCA system in a server computer (without the VM) +is the mostly tested solution, but the VM version was used in many sites already. If you want to +run it natively, stop here and go to the xubuntu directory of bombonera.ime.usp.br to see the +instructions. You will need a computer that you can format and reinstall. +That is the simplest way of having a full ICPC linux server +running apart from using the VM version itself, as explained here. + +- After having the server and clients running up, it is necessary to configure the BOCA +web system. For that purpose, please follow the steps of the ADMIN.txt file in the doc/ +folder of the boca system. It is available in the BOCA package or inside the ICPC +linux at /var/www/boca/doc/. There are some examples inside the bits/ subfolder. + +- Try to use the vm without fear. In the worst case, download it again and start again +(or even better, keep a copy of the image without changes). Any questions, please +do not hesitate to contact me: bocasystem@gmail.com. + +- If you need to update the BOCA system that is running in your server (with the risk of losing +data in the database of BOCA!), then you may run the script /etc/icpc/installboca.sh +If you need to update general scripts that are used in the system and were installed by the +installv2.sh procedure, you may run the script /etc/icpc/installscripts.sh +These are easy ways to update the system in case bugs are found and fixed. diff --git a/boca-1.5.0/doc/changelog.txt b/boca-1.5.0/doc/changelog.txt new file mode 100644 index 0000000..65e63b3 --- /dev/null +++ b/boca-1.5.0/doc/changelog.txt @@ -0,0 +1,159 @@ +version 1.5.0: +2012/07/10 +- (ICPC Linux) updated scripts to create ICPC linux under ubuntu 12.04. Hopefully it will still work with + older versions of ubuntu. +- (ICPC Linux) java version now is openjdk6 (it is getting harder to keep using sun java on new linux distributions) + +version 1.4.2: +2011/11/04 +- user type site created to allow for pushing of scores from other sites +- createdb.php moved to private/ for better safety. Option to abort its execution is included. +- autojudging.php moved to private/ for better safety +- possibility of multiple scores defined by the private/score.sep file +- fix of setup.sh and rc.local scripts to properly set firewall rules (thanks Flavio GC Rocha). + Also some other minor script changes, such as /etc/network/if-pre-up.d/boca +- script that creates the bocajail changed to /etc/icpc/createbocajail.sh and some + improvements are applied (e.g. use of debootstrap). It should now run smoother on + ubuntu and other debian-like systems. +- bugfix: general clarification option was not appearing in the list of problems. +- scripts have been updated to make it easy to replace the use of user 'www-data' by 'apache'. +- updatescores.sh now accepts full path names for servers. This solves the case where boca + is not installed in the default http://SERVER/boca/ +- updatescores.sh now gets all the available information about the score of the other sites, and + the local boca server decides which info shall be put in the score board. This fixes issues with + displaying undesired info from other sites, because the responsability is given to local boca. +- webcast directory for F. D. Moreira's fancy score included in the distro. + +version 1.4.1: +2011/10/10 +- special chars and character encoding included as utf-8 in every page. This shall fix the + bug of dealing with special chars. +- bug fix: max length of clars fixed. +- bug fix: teams could not download their submitted code. +- many changes to improve security of safeexec (including possibility of chrooting) +- changes to improve security of conf.php +- changes to make php configuration directly on .htaccess file of the boca folder +- new feature: speed improvement by caching run.php of teams +- new feature: speed improvement by caching scores of all users +- new feature: scores can be read from files, which can be updated from other servers by a script +- new feature: chief judge is introduced (configured at admin/site.php) and each run has to be + judged by two judges. In case of disagreement, chief judge or admin has to act. +- new feature: judges can submit code to the system (even before the competition is running). +- new feature: admin and chief judge can open multiple runs to re-judge at once in the same screen. +- scripts to run code at doc/bits/ updated to cope with new safeexec and possible chrooting +- directory doc/tools/ moved to tools/ +- directory doc/bits/ reorganized +- development of install scripts and config files for making ubuntu/xubuntu be ready for running + a competition are included in tools/ +- simple html versions of manuals for teams and judges included in doc/html/ + +version 1.4.0: +2009/08/31 +- safeexec updated to include option of multiple runs of the same code (e.g. for averaging the time). + +version 1.3.2: +2008/08/31 +- bug fix: div by zero at history of judges (thanks to Marcelo Cezar Pinto). +- standard encoding changed to UTF8 to facilitate the installation on debian/ubuntu systems. +- scripts to compile/execute runs changed to user nobody and group nogroup to fix a warning. + +version 1.3.1: +2008/08/19 +- bug fix: filenames with spaces were not properly handled by filewindow.php and filedownload.php +- delete functions of languages, problems and answers are replaced by nicer versions where the runs + are kept in the system (Thanks to Renato Lucindo :). +- openrun feature now does not make the run completely reopened (the teams keep seeing the already + judged results, while the runs are rejudged. If a change is performed, then the new status is seen. +- autojudging procedure now keeps a copy of input and output files in the local filesystem, so the + network and DB accesses are reduced (Thanks to huge files of Wanderley Guimaraes :). +- bug fix: autojudging was not removing old directories, so that was taking extra space on disk. I + do not know if this was a bug or a feature. +- script makebkp.sh added to connect to BOCA by http and send source files. + +version 1.3.0: +2008/08/12 +- new backup feature. Teams can submit files to the server to keep them there. This is going to + replace the network mounted homes of Maratona Linux. + +version 1.2.3: +2007/08/25 +- php tag <? changed to <?php in all files for better compatibility (Thanks to Joel Uchoa). + +version 1.2.2: +2007/08/22 +- bug fix: (Thanks to Fabio D. Moreira) when installing on root directory, + global path variables had an extra '/', leading to problems with browsers. + +version 1.2.1: +2007/08/21 +- new md5sum check while importing files in "systems" interface. +- bug fix: autojudge WHI didnt work. It is still experimental. + +version 1.2.0: +2007/08/20 +- bug fix: tie rule now includes the first accepted run. +- bug fix: names with spaces would create problems to bash scripts. +- scoreboard improved. New level (4) has many ideas introduced + during ICPC world finals 2007. +- judge's history now is complete: it has all clars and runs. +- autojudging and scripts modified so as to send diff outputs to judges. +- autojudging and related procedures updated to allow automatic + judging without human interaction (WHI). +- documentation updated to agree with system improvements. + +version 1.1.2: +2006/09/16 +- bug fix: extra empty line removed when donwloading files. + +version 1.1.1: +2006/08/21 +- bug fix: wrong variable name in DBUpdateTask. +- bug fix: admin calls DBChiefUpdateTask instead of DBUpdateTask. +- bug fix: send only one balloon per problem. +- textarea for showing clarifications. + +version 1.1.0: +2006/07/31 +- documentation atualization. +- new problem attributes: color and colorname. +- new balloon images and graphics. +- new feature to stop and start the contest several times. +- report page implementation. +- new feature to order runs (on admin's interface) as desired. +- new feature to order clarifications (on admin's interface) as desired. +- new feature to order tasks (on admin's interface) as desired. +- html tag <pre></pre> defined for showing clarifications. +- bug fix: some http headers could not be sent because of misplaced + output buffering. This was implying in some "session expired" messages. + +version 1.0.6: +2005/09/04 +- bug fix: special characters in problem names. + +version 1.0.5: +2004/10/06 +- included timelimit field for problems. + +version 1.0.4: +2004/08/19 +- bug fix: in the task window, the file to print was unavailable. +- new button to view the file before printing. +- Pascal (Free Pascal Compiler) included in the run.sh example. +- run.sh improved to better detect errors +- autojudging small text changes + +version 1.0.3: +2004/06/18 +- bug fix: incorrect report of new balloons to staff. +- documentation changes concerning autojugding. +- changes on limit clauses for compatibility with postgres 7.1.x/php 4.1.x. + +version 1.0.2: +2004/06/05 +- bug fix: problem to drop the database when it does not exist. +- bug fix: duplicating new contests using mozilla browser. +- changes on file permissions inside the tarball. + +version 1.0.1: +2004/05/09 +- first public release. In 2003, boca 0.5 was used. diff --git a/boca-1.5.0/doc/dump.sh b/boca-1.5.0/doc/dump.sh new file mode 100755 index 0000000..caf03ef --- /dev/null +++ b/boca-1.5.0/doc/dump.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +for i in pg_dump grep cut gzip date; do + if [ "`which $i`" == "" ]; then + echo "$i executable is not in the PATH. Aborting" + exit 1 + fi +done +da=`date +%d%b%Y-%Hh%Mmin` +echo "I will create the file `pwd`/bocadb.$da.tar.gz" +f=/var/www/boca/private/conf.php +[ -r $f ] || f=/var/www/private/conf.php +if [ -r $f ]; then + echo I believe the password is `grep "\$conf\[\"dbpass\"\]=" /var/www/boca/private/conf.php | cut -d'"' -f4` +else + echo "The password can be found in private/conf.php of the boca directory" +fi +pg_dump -f bocadb.$da.tar -Ft -b -h 127.0.0.1 -U bocauser bocadb +gzip -9 bocadb.$da.tar + +exit 0 diff --git a/boca-1.5.0/doc/html/.htaccess b/boca-1.5.0/doc/html/.htaccess new file mode 100644 index 0000000..605d2f4 --- /dev/null +++ b/boca-1.5.0/doc/html/.htaccess @@ -0,0 +1 @@ +Allow from all diff --git a/boca-1.5.0/doc/html/manualjudge.en.html b/boca-1.5.0/doc/html/manualjudge.en.html new file mode 100644 index 0000000..a7f8a0e --- /dev/null +++ b/boca-1.5.0/doc/html/manualjudge.en.html @@ -0,0 +1,203 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html><head> + +<meta http-equiv="content-type" content="text/html;charset=iso-8859-1"> +<title>BOCA Manual for the judges</title> +</head> +<body bgcolor="white" link="blue" vlink="blue"> +<font size="5"><b>BOCA Online Contest Administrator</b></font> +<p><b>BOCA Reference Manual for judges<font size="5"> - </font> +version October/2011 (BOCA 1.4.1+)</b> +</p> + +<p><font size="1">Copyright (c) 2006-2011 Cassio P. de Campos (cassio@ime.usp.br).<br> +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU Free Documentation License, Version 1.2 or any later +version published by the Free Software Foundation; with no Invariant Sections, +no Front-Cover Texts, and no Back-Cover Texts. A copy of the license may be +found in <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a></font></p> + +<p>BOCA is a software created to control a contest with the <i>ACM International Collegiate +Programming Contest</i> rules. It has been developed in PHP and the interaction between judges +and the system is done through a <i>web browser</i>. In the following we describe +the set of available features for a judge in the system.</p> + +<p>It is assumed here that the judge has already logged in the system with their +<i>username</i> and <i>password</i> in a windows of their browser. Tthe <i>URL</i> +to access BOCA will depend on the setup of your server. Usually this URL ends with +<i>/boca/</i>, where a simple authentication form will show up. + +<p> +After a successful login, the web page contains the judge identification in the upper-left +corner. In the upper-right corner, the clock of the contest is shown, indicating if it has +started or not, if it has already ended, stopped, or in progress, in which case the number of +minutes to go are displayed. Below that, there is a set of options in a vertical menu, namely +<i>Runs, Score, Clarifications, History, As Team, Options e Logout.</i> +There is still an extra option named <i>Chief</i> which only appear to the chief judge, who +has to be appointed in the admin's interface (with in the <i>Site</i> options). +</p> + +<p><font size="4"><b>Runs</b></font></p> +<p> In this area, the judge might visualize the runs that are still to be judged and shall be +taken care of. In order to process a run, the judge has to click in its number (eventually a +message might pop up here indicating the run was already taken; this happens if another judge +got the run before you). After clicking on the run to judge, a new set of data appear about it: + +<ol> +<li><b>Site</b>: site number of the run.</li> +<li><b>Number</b>: run number.</li> +<li><b>Time</b>: minutes from the start of the competition until this submission.</li> +<li><b>Problem</b> <i>X</i>: <i>X</i> is the name of problem. There are links +to download the input and output files (click on the names), or simply to visualize them in the browser (click on view). +These links are mostly used when the <i>autojudge</i> is turned off or is not running properly for a given problem/language. +Instead, if the <i>autojudge</i> feature is working correctly, then the judge can directly to go the links in the bottom part of +the page in order to see the expected output together with the output generated by the team. +</li> +<li><b>Language</b> <i>Y</i>: <i>Y</i> is the language chosen by the team. The scripts that are used to +compile and execute the submission with this language are available through links. +When using the <i>autojudge</i>, note that is not necessary to use this links, because the results are +already shown in the bottom of the page. +</li> +<li><b>Source code</b>: here it is possible to <i>view</i> or download the submitted file. An important +task is to check if the name and extension of this file are correct with respect to the chosen problem, language, +and the specification in the booklet of problem descriptions. +</li> +<li><b>Answer</b>: the judge has to choose, among the options available in the system (which were configured by the admin), +the correct answer to be sent to the team. +</li> +<li><b>Autojudging answer</b>: here it is presented the suggestion from the <i>autojudge</i> about this submission. +Usually the <i>autojudge</i> properly identify the answer that has to be sent to the team. However, it may +fail to do so. For example, the <i>autojudge</i> might indicate a <b>wrong answer</b>, because the +<i>diff</i> procedure identified the output and expected output to be different, while the only mistake +happened in the punctuation/accent of a letter (this is usually a case of <b>presentation error</b>, but +may vary according to the contest). Other issues might happen, and the role of the judge is to check everything +for eventual mistakes. +</li> +<li><b>Autojudged by</b>: indicates the computer that has acts as <i>autojudge</i>. Usually this is not +much relevant for judging a submission. +</li> +<li><b>Standard output</b>: links for downloading and visualizing the output generated by the team's code are +available. This is the output generated by the team, which is to be compared with the expected output of +the given problem. It might also be possible to see some error, in case it happened. +</li> +<li><b>Standard error</b>: links for downloading and visualizing the standard error output generated by the team's code. +When a error happens (including compilation or runtime errors, but not restricted to them), this is the most probable file to identify it. +The judge must always check the content of this file. In the end of it, the judge also finds the output of the <i>diff</i> command +that has compared the team's output and the expected one (to facilitate the visual inspection). +</li> +</ol> + +<p>By pressing the button named <b>Judge</b>, the judge submits their veredict about the <i>run</i>, and then +has no access to the this <i>run</i> anymore. It is also possible to give up judging the run by clicking +on <b>Cancel</b>, which will send the run back to the pool (and it will be eventually judged by another judge). +</p> + +<p>In the tab <i>Runs</i>, the judge can see all the submissions that are yet to be judged. The colors +represent their status, meaning that they are already been judged by others, or that they are waiting +you to judge them (red color). You must act with respect to those in red, as only you can judge them (or +send them back to the pool). +</p> + +<p></p> +<p><font size="4"><b>Chief</b></font></p> +<p> +Besides acting as a normal judge, there is a designated judge with access to the tab <i>Chief</i>. This tab +is used for the chief judge to resolve disputes regarding submissions that received different answers by different +judges (they are shown in red). The prodecure is equivalent to that of a normal judge, but the decision made in the tab of the chief is +final. The idea is to have the chief judge acting as a tie-breaker between the distinct answers that were assigned to +a <i>run</i>. Hence, if the chief judge is acting as a normal judge (and they may do so), it is recommended to use +the tab <i>Runs</i> instead, leaving the tab <i>Chief</i> only for resolving issues. (In the very special case where there +is a single judge in the competition, then this judge has to be designated as chief and shall use the tab <i>Chief</i> +to judge the runs, otherwise they will never receive the judgement of another judge and thus will not be sent to teams.) +In this same tab, the chief judge is able to ask the <i>autojudge</i> to be re-executed for some submissions (selected by +the boxes besides each of them) or to completely re-open the submission for judging again, which implies in a new round +of autojudging and judging by actual judges. The <b>team does not become aware</b> of this rejudging unless the new final +result for the run has to be changed (with respect to the first round of judgement). +</p> +<p></p> + +<p></p> +<p><font size="4"><b>Score</b></font></p> +<p>In this tab the judge can see the scoreboard of the competition. It has to be noted that the scoreboard available +for the judges is complete and not subject to the freezing of the final part of the contest. Hence, the judge is +expected to keep the scoreboard in secret. In case the scoreboard is consolidated among different sites, the final part +of the other sites is not shown (*this fact is for technical reasons, to be discussed later*). +</p> + +<p><font size="4"><b>Clarifications</b></font></p> +<p>This tab allows the judge to answer <i>clarifications</i> submitted by team regarding +a specific problem or any general aspect of the contest. +In order to reply to a <i>clarification</i>, the judge must first <b>click on the clarification number</b>. +The box available in the bottom part is meant for creating a new clarification, as judges are allowed to do +so. The new clarification will only be meaningful if the judge that gets it to answer selected the reply to all +option (explained in the next paragraph). This is useful for the judges to send a general information to the teams. +</p> + +<p>After clicking on the clarification number, the judge sees information about it, such as +site number, clarification number, time in minutes from the start of the competition, and the +problem to which the clarification regards. There are two text boxes: one with the question (on top) +and one to be filled with the reply. Finally, there is a selection box to indicate if the reply +should be sent to all the teams or just the the team that posted the question. +</p> + +<p>The system also allows the judge to select the <u><i>No response</i></u> button. In general +this is used for questions that are already stated in the booklet of problem descriptions, or +that has already been replied, or even that should not be answered at all (for example, about +the timelimit of a problem, or about some sensitive information of the input/output). +</p> + +<p><font size="4"><b>History</b></font></p> +<p>This tab shows the history of <i>Clarifications</i> and +<i>Runs</i> that were processed by the judge so far. +</p> + +<p><font size="4"><b>Options</b></font></p> +<p>This tab shows the information of the judge, such as <i>Username, +User</i> <i>full name </i>,<i> User description</i>. It is possible +for the judge to update their password, although this is not necessary neither +recommended. Instead it is recommended that the admin who created the users already +specifies secret and safe password for all users. +</p> +<br> + +</p> +<p><font size="4"><i><b>Logout</b></i></font></p> +<p>Button to log out from the judge interface.</p> + +<p><font size="4"><b>Important hints for judges</b></font></p> +<p> While judging a submission, it is necessary to be very careful. Even if it is possible +to alter the judgement of a run afterwards, this has to be avoided as much as possible, because +the team might suffer an undesired situation. +</p> +<p>Every time a judge is about to answer a problem for its first time (that is, the problem has not +been submitted before, or has not received yet any YESes), when possible it is interesting to have other judges +also checking the submission, which should be analyzed with even greater care. Sometimes this is the +moment when an unfortunate issue with the <i>autojudge</i> or with inputs or outputs is discovered +(obviously nobody wants it to happen, but it might). +</p> +<p>In order to reply to <i>clarifications</i>, it is important that the judge has read and understood +the question and the problem to which it concerns. When possible, it is interesting to have the opinion +of the person or group that created the problem description, its input and output. After that, +it is necessary to think if such reply has to be sent only +to this user or to all teams in the contest. If it is a relevant issue and the contest is also offered in +other sites, then the judge shall find a way to contact other sites about the clarification. +Some examples of clarifications that are not disclosured (that is, are replied with a <i>no response</i>) +are +<i>What is the timelimit for this problem?</i>, +<i>Given this input, which is the correct output?</i>, +questions that are already explained in the problem description, +etc. +In case the judge is not certain about it, they must contact the chief judge of the site or the +chief judge of the contest for help. +</p> + +<p><font size="4"><b>About BOCA and this document</b></font></p> +<p>BOCA System and this document have been created by Cassio Polpo de Campos and can be found at +<a href="http://www.ime.usp.br/~cassio/boca/">http://www.ime.usp.br/~cassio/boca/</a>.</p> + +<hr> +<p> +<a href="http://validator.w3.org/check?uri=referer"> +<img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!" border="0" height="31" width="88"></a> + +</p></body></html> diff --git a/boca-1.5.0/doc/html/manualjudge.pt_br.html b/boca-1.5.0/doc/html/manualjudge.pt_br.html new file mode 100644 index 0000000..eabeecc --- /dev/null +++ b/boca-1.5.0/doc/html/manualjudge.pt_br.html @@ -0,0 +1,219 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html><head> + +<meta http-equiv="content-type" content="text/html;charset=iso-8859-1"> +<title>Manual do BOCA para as equipes</title> +</head> +<body bgcolor="white" link="blue" vlink="blue"> +<font size="5"><b>BOCA Online Contest Administrator - Sistema de Submissão</b></font> +<p><b>Manual de Referência para os juízes<font size="5"> - </font> +versão setembro/2010 (para o BOCA versão 1.4.x)</b> +</p> + +<p><font size="1">Copyright (c) 2006-2010 Cassio P. de Campos (cassio@ime.usp.br).<br> +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU Free Documentation License, Version 1.2 or any later +version published by the Free Software Foundation; with no Invariant Sections, +no Front-Cover Texts, and no Back-Cover Texts. A copy of the license may be +found in <a href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a></font></p> + +<p>O BOCA é um <i>software</i> criado para controlar uma competição nos moldes +da Maratona de Programação da SBC. Foi feito em PHP e a interação dos juízes +com o sistema é feita usando-se um <i>browser</i>. A seguir descrevemos a +interface disponível no BOCA para os juízes e suas principais funções.</p> + +<p>Neste texto será assumido que o juiz já realizou o seu +<i>login</i> na máquina e abriu uma janela do navegador (leia +as instruções sobre o Maratona Linux ou sobre o sistema que +estiver sendo utilizado). O BOCA é acessado através de uma +<i>URL</i> (usualmente a página se chama +http://mainserver/boca ou http://bocaserver/boca). +Ao carregar a página, o juiz deverá ver a +tela de <i>login</i> do BOCA. Basta digitar o <i>login</i> do +BOCA fornecido ao juiz e a sua senha correspondente.</p> + +<p>Após realizar o <i>login</i> com sucesso, uma página deverá ser aberta +contendo a identificação do juiz no canto superior esquerdo. +No canto superior +direito haverá a informação sobre o estado da competição: ou ainda não +começou, ou já acabou, ou está parada, ou a competição está em andamento e a +quantidade de minutos restantes será mostrada. Mais abaixo dessas primeiras +linhas estarão seis opções, que representam a interface propriamente dita do +BOCA. Estas seis opções são: <i>Runs, +Score, Clarifications, History, Options e Logout.</i> +Existe ainda uma opção extra para o juiz chefe (que deve ser previamente apontado através da +interface do admin no sistema): <i>Chief</i>. Ela não está disponível para os demais juízes. +</p> + +<p><font size="4"><b>Runs</b></font></p> +<p>Ao entrar nessa opção, o juiz poderá visualizar as submissões que ainda +não foram corrigidas e devem ser processadas. Para corrigir uma submissão, +o juiz deve clicar sobre seu número (como é feito o tratamento de concorrência +para que dois ou mais juízes não peguem a mesma <i>Run</i>, neste momento o juiz pode +ser avisado que a <i>Run</i> acaba de ser pega por outro juiz). Ao clicar em uma +submissão, o juiz verá os seguintes campos: +<ol> +<li><b>Site</b>: número do site atual.</li> +<li><b>Number</b>: número da <i>Run</i> sendo julgada.</li> +<li><b>Time</b>: minutos decorridos da competição para esta submissão.</li> +<li><b>Problem</b> <i>X</i>: <i>X</i> é o nome do problema. Ao lado, existem +links para fazer o download (clicando sobre o nome) ou simplesmente visualizar +os arquivos de entrada e saída (clicando em <i>view</i>). Usando o esquema de +autojudging, o importante é ficar atento à saída esperada, comparando-a com a +saída que o programa da equipe gerou.</li> +<li><b>Language</b> <i>Y</i>: <i>Y</i> é a linguagem escolhida pela equipe. Ao +lado aparece o script para compilação e execução nesta linguagem. Note que, +utilizando o esquema de autojudging, não é necessário olhar para esse arquivo.</li> +<li><b>Source code</b>: Aqui é possível visualizar (<i>view</i>) ou fazer o +download do arquivo submetido. Um ponto importante para o juiz é verificar se +o nome e a extensão desse arquivo estão de acordo com o problema e a linguagem +escolhidos.</li> +<li><b>Answer</b>: Neste campo o juiz escolherá qual a resposta que será enviada +para a equipe. Para tomar essa decisão, ele tem à disposição os arquivos e botões +já mencionados e também, logo abaixo, os dados gerados pelo esquema de autojudging +(se esse esquema estiver sendo utilizado).</li> +<li><b>Autojudging answer</b>: Resposta sugerida pelo esquema de autojudging. +Usualmente o autojudging acerta o que deve ser respondido às equipes, mas pode +falhar. Por exemplo, ele pode dizer que a resposta está errada (<b>Incorrect Output</b>), +pois comparou os arquivos e não eram iguais, mas o único erro do programa da +equipe foi na digitação de um acento em uma palavra (usualmente isso é simplesmente +um <b>Output format error</b>). Outros detalhes podem ocorrer, e o juiz deve +estar atento aos próximos demais dados fornecidos pelo autojudging.</li> +<li><b>Autojudged by</b>: indica qual computador fez o autojudging, no +caso de diversos autojudgings estarem sendo utilizados. Usualmente não essencial +na correção.</li> +<li><b>Standard output</b>: links para fazer o download ou visualizar a saída +padrão gerada pelo programa da equipe. Usualmente neste lugar deve estar a +saída que foi gerada pela equipe e que deve ser comparada com a saída esperada, +disponível no item <b>Problem</b>. Caso haja algum problema, eventualmente +pode ser possível visualizar o erro aqui.</li> +<li><b>Standard error</b>: links para fazer o download ou visualizar a saída de +erro padrão gerada pelo programa da equipe. Quando um problema acontece, por +exemplo um erro em tempo de execução por causa de um acesso ilegal, a informação +sobre o erro torna-se disponível nesta saída de erro. Além de sempre +analisar essa saída, o juiz deve estar atento à saída padrão, pois máquinas virtuais +como da linguagem Java podem escrever os erros na saída padrão e/ou na saída +de erro. Na saída de erro está ainda o resultado do diff feito entre o arquivo + esperado e o arquivo gerado pelo programa submetido. +</li> +</ol> + +<p>Utilizando o botão <b>Judge</b> o juiz faz o julgamento da <i>Run</i>, e após +isso não tem mais acesso para alterar seu julgamento. É possível ainda devolver +a <i>Run</i> para o <i>pool</i> de submissões a serem julgadas, utilizando o +botão <b>Cancel</b>.</p> + +<p>Na tela de <i>Runs</i>, o juiz visualiza todas as submissões, mesmo aquelas que +estão sendo julgadas por outros juízes. Tais submissões aparecem com a cor +azul. As submissões sendo julgados por ele próprio aparecem em vermelho, e somente +ele tem acesso para julgá-las (ou o admin, claro).</p> + +<p></p> +<p><font size="4"><b>Chief</b></font></p> +<p> +Além de poder atuar como um juiz <i>normal</i>, um juiz pode ser designado como <i>chief</i>. Nesta aba +o juiz chefe tem a opção de julgar <i>runs</i> que foram previamente julgadas mas obtiveram resultados +diferentes dos diferentes juízes. A tela é similar àquela do juiz normal, só que <i>runs</i> +julgadas aqui são dadas como resposta final ao time, sem a necessidade de intervenção de outro juiz. +Por esse motivo, é aconselhável que mesmo o juiz chefe, quando estiver julgando <i>runs</i> sem conflito, apenas +utilize a aba <i>Runs</i>, e deixe para utilizar esta aba apenas para resolver os casos de <i>runs</i> que foram julgadas de +forma diferente por diferente juízes. Além das informações da <i>run</i>, o juiz chefe possui +(ao clicar sobre a <i>run</i>) as resposta contraditórias que foram dados pelos juízes, de forma a desempatar +a questão e enviar a resposta mais adequada ao time. +</p> +<p></p> + +<p></p> +<p><font size="4"><b>Score</b></font></p> +<p>Nessa opção será mostrado o placar atualizado da competição. Vale a pena +lembrar que o placar disponível para os juízes é completo, e portanto +deve ser mantido em <b>sigilo até a divulgação dos resultados finais da competição</b> +(para manter o suspense :-). </p> + +<p><font size="4"><b>Clarifications</b></font></p> +<p>Essa opção permite que o juiz responda as <i>clarifications</i> enviadas +pelas equipes a cerca de um problema específico ou de algum aspecto geral da +prova. Para responder uma <i>clarification</i>, o juiz deve clicar sobre seu +número <b>Cuidado:</b> a caixa de texto disponível na parte inferior não é para +responder perguntas, mas para elaborar uma pergunta. Isso serve para que um juiz +crie uma pergunta, que então poderá ser respondida por ele mesmo (ou por outros +juízes) e enviada para todas as equipes, funcionando assim como uma forma de +aviso geral.</p> + +<p>Neste instante ele poderá visualizar informações sobre a <i>clarification</i>, +como número do site, número da <i>clarification</i>, tempo em minutos desde o +início da competição e problema sobre o qual +a pergunta está relacionada, além de duas caixas de texto: uma com a +pergunta e outra onde será preenchida a resposta. Se julgar relevante, o juiz +pode clicar nas seleções <b>answer to all users in the site</b> para que esta pergunta seja +respondida (enviada) para todas as equipes no site ou <b>answer to all users in all sites</b> +para que a resposta seja enviada para todas as equipes em todos os sites (no caso de +uma competição executada no BOCA em um único site, não há diferença entre estas seleções).</p> + +<p>O sistema também permite que o juiz utilize um botão chamado +<u><i>No response</i></u>. Isso ocorre +em geral porque a pergunta feita não deve ser respondida, pois sua resposta faz parte do +entendimento da questão ou da prova, ou já foi respondida anteriormente. +Por fim, existe um botão onde o juiz pode devolver a <i>clarification</i> para que +outro juiz a responda. +</p> + +<p><font size="4"><b>History</b></font></p> +<p>Ao entrar nessa opção, o juiz poderá visualizar as <i>Clarifications</i> e +<i>Runs</i> que foram respondidas/corrigidas até o momento. +Não é possível alterar nada, apenas visualizar.</p> + +<p><font size="4"><b>History</b></font></p> +<p>Nesta aba o juiz pode atuar como uma equipe, submetendo <i>runs</i> para serem julgadas. +O uso deste item se dá no momento de testar o sistema e o conjunto de problemas. Juízes +podem submeter <i>runs</i> mesmo antes de iniciada a competição. +</p> + +<p><font size="4"><b>Options</b></font></p> +<p>Entrando nessa opção poderão ser vistas as informações: <i>Username, +User</i> <i>full name </i>e<i> User description</i> do juiz.<i> </i>Também +será possível trocar a senha do juiz no BOCA digitando-se a senha antiga e a +nova (duas vezes). Para efetuar a troca da senha, basta preencher os campos +corretamente e clicar no botão <i>Send</i>. É importante ter uma senha +segura para um juiz.<br> + +</p> +<p><font size="4"><i><b>Logout</b></i></font></p> +<p>Essa opção permite sair do BOCA.</p> + +<p><font size="4"><b>Dicas importantes</b></font></p> +<p>Ao corrigir problemas, devemos tomar extremo cuidado. Ainda que seja possível +alterar a correção posteriormente (através do ambiente do administrador da competição), +isso implica que a equipe receberá uma resposta e, depois de certo tempo, outra. +Obviamente esse tipo de situação não é agradável.</p> +<p>Sempre que um dos juízes está corrigindo um problema pela primeira vez (ou ainda nas +demais vezes iniciais, isto é, até o momento foram feitas poucas submissões +desde problema), +é interessante que todos participem e tenham cuidados especiais, analisando a +submissão com calma. É possível que na primeira +submissão de um dado problema possamos descobrir um defeito no +sistema ou nos arquivos de entrada e saída (claro que torcemos para isso nunca aconteça :-). +</p> +<p>Para responder às <i>clarifications</i>, é necessário que o juiz tenha lido com +calma as questões e identifique se a pergunta é válida e deve ser respondida. Além disso, +é necessário considerar se a resposta deve ser enviada para todas as equipes ou apenas +para aquela que fez a pergunta. Perguntas típicas que não são respondidas são: +<i>Qual o tempo limite desse problema?</i>, <i>Dada essa entrada, qual a saída correta?</i>, +etc. Além disso, perguntas cujas respostas estão definidas nos enunciados normalmente +não são respondidas. +Caso haja uma dúvida sobre o que se deve responder, o juiz deve procurar o juiz-chefe +responsável pela prova. +</p> + +<p><font size="4"><b>Sobre o BOCA e este documento</b></font></p> +<p>O sistema BOCA foi criado por Cassio Polpo de Campos +e pode ser encontrado em +<a href="http://www.ime.usp.br/~cassio/boca/">http://www.ime.usp.br/~cassio/boca/</a>. +Este manual foi feito por Cassio Polpo de Campos.</p> + +<hr> +<p> +<a href="http://validator.w3.org/check?uri=referer"> +<img src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!" border="0" height="31" width="88"></a> + +</p></body></html> diff --git a/boca-1.5.0/doc/html/manualteam.en.html b/boca-1.5.0/doc/html/manualteam.en.html new file mode 100644 index 0000000..815eda0 --- /dev/null +++ b/boca-1.5.0/doc/html/manualteam.en.html @@ -0,0 +1,198 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> + +<head> +<meta http-equiv="content-type" content="text/html;charset=iso-8859-1"> +<title>BOCA Team's Manual</title> +</head> + +<body bgcolor="white" vlink="blue" link="blue"> +<font size="5"><b>BOCA Online Contest Administrator</b></font> +<p><b>Reference Manual for teams<font size="5"> - </font>version +October/2011 (BOCA version 1.4.1+)</b></p> + +<p><font size="1">Copyright (c) 2003-2010 Ulisses F. F. da Silva and Cassio +P. de Campos.<br> +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU Free Documentation License, Version 1.2 or any later +version published by the Free Software Foundation; with no Invariant Sections, +no Front-Cover Texts, and no Back-Cover Texts. A copy of the license may be +found in <a +href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a></font></p> + +<p>BOCA is a software for controlling a competition in the scope of the <i>ACM International +Collegiate Programming Contest</i>. It has been developed in PHP and the interaction between teams +and the system is performed using a <i>web browser</i>. In the following it is described +this interface and its main functions.</p> + +<p><u>It is important that teams tested the system during the <i>warmup session</i>, before +the official contest, so any issue can be addressed in time. The warmup has exactly this +purpose. It is expected that teams submit correct and incorrect runs, as long as they <b>do not</b> +try to perform malicious operations in the system. It is also expected that clarifications be +submitted, and a small file to print. +</u></p> + +<p>It is assumed here that the team has already logged in using the web browser and +the URL address provided to access the BOCA system. The URL varies from contest to contest, +so you have to ask the staff of your site about it. The login page contains the fields +username and password, which are provided by the staff of the contest. Usually the +username follows the format <b>teamX</b>, where <b>X</b> is the team number, but that is +not mandatory (again, check with the staff). If not speficied, the initial password is empty.</p> + +<p>After the successful login, a page opens with the team identification in the upper-left +corner, and the clock of the contest in the upper-right corner. During the contest, +as the team gets YESes as balloons appear besides the team name. +Just below this information, a vertical menu has the following options: +<i>Problems, Runs, Score, Clarifications, Tasks, Backups, Options e Logout.</i></p> + +<p><font size="4"><b>Problems</b></font></p> +<p>In this tab, the team sees the problems of the contest, together with the book of problem +descriptions (if available online). In <i>in-loco</i> contests, this tab is less important +given that a printed version of the booklet is distributed to the teams. Still, the column +named <b>Basename</b> provides to teams the name of the file that has to be used for each problem. +This is the name that has to be followed by the extension (depending on the language) and +also as the <u>name of the class containing the <i>public main</i> procedure</u> in Java. +Usually this information is also available in the booklet. Nevertheless, here the team can +check if their name is correct. +</p> + +<p><font size="4"><b>Runs</b></font></p> +<p>This tab represents the actual information about the team's submissions, as well as provides +the interface to submit new <i>runs</i>. It is important for the team to select the correct +problem, language, and to choose the correct file for the submission. <b>Note that the file name +must follow the specification</b> in the booklet, and which shall also be available in the tab <i>Problems</i>. +Hence, +<ol> + <li>Use in the source-code the filename defined in the column <b>Basename</b> of the tab <i>Problems</i>. + Take care with small typos and the proper extension according to the chosen language. + </li> + <li>Choose the correct language and problem. It is not uncommon to happen submissions with wrong filename, language or problem. + </li> + <li>Make sure your code reads the input from the <b>standard input</b> and writes the output to the + <b>standard output</b>. Avoid writing anything to the <b>standard error</b>. Furthermore, make your + program exit the code zero in the final return or exit(.) call. By default, this indicates that no + error has happened during its execution. + </li> +</ol> + +<p>In order to see the judgements of runs, the team must click on +the tab <i>Runs</i> and watch the list of submitted runs. +However, do not stop working while waiting for the answers. Even if the judges +are in the backstage working hard to reply to all submissions, this might take some time. +In the last part of the competition, the scoreboard is not updated, neither the runs are answered back +(the number of minutes from the end when this happens depends on the contest; usually it is something around +15 minutes, but this is informed by the staff). For each run, there is a set of standard answers that +exist in each contest (and they may vary depending on the contest). Still the common options are shown below: +<table border="1"> + <tr> + <td nowrap>Answer</td><td>Description</td> + </tr> + <tr> + <td nowrap>YES</td> + <td>Your code was properly compiled, run, and correctly generated the expected output for the problem.</td></tr> + <tr> + <td nowrap>NO: Wrong answer</td> + <td>Some times known as <i>Incorrect output</i>. It indicates that the code compiled and ran, however it + did not generated the expected output for the problem, given the input of the judges (which most certainly + is different from yours and is not available to you).</td> + </tr> + <tr> + <td nowrap>NO: Time-limit Exceeded</td> + <td>The code compiled properly but spent more than the maximum amount of time defined for the given problem. + This time-limit is defined by the judges for each problem and is not disclosed to the teams.</td> + </tr> + <tr> + <td nowrap>NO: Runtime Error</td> + <td>The code compiled properly but achieved an error during its run, given the input of the judges. Some examples + of runtime error are: illegal memory access (seg. fault), illegal file access, excess of memory usage, etc.</td> + </tr> + <tr><td nowrap>NO: Compilation Error</td> + <td>The code has not compiled properly in the judges' computers. Note that you are expected to have compiled in your + own computer before submitting the code. So check the compilation options and versions in your + computer, and if you do not have a problem compiling it locally, ask a member of the staff for help.</td> + </tr> + <tr> + <td nowrap>NO: presentation Error</td> + <td>Also known as <i>output format error</i>, it means that your code compiled, ran, and generated the + expected output apart from some minor presentation issue, such as upper/lower-cases, acents or punctuations (the + definition of presentation error may vary in each contest and is defined by the judges who created the test set).</td> + </tr> + <tr> + <td nowrap>NO: If possible, contact staff</td> + <td>This reply tells you to contact your local staff for help/asking about the issue, if at all possible.</td> + </tr> +</table> + +<p></p> +<p></p> +<p><font size="4"><b>Score</b></font></p> +<p>This tab shows the scoreboard of the contest. If running as a multi-site competition, the scoreboard might also +contain teams from other sites, which can be identified by the <b>/X</b> after the team name, where <b>X</b> is the +site number of the corresponding team. Note that the scoreboard is not updated during the last part of the competition. +This is indicated accordingly. +</p> + +<p><font size="4"><b>Clarifications</b></font></p> +<p>This tab can be used by the team to submit questions to the judges concerning the problems, their descriptions, +or any other aspect of the contest. If the question is specific to a problem of the test set, the team must select +the problem from the combo list. Otherwise, the option <i>General</i> is to be used. The text box is used to +write the question. It is also available in this tab all the replies to questions that were formulated by the +team, as well as questions formulated by other teams but that judges decided that the reply should be made +available to all the teams. Some facts:</p> + +<ol> + <li><b>Teams must make questions regarding the problems and test set using only this interface, and not directly + to the staff or judges.</b> + </li> + <li>It is the team's responsibility to check the tab about <i>clarifications</i> during the contest + to check for new replies. Judges may also send general clarifications to teams, and they will appear in this tab. + </li> +</ol> + +<p>BOCA allows judges to use a particular button named <u><i>No response</i></u>. If you receive this +reply it means that the question may not be answered by the judges, for instance because it is against +the rules to disclose such information, or because the judges understand that the +information asked is already available in the booklet of problem descriptions.</p> + +<p><font size="4"><b>Tasks</b></font></p> +<p>This tab allows the team to send files for printing, as well as ask for help from a staff member (using +the button <i>S.O.S.</i>. To print a file, just select it from the disk and click on <i>Send</i>. +The help provided by the <i>staff</i> has to be only related to issues with the computers or other +physical problem, while questions about the test set, problem descriptions, etc must be send to the +judges using the tab <i>Clarifications</i>.</p> + +<p><font size="4"><b>Backups</b></font></p> +<p>It is possible to send small files to BOCA in order to keep them safe in the server. This is +particularly useful if some drastic issue happens with your computer. This tab provides a way +for the teams to send and query back files that are stored in the server. Only very small files +are allowed, so it is recommended that you backup only plain text files (source code, inputs, etc) +and use a zip or tar.gz format to create a single file. +</p> +<br> + +<p><font size="4"><b>Options</b></font></p> +<p>This tab shows the information of the team, such as <i>Username, +User</i> <i>full name </i>,<i> User description</i>. It is possible +for the team to update their password, although this is not necessary neither +recommended. Instead it is recommended that the admin who created the users already +specifies secret and safe password for all users. +</p> +<br> + +</p> +<p><font size="4"><i><b>Logout</b></i></font></p> +<p>Button to log out from the team interface.</p> + +<p><font size="4"><b>About BOCA and this document</b></font></p> +<p>BOCA System and this document have been created by Cassio Polpo de Campos and can be found at +<a href="http://www.ime.usp.br/~cassio/boca/">http://www.ime.usp.br/~cassio/boca/</a>. +An initial version of this document was made by Ulisses Furquim Freire da Silva. +</p> + +<hr> +<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" +src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!" height="31" +width="88"></a> +</body> + +</html> diff --git a/boca-1.5.0/doc/html/manualteam.pt_br.html b/boca-1.5.0/doc/html/manualteam.pt_br.html new file mode 100644 index 0000000..efa3871 --- /dev/null +++ b/boca-1.5.0/doc/html/manualteam.pt_br.html @@ -0,0 +1,227 @@ +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> + +<head> +<meta http-equiv="content-type" content="text/html;charset=iso-8859-1"> +<title>Manual do BOCA para as equipes</title> +</head> + +<body bgcolor="white" vlink="blue" link="blue"> +<font size="5"><b>BOCA Online Contest Administrator - Sistema de Submissão</b></font> +<p><b>Manual de Referência para as equipes<font size="5"> - </font>versão +setembro/2010 (para o BOCA versão 1.4.x)</b></p> + +<p><font size="1">Copyright (c) 2003-2010 Ulisses F. F. da Silva and Cassio +P. de Campos.<br> +Permission is granted to copy, distribute and/or modify this document under +the terms of the GNU Free Documentation License, Version 1.2 or any later +version published by the Free Software Foundation; with no Invariant Sections, +no Front-Cover Texts, and no Back-Cover Texts. A copy of the license may be +found in <a +href="http://www.gnu.org/licenses/">http://www.gnu.org/licenses/</a></font></p> + +<p>O BOCA é um <i>software</i> criado para controlar uma competição nos moldes +da Maratona de Programação da SBC. Foi feito em PHP e a interação dos times +com o sistema é feita usando-se um <i>browser</i>. A seguir descrevemos a +interface disponível no BOCA para as equipes e suas principais funções.</p> + +<p><b>É interessante que todos os times testem essas opções durante a<i> +</i>sessão de aquecimento <i>(warmup)</i></b> <b>que antecede a competição. O +warmup tem exatamente esta função, e assim espera-se que cada equipe submeta +um problema correto, submeta um problema errado, faça perguntas aos juízes +através do sistema de <i>clarifications</i> e até submeta um arquivo pequeno +para impressão.</b></p> + +<p>Neste texto será assumido que o time já realizou o seu +<i>login</i> na máquina e abriu uma janela do navegador (leia +as instruções sobre o Maratona Linux ou sobre o sistema que +estiver sendo utilizado). O BOCA é acessado através de uma +<i>URL</i> (endereços comuns são +http://mainserver/boca/ ou http://bocaserver/boca/). Ao carregar a página, o time deverá ver a +tela de <i>login</i> do BOCA. Basta digitar o <i>login</i> do +BOCA fornecido ao time e a sua senha correspondente (usualmente +algo como <b>teamX</b>, onde <b>X</b> +deve ser substituído pelo número da equipe. A senha inicial é +vazia caso não escolhida diferentemente).</p> + +<p>Após realizar o <i>login</i> com sucesso, uma página deverá ser aberta +contendo a identificação do time no canto superior esquerdo. Durante a +competição, conforme o time acerta os problemas, pequenos balões coloridos +são apresentados próximos ao nome do time. +No canto superior +direito haverá a informação sobre o estado da competição: ou ainda não +começou, ou já acabou, ou está parada, ou a competição está em andamento e a +quantidade de minutos restantes será mostrada. Mais abaixo dessas primeiras +linhas estarão sete opções, que representam a interface propriamente dita do +BOCA. Estas sete opções são: <i>Problems, Runs, +Score, Clarifications, Tasks, Backups, Options e Logout.</i></p> + +<p><font size="4"><b>Problems</b></font></p> +<p>Ao entrar nessa opção, o time poderá visualizar as questões da prova. Para +cada questão, estará disponível um arquivo con sua descrição (muitas vezes +apenas um arquivo de descrição é dado, contendo todas as questões da prova). +Esta opção é normalmente utilizada para competições não-presenciais como forma de +distribuir a prova. Em competições presenciais, sua utilidade é reduzida. +Ainda nesta tela é possível visualizar as cores dos balões de cada problema.</p> + +<p><font size="4"><b>Runs</b></font></p> +<p>Ao entrar nessa opção, o time poderá submeter as suas soluções e receber as +respostas dos juízes. <b>Para submeter uma solução, o time deverá selecionar o +problema para o qual a solução foi feita, a linguagem utilizada e depois +carregar o arquivo contendo a solução.</b> Depois disso, basta clicar no botão +<i>Send</i> para enviar sua solução. O botão <i>Clear</i> permite apagar os +dados selecionados. Algumas observações importantes na hora de criar e +submeter uma solução:</p> + +<ol> + <li>Crie o seu arquivo-fonte contendo a solução de um problema com o <b>nome + indicado</b> <b>no enunciado.</b> Cuidado com pequenos erros no nome e em sua extensão. + </li> + <li>Escolha a <b>linguagem correta.</b> Note que seu fonte deverá ter a + extensão correspondente para cada uma das linguagens aceitas (veja a folha + de questões da prova). + </li> + <li>Lembre-se de que sua solução deve <b>ler os dados da entrada padrão e + escrever os</b> <b>resultados na saída padrão.</b> <b>Nada</b> deve ser + escrito <b>na saída padrão de erro.</b> Além disso, programas escritos em + linguagens que possibilitam o retorno de algum valor para o sistema + operacional devem retornar o valor 0 (zero), que por convenção indica que + nenhum problema ocorreu na execução. + </li> +</ol> + +<p>Para receber as respostas dos juízes, o time deverá clicar em <i>Runs</i> e +esperar que a lista contendo as respostas recebidas para cada solução +submetida seja atualizada (ainda assim, não perca tempo esperando. Você pode +produzir enquanto a resposta dos juízes não chega). Vale a pena lembrar que +nos <b>últimos minutos os times que submeterem</b> <b>soluções não receberão +mais as respostas dos juízes</b> +(assim o suspense fica melhor, não? :-). Esse prazo é informado na +competição. Cada competição tem seu conjunto de respostas possível que as +equipes podem receber. A seguir apresentamos apenas uma tabela exemplo com as +respostas tradicionais. <b>Verifique as especialidades da sua +competição</b>.</p> + +<table border="1"> + <tr> + <td nowrap>Resposta</td><td>Descrição</td> + </tr> + <tr> + <td nowrap>YES</td> + <td>Seu programa foi aceito, e você receberá um balão da cor correspondente ao problema.</td></tr> + <tr> + <td nowrap>NO: Incorrect Output</td> + <td>Também conhecido como <i>Wrong Answer</i>. Indica que seu programa + respondeu incorretamente a algum(ns) dos testes dos juízes.</td> + </tr> + <tr> + <td nowrap>NO: Time-limit Exceeded</td> + <td>A execução do seu programa excedeu o tempo permitido pelos + juízes. Esse limite de tempo usualmente não é divulgado aos times e pode variar + para cada problema.</td> + </tr> + <tr> + <td nowrap>NO: Runtime Error</td> + <td>Durante o teste ocorreu um erro de execução (causado pelo seu + programa) na máquina dos juízes. Acesso a posições irregulares de + memória ou estouro dos limites da máquina são os erros mais comuns.</td> + </tr> + <tr><td nowrap>NO: Compilation Error</td> + <td>Seu programa tem erros de sintaxe. Pode ser ainda que você errou o + nome do problema ou linguagem no momento da submissão.</td> + </tr> + <tr> + <td nowrap>NO: Output Format Error</td> + <td>Também conhecido como <i>Presentation Error</i>, indica que a saída + do seu programa não segue a especificação exigida na folha de + questões, apesar do "resultado" estar correto. Corrija para se + adequar à especificação do problema.</td> + </tr> + <tr> + <td nowrap>NO: Contact Staff</td> + <td>Você deve pedir a presença do pessoal de <i>staff</i>, pois algum + erro incomum aconteceu.</td> + </tr> +</table> + +<p></p> +<p></p> +<p><font size="4"><b>Score</b></font></p> +<p>Nessa opção será mostrado o placar atualizado da competição. Vale a pena +lembrar que <b>o placar será congelado antes do final da competição</b> +(suspense mantido :-). Esse prazo também é informado na competição, e o placar +quando estiver congelado mostra um aviso sobre seu estado.</p> + +<p><font size="4"><b>Clarifications</b></font></p> +<p>Essa opção permite que o time faça perguntas aos juízes a cerca de um +problema específico ou de algum aspecto geral da prova. O time deverá +selecionar o problema relacionado à sua pergunta ou selecionar <i>General</i>, +caso a pergunta não seja específica. Logo abaixo deverá ser escrito o texto da +<i>clarification</i>. Para enviar a <i>clarification</i> basta clicar no botão +<i>Send.</i> O botão <i>Clear</i> apaga os dados selecionados. Para visualizar +a resposta da <i>clarification</i>, o time deverá estar na opção +<i>Clarifications</i> e olhar na lista das <i>clarifications</i> submetidas se +a resposta já foi dada. Como já foi mencionado, uma lista contendo as +<i>clarifications</i> pertinentes a cada time será sempre mostrada nessa +opção. Algumas observações importantes sobre <i>clarifications</i>:</p> + +<ol> + <li><b>Os times devem fazer perguntas sobre a prova utilizando apenas essa + interface</b> <b>disponível no BOCA!</b> + </li> + <li>O time deverá ficar atento às <i>clarifications</i> durante toda a + prova, pois uma <i>clarification</i> feita por um time poderá ser respondida + para todos os outros. Os juízes também podem enviar clarifications a todos + os times se julgarem conveniente. Fiquem atentos. + </li> + <li>As respostas de clarifications não surgem na tela. Você deve consultar esta página para vê-las. + </li> +</ol> + +<p>O sistema permite que o juiz respondendo uma dúvida utilize um botão chamado <u><i>No response</i></u>. Isso ocorre +em geral porque a pergunta feita não deve ser respondida, pois sua resposta faz parte do +entendimento da questão ou da prova. Neste caso sugerimos ler com cuidado as questões e as +possíveis <i>clarifications</i> relacionadas.</p> + +<p><font size="4"><b>Tasks</b></font></p> +<p>Ao entrar nessa opção, o time poderá enviar arquivos para impressão. Para +isso o arquivo deve ser selecionado e então basta clicar no botão +<i>Send</i>. O botão <i>Clear</i> permite apagar os dados selecionados. Outra +opção neste item é o botão <i>S.O.S.</i> que pode ser usado para chamar a +ajuda do pessoal de <i>staff</i>. Essa ajuda deve estar relacionada apenas com +problemas do computador ou semelhantes, já que dúvidas sobre a prova devem ser +enviadas pelo sistema BOCA na opção <i>Clarifications</i>.</p> + +<p><font size="4"><b>Backups</b></font></p> +<p>No sistema BOCA é possível enviar pequenos arquivos para que sejam +guardados no servidor em case de uma interrupção do funcionamento do computador +do time. Entrando nessa opção poderão ser vistos os arquivos já enviados +e mantidos no servidor, assim como enviar novos arquivos. Note que existe um limite usualmente +pequeno na capacidade de armazenamento para que não hajam abusos. Um arquivo compactado é +geralmente a melhor forma de guardar dados no servidor.<br> + +<p><font size="4"><b>Options</b></font></p> +<p>Entrando nessa opção poderão ser vistas as informações: <i>Username, +User</i> <i>full name </i>e<i> User description</i> do time.<i> </i>Também +será possível trocar a senha do time no BOCA digitando-se a senha antiga e a +nova (duas vezes). Para efetuar a troca da senha, basta preencher os campos +corretamente e clicar no botão <i>Send</i>.<br> + +</p> +<p><font size="4"><i><b>Logout</b></i></font></p> +<p>Essa opção permite sair do BOCA.</p> + +<p><font size="4"><b>Sobre o BOCA e este documento</b></font></p> +<p>O sistema BOCA foi criado por Cassio Polpo de Campos +e pode ser encontrado em +<a href="http://www.ime.usp.br/~cassio/boca">http://www.ime.usp.br/~cassio/boca</a>. +Este manual, em sua versão inicial, foi feito por Ulisses Furquim Freire da Silva e +complementado e atualizado por Cassio Polpo de Campos.</p> + +<hr> +<p><a href="http://validator.w3.org/check?uri=referer"><img border="0" +src="http://www.w3.org/Icons/valid-html401" alt="Valid HTML 4.01!" height="31" +width="88"></a> +</body> + +</html> diff --git a/boca-1.5.0/doc/import-user.txt b/boca-1.5.0/doc/import-user.txt new file mode 100644 index 0000000..9656235 --- /dev/null +++ b/boca-1.5.0/doc/import-user.txt @@ -0,0 +1,105 @@ +import-user.txt +--------------- +Last modified 05/aug/2012 by cassio@ime.usp.br +See Copyright below. + +To simplify the input of user's data, it is +possible to put all information in a text +file, according to three different formats. Two +of them are based on the files generated from the +ICPC website system, usually in TAB separated format. +The third possible format follows the example below: + +************ users.txt: ************* +[user] +usernumber=2000 +usersitenumber=1 +username=cassio +userfullname=Cassio Polpo de Campos +usertype=admin + +usernumber=2001 +usersitenumber=1 +username=judge1 +usertype=judge +userfullname=First judge name +userenabled=f +usermultilogin=t +userip=10.0.0.5 + +usernumber=2002 +usersitenumber=1 +username=staff1 +usertype=staff +userfullname=Staff person name +userpassword=aBcDe + +usernumber=1 +usersitenumber=1 +userfullname=PUC-SP A +userip=192.168.0.1 +usericpcid=1234 + +usernumber=2 +usersitenumber=1 +userfullname=PUC-SP B +userip=192.168.0.2 +usericpcid=1111 + +usernumber=3 +usersitenumber=1 +userfullname=IME-USP C +userip=192.168.0.3 + +************************************** +Note that the "****" lines should not +be included in the text file. + +The users are defined per block of lines. +Blank lines separate the definitions of the +users. The parameters not specified for a +given user inside its block are set to +the default values. + +The parameters in the user's file are: +usernumber: number of the user in the site +usersitenumber: number of the user's site +username: nickname of the user. If not + specified, it's generated from + the usernumber, ie, "team"+usernumber +userfullname: institution name and team name or + just the user name. +userdesc: detailed description about the user. +usertype: type of the user. If not specified, + it's set to "team". +userpassword: if not specified, it's left emtpy. +userenabled: if not specified, the user is enabled. +usericpcid: ID of user in the ICPC system. Not required. +usermultilogin: if not specified, the user cannot + make simultaneous logins form distinct IPs. +userip: from which IP number the user may connect. A list + of IPs separated by comma may be specified. IPs may + have netmasks, such as 10.0.0.0/16, or negations, + such as !143.107.0.0/16. + +Contacts and Copyrights +----------------------- +BOCA Copyright (c) 2003- Cassio Polpo de Campos (cassio@ime.usp.br) +http://www.ime.usp.br/~cassio/boca + +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// diff --git a/boca-1.5.0/doc/problemtemplate/compare/c b/boca-1.5.0/doc/problemtemplate/compare/c new file mode 100755 index 0000000..4998be3 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/compare/c @@ -0,0 +1,97 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 21/jul/2012 by cassio@ime.usp.br +# +# This script receives: +# $1 team_output +# $2 sol_output +# $3 problem_input (might be used by some specific checkers, here it is not) +# +# BOCA reads the last line of the standard output +# and pass it to judges +# +if [ ! -r "$1" -o ! -r "$2" ]; then + echo "Parameter problem" + exit 43 +fi + +# Next lines of this script just compares team_output and sol_output, +# although it is possible to change them to more complex evaluations. + +diff -q "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff \"$1\" \"$2\" # files match" + echo "Files match exactly" + exit 4 +fi +diff -q -b "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b \"$1\" \"$2\" # files match" + echo -e "diff -c \"$1\" \"$2\" # files dont match - see output" + diff -c "$1" "$2" + echo "Files match with differences in the amount of white spaces" + exit 5 +fi +diff -q -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b \"$1\" \"$2\" # files dont match - see output" + diff -c -b "$1" "$2" + echo "Files match with differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -i -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B "$1" "$2" + echo "Files match if we ignore case and differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B "$1" "$2" + echo "Files match if we discard all white spaces" + exit 5 +fi +diff -q -i -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B -w "$1" "$2" + echo "Files match if we ignore case and discard all white spaces" + exit 5 +fi +wd=`which wdiff` +if [ "$wd" != "" ]; then + wdiff \"$1\" \"$2\" >/dev/null 2>/dev/null + if [ "$?" == "0" ]; then + echo -e "wdiff \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B -w "$1" "$2" + echo "BUT Files match if we compare word by word, ignoring everything else, using wdiff" + echo "diff has a bug that, if a line contains a single space, this is not discarded by -w" + exit 5 + fi +fi +echo -e "### files dont match - see output" +diff -c -i -b -B -w "$1" "$2" +echo "Differences found" +exit 6 diff --git a/boca-1.5.0/doc/problemtemplate/compare/cpp b/boca-1.5.0/doc/problemtemplate/compare/cpp new file mode 100755 index 0000000..4998be3 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/compare/cpp @@ -0,0 +1,97 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 21/jul/2012 by cassio@ime.usp.br +# +# This script receives: +# $1 team_output +# $2 sol_output +# $3 problem_input (might be used by some specific checkers, here it is not) +# +# BOCA reads the last line of the standard output +# and pass it to judges +# +if [ ! -r "$1" -o ! -r "$2" ]; then + echo "Parameter problem" + exit 43 +fi + +# Next lines of this script just compares team_output and sol_output, +# although it is possible to change them to more complex evaluations. + +diff -q "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff \"$1\" \"$2\" # files match" + echo "Files match exactly" + exit 4 +fi +diff -q -b "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b \"$1\" \"$2\" # files match" + echo -e "diff -c \"$1\" \"$2\" # files dont match - see output" + diff -c "$1" "$2" + echo "Files match with differences in the amount of white spaces" + exit 5 +fi +diff -q -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b \"$1\" \"$2\" # files dont match - see output" + diff -c -b "$1" "$2" + echo "Files match with differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -i -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B "$1" "$2" + echo "Files match if we ignore case and differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B "$1" "$2" + echo "Files match if we discard all white spaces" + exit 5 +fi +diff -q -i -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B -w "$1" "$2" + echo "Files match if we ignore case and discard all white spaces" + exit 5 +fi +wd=`which wdiff` +if [ "$wd" != "" ]; then + wdiff \"$1\" \"$2\" >/dev/null 2>/dev/null + if [ "$?" == "0" ]; then + echo -e "wdiff \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B -w "$1" "$2" + echo "BUT Files match if we compare word by word, ignoring everything else, using wdiff" + echo "diff has a bug that, if a line contains a single space, this is not discarded by -w" + exit 5 + fi +fi +echo -e "### files dont match - see output" +diff -c -i -b -B -w "$1" "$2" +echo "Differences found" +exit 6 diff --git a/boca-1.5.0/doc/problemtemplate/compare/java b/boca-1.5.0/doc/problemtemplate/compare/java new file mode 100755 index 0000000..4998be3 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/compare/java @@ -0,0 +1,97 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 21/jul/2012 by cassio@ime.usp.br +# +# This script receives: +# $1 team_output +# $2 sol_output +# $3 problem_input (might be used by some specific checkers, here it is not) +# +# BOCA reads the last line of the standard output +# and pass it to judges +# +if [ ! -r "$1" -o ! -r "$2" ]; then + echo "Parameter problem" + exit 43 +fi + +# Next lines of this script just compares team_output and sol_output, +# although it is possible to change them to more complex evaluations. + +diff -q "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff \"$1\" \"$2\" # files match" + echo "Files match exactly" + exit 4 +fi +diff -q -b "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b \"$1\" \"$2\" # files match" + echo -e "diff -c \"$1\" \"$2\" # files dont match - see output" + diff -c "$1" "$2" + echo "Files match with differences in the amount of white spaces" + exit 5 +fi +diff -q -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b \"$1\" \"$2\" # files dont match - see output" + diff -c -b "$1" "$2" + echo "Files match with differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -i -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B "$1" "$2" + echo "Files match if we ignore case and differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B "$1" "$2" + echo "Files match if we discard all white spaces" + exit 5 +fi +diff -q -i -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B -w "$1" "$2" + echo "Files match if we ignore case and discard all white spaces" + exit 5 +fi +wd=`which wdiff` +if [ "$wd" != "" ]; then + wdiff \"$1\" \"$2\" >/dev/null 2>/dev/null + if [ "$?" == "0" ]; then + echo -e "wdiff \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B -w "$1" "$2" + echo "BUT Files match if we compare word by word, ignoring everything else, using wdiff" + echo "diff has a bug that, if a line contains a single space, this is not discarded by -w" + exit 5 + fi +fi +echo -e "### files dont match - see output" +diff -c -i -b -B -w "$1" "$2" +echo "Differences found" +exit 6 diff --git a/boca-1.5.0/doc/problemtemplate/compile/c b/boca-1.5.0/doc/problemtemplate/compile/c new file mode 100644 index 0000000..04a08e9 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/compile/c @@ -0,0 +1,159 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA System (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +#Last modified: 21/july/2012 by cassio@ime.usp.br +# +# parameters are: +# $1 source_file +# $2 exe_file (default run.exe) +# $3 timelimit (optional, limit to run all the repetitions, by default only one repetition) +# $4 maximum allowed memory (in MBytes) +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened (according to safeexec): +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 + +if [ "$1" == "" ]; then + echo "parameter problem" + exit 43 +fi +if [ ! -r "$1" ]; then + echo "$1 not found or it's not readable" + exit 44 +fi +name="$1" +if [ ! -r "$1" ]; then + echo "$1 not found or it's not readable" + exit 44 +fi +mkdir -p src +if [ "${name##*.}" == "zip" -a "${name##*.}" == "ZIP" ]; then + unzip "$name" -d src + name="*.c" +else + mv $name src +fi +id -u bocajail >/dev/null 2>/dev/null +if [ $? == 0 ]; then + bocau=`id -u bocajail` + bocag=`id -g bocajail` + chown bocajail.nogroup . +else + bocau=`id -u nobody` + bocag=`id -g nobody` + chown nobody.nogroup . +fi +if [ "$bocau" == "" -o "$bocag" == "" ]; then + echo "error finding user to run script" + exit 43 +fi + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec +if [ ! -x $sf ]; then + echo "$sf not found or it's not executable" + exit 46 +fi +maxm=512000 +if [ "$4" != "" -a "$4" -gt "0" ]; then +maxm=${4}000 +fi + +# setting up the timelimit according to the problem +if [ "$3" == "" ]; then +time=5 +else +time=$3 +fi +let ttime=$time+30 + +if [ "$2" == "" ]; then + exe=run.exe +else + exe=$2 +fi + +rm -f ../$exe 2>/dev/null +cat <<EOF > compileit.sh +#!/bin/bash +cc=\`which gcc\` +[ -x "\$cc" ] || cc=/usr/bin/gcc +if [ ! -x "\$cc" ]; then + echo "\$cc not found or it's not executable" + exit 47 +fi +cd src +"\$cc" -static -O2 -lm -o ../$exe "$name" +echo \$? > compileit.retcode +exit 0 +EOF +chmod 755 compileit.sh + +cdir=`pwd` +echo "Current directory is $cdir" >&2 +echo $cdir | grep -q "/bocajail" +if [ $? == 0 ]; then + cdir=`echo $cdir | sed "s/.*\/bocajail//"` + cat <<EOF > runit.sh +#!/bin/bash +[ -f /proc/cpuinfo ] || /bin/mount -t proc proc /proc +#/bin/mount --bind /dev /dev +[ -d /sys/kernel ] || /bin/mount -t sysfs sysfs /sys +$sf -r1 -F1000 -n0 -U$bocau -G$bocag -C. -ostdout0 -estderr0 -d$maxm -m$maxm -f20000 -t$ttime -T$ttime ./compileit.sh +echo \$? > runit.retcode +/bin/umount /proc 2>/dev/null +#/bin/umount /dev +/bin/umount /sys 2>/dev/null +EOF + chmod 755 runit.sh + chroot /bocajail "$cdir/runit.sh" + ret=`cat runit.retcode` +else + echo "COMPILATION IS NOT BEING CHROOTED -- THIS IS NOT AN IDEAL SETTING" + $sf -r1 -F1000 -n0 -U$bocau -G$bocag -C. -ostdout0 -estderr0 -d$maxm -m$maxm -f20000 -t$ttime -T$ttime ./compileit.sh + ret=$? +fi +rm -rf src/ +if [ -f stdout0 ]; then + cat stdout0 +fi +if [ "$ret" != "0" ]; then + echo "Compilation Error: $ret" + exit $ret +fi +ret=`cat compileit.retcode` +if [ "$ret" != "0" ]; then + echo "Compilation Error: $ret" + ret=1 +fi +exit $ret diff --git a/boca-1.5.0/doc/problemtemplate/compile/cpp b/boca-1.5.0/doc/problemtemplate/compile/cpp new file mode 100644 index 0000000..2ec55ac --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/compile/cpp @@ -0,0 +1,159 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA System (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +#Last modified: 21/july/2012 by cassio@ime.usp.br +# +# parameters are: +# $1 source_file +# $2 exe_file (default run.exe) +# $3 timelimit (optional, limit to run all the repetitions, by default only one repetition) +# $4 maximum allowed memory (in MBytes) +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened (according to safeexec): +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 + +if [ "$1" == "" ]; then + echo "parameter problem" + exit 43 +fi +if [ ! -r "$1" ]; then + echo "$1 not found or it's not readable" + exit 44 +fi +name="$1" +if [ ! -r "$1" ]; then + echo "$1 not found or it's not readable" + exit 44 +fi +mkdir -p src +if [ "${name##*.}" == "zip" -a "${name##*.}" == "ZIP" ]; then + unzip "$name" -d src + name="*.c" +else + mv $name src +fi +id -u bocajail >/dev/null 2>/dev/null +if [ $? == 0 ]; then + bocau=`id -u bocajail` + bocag=`id -g bocajail` + chown bocajail.nogroup . +else + bocau=`id -u nobody` + bocag=`id -g nobody` + chown nobody.nogroup . +fi +if [ "$bocau" == "" -o "$bocag" == "" ]; then + echo "error finding user to run script" + exit 43 +fi + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec +if [ ! -x $sf ]; then + echo "$sf not found or it's not executable" + exit 46 +fi +maxm=512000 +if [ "$4" != "" -a "$4" -gt "0" ]; then +maxm=${4}000 +fi + +# setting up the timelimit according to the problem +if [ "$3" == "" ]; then +time=5 +else +time=$3 +fi +let ttime=$time+30 + +if [ "$2" == "" ]; then + exe=run.exe +else + exe=$2 +fi + +rm -f ../$exe 2>/dev/null +cat <<EOF > compileit.sh +#!/bin/bash +cc=\`which g++\` +[ -x "\$cc" ] || cc=/usr/bin/g++ +if [ ! -x "\$cc" ]; then + echo "\$cc not found or it's not executable" + exit 47 +fi +cd src +"\$cc" -static -O2 -lm -o ../$exe "$name" +echo \$? > compileit.retcode +exit 0 +EOF +chmod 755 compileit.sh + +cdir=`pwd` +echo "Current directory is $cdir" >&2 +echo $cdir | grep -q "/bocajail" +if [ $? == 0 ]; then + cdir=`echo $cdir | sed "s/.*\/bocajail//"` + cat <<EOF > runit.sh +#!/bin/bash +[ -f /proc/cpuinfo ] || /bin/mount -t proc proc /proc +#/bin/mount --bind /dev /dev +[ -d /sys/kernel ] || /bin/mount -t sysfs sysfs /sys +$sf -r1 -F1000 -n0 -U$bocau -G$bocag -C. -ostdout0 -estderr0 -d$maxm -m$maxm -f20000 -t$ttime -T$ttime ./compileit.sh +echo \$? > runit.retcode +/bin/umount /proc 2>/dev/null +#/bin/umount /dev +/bin/umount /sys 2>/dev/null +EOF + chmod 755 runit.sh + chroot /bocajail "$cdir/runit.sh" + ret=`cat runit.retcode` +else + echo "COMPILATION IS NOT BEING CHROOTED -- THIS IS NOT AN IDEAL SETTING" + $sf -r1 -F1000 -n0 -U$bocau -G$bocag -C. -ostdout0 -estderr0 -d$maxm -m$maxm -f20000 -t$ttime -T$ttime ./compileit.sh + ret=$? +fi +rm -rf src/ +if [ -f stdout0 ]; then + cat stdout0 +fi +if [ "$ret" != "0" ]; then + echo "Compilation Error: $ret" + exit $ret +fi +ret=`cat compileit.retcode` +if [ "$ret" != "0" ]; then + echo "Compilation Error: $ret" + ret=1 +fi +exit $ret diff --git a/boca-1.5.0/doc/problemtemplate/compile/java b/boca-1.5.0/doc/problemtemplate/compile/java new file mode 100644 index 0000000..dae050e --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/compile/java @@ -0,0 +1,176 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA System (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +#Last modified: 21/july/2012 by cassio@ime.usp.br +# +# parameters are: +# $1 source_file +# $2 exe_file (default run.jar) +# $3 timelimit (optional, limit to run all the repetitions, by default only one repetition) +# $4 maximum allowed memory (in MBytes) +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened (according to safeexec): +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 +if [ "$1" == "" ]; then + echo "parameter problem" + exit 43 +fi +name="$1" +if [ ! -r "$1" ]; then + echo "$1 not found or it's not readable" + exit 44 +fi +mkdir -p src +if [ "${name##*.}" == "zip" -a "${name##*.}" == "ZIP" ]; then + unzip "$name" -d src + if [ "${name##*.}" == "zip" ]; then + name=`basename $name .zip` + else + name=`basename $name .ZIP` + fi +else + mv $name src +fi + +id -u bocajail >/dev/null 2>/dev/null +if [ $? == 0 ]; then + bocau=`id -u bocajail` + bocag=`id -g bocajail` + chown bocajail.nogroup . +else + bocau=`id -u nobody` + bocag=`id -g nobody` + chown nobody.nogroup . +fi +if [ "$bocau" == "" -o "$bocag" == "" ]; then + echo "error finding user to run script" + exit 43 +fi + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec +if [ ! -x $sf ]; then + echo "$sf not found or it's not executable" + exit 46 +fi + +time=$4 +if [ "$time" -gt "0" ]; then + let "ttime = $time + 30" +else + time=1 + ttime=30 +fi + +maxm=512 +if [ "$4" != "" -a "$4" -gt "0" ]; then +maxm=$4 +fi + +if [ "$2" == "" ]; then + jarfile=run.jar +else + jarfile=$2 +fi + +cdir=`pwd` +echo "Current directory is $cdir" >&2 + +cat <<EOF > compileit.sh +#!/bin/bash +javac=`which javac` +[ -x "\$javac" ] || javac=/usr/bin/javac +if [ ! -x \$javac ]; then + echo "\$javac not found or it's not executable" + exit 47 +fi +jar=`which jar` +[ -x "\$jar" ] || jar=/usr/bin/jar +if [ ! -x \$jar ]; then + echo "\$jar not found or it's not executable" + exit 47 +fi +export CLASSPATH=.:\$CLASSPATH +cd src +if [ -r "$name" ]; then + \$javac -Xmx${maxm}M -Xms${maxm}M "$name" + echo \$? > compileit.retcode +fi +find . -name "*.java" | while read lin; do + \$javac -Xmx${maxm}M -Xms${maxm}M "\$lin" + echo \$? > compileit.retcode +done +rm -f ../$jarfile +\$jar cvf ../$jarfile * +EOF +chmod 755 compileit.sh + +echo $cdir | grep -q "/bocajail" +if [ $? == 0 ]; then + cdir=`echo $cdir | sed "s/.*\/bocajail//"` + cat <<EOF > runit.sh +#!/bin/bash +[ -f /proc/cpuinfo ] || /bin/mount -t proc proc /proc +#/bin/mount --bind /dev /dev +[ -d /sys/kernel ] || /bin/mount -t sysfs sysfs /sys + +$sf -r1 -t$time -T$ttime -F256 -u256 -ostdout0 -estderr0 -U$bocau -G$bocag -n0 -C. -f20000 -d20000000 -m20000000 ./compileit.sh + +/bin/umount /proc 2>/dev/null +#/bin/umount /dev +/bin/umount /sys 2>/dev/null +EOF + chmod 755 runit.sh + chroot /bocajail "$cdir/runit.sh" + ret=`cat runit.retcode` +else + echo "COMPILATION IS NOT BEING CHROOTED -- THIS IS NOT AN IDEAL SETTING" +# $javac "$name" + $sf -r1 -t$time -T$ttime -F256 -u256 -U$bocau -G$bocag -ostdout0 -estderr0 -n0 -C. -d20000000 -m20000000 ./compileit.sh + ret=$? +fi +rm -rf src/ +if [ -f stdout0 ]; then + cat stdout0 +fi +if [ "$ret" != "0" ]; then + echo "Compilation Error: $ret" + exit $ret +fi +ret=`cat compileit.retcode` +if [ "$ret" != "0" ]; then + echo "Compilation Error: $ret" + ret=1 +fi +exit $ret diff --git a/boca-1.5.0/doc/problemtemplate/description/bits.txt b/boca-1.5.0/doc/problemtemplate/description/bits.txt new file mode 100644 index 0000000..4cd89f0 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/description/bits.txt @@ -0,0 +1 @@ +THIS IS THE FILE DESCRIBING THE PROBLEM! IT CAN BE A PDF OR ANY OTHER FORMAT... diff --git a/boca-1.5.0/doc/problemtemplate/description/problem.info b/boca-1.5.0/doc/problemtemplate/description/problem.info new file mode 100644 index 0000000..e1bc487 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/description/problem.info @@ -0,0 +1,3 @@ +basename=bits +fullname=The Problem of bits +descfile=bits.txt diff --git a/boca-1.5.0/doc/problemtemplate/input/bits b/boca-1.5.0/doc/problemtemplate/input/bits new file mode 100644 index 0000000..ef548be --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/input/bits @@ -0,0 +1,9 @@ +1 7 +4 1 10 20 30 +2 2000 999 +3 0 0 0 +2 1 1000 +1000 1073741824 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 +1 8 +0 diff --git a/boca-1.5.0/doc/problemtemplate/limits/c b/boca-1.5.0/doc/problemtemplate/limits/c new file mode 100644 index 0000000..b48a3b7 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/limits/c @@ -0,0 +1,13 @@ +#!/bin/bash +# this executable shall output the number of second of timelimit in the first line, for the given problem and with language according to this filename +echo 4 +# and the number of repetitions to run within the given timelimit in the second line +echo 10 +# and the maximum amount of memory per repetition in the third line (in Mbytes) +echo 512 +# and shall return zero to indicate no failure +exit 0 +# the idea is that this file will be executed by the autojudge in the first time the autojudge downloads a problem, so as it will be +# able to decide the proper time limit for the machine where it is running. If one wants to fix a predefined time limit, then it is +# enough to write a script like this one with the desired value. Otherwise, one can build any more sophisticated program that outputs +# the value. diff --git a/boca-1.5.0/doc/problemtemplate/limits/cpp b/boca-1.5.0/doc/problemtemplate/limits/cpp new file mode 100644 index 0000000..b48a3b7 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/limits/cpp @@ -0,0 +1,13 @@ +#!/bin/bash +# this executable shall output the number of second of timelimit in the first line, for the given problem and with language according to this filename +echo 4 +# and the number of repetitions to run within the given timelimit in the second line +echo 10 +# and the maximum amount of memory per repetition in the third line (in Mbytes) +echo 512 +# and shall return zero to indicate no failure +exit 0 +# the idea is that this file will be executed by the autojudge in the first time the autojudge downloads a problem, so as it will be +# able to decide the proper time limit for the machine where it is running. If one wants to fix a predefined time limit, then it is +# enough to write a script like this one with the desired value. Otherwise, one can build any more sophisticated program that outputs +# the value. diff --git a/boca-1.5.0/doc/problemtemplate/limits/java b/boca-1.5.0/doc/problemtemplate/limits/java new file mode 100644 index 0000000..b48a3b7 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/limits/java @@ -0,0 +1,13 @@ +#!/bin/bash +# this executable shall output the number of second of timelimit in the first line, for the given problem and with language according to this filename +echo 4 +# and the number of repetitions to run within the given timelimit in the second line +echo 10 +# and the maximum amount of memory per repetition in the third line (in Mbytes) +echo 512 +# and shall return zero to indicate no failure +exit 0 +# the idea is that this file will be executed by the autojudge in the first time the autojudge downloads a problem, so as it will be +# able to decide the proper time limit for the machine where it is running. If one wants to fix a predefined time limit, then it is +# enough to write a script like this one with the desired value. Otherwise, one can build any more sophisticated program that outputs +# the value. diff --git a/boca-1.5.0/doc/problemtemplate/output/bits b/boca-1.5.0/doc/problemtemplate/output/bits new file mode 100644 index 0000000..7749442 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/output/bits @@ -0,0 +1,24 @@ +Instancia 1 +3 + +Instancia 2 +20 + +Instancia 3 +22 + +Instancia 4 +3 + +Instancia 5 +20 + +Instancia 6 +31000 + +Instancia 7 +1 + +Instancia 8 +4 + diff --git a/boca-1.5.0/doc/problemtemplate/run/c b/boca-1.5.0/doc/problemtemplate/run/c new file mode 100755 index 0000000..d65ed58 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/run/c @@ -0,0 +1,124 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA System (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +#Last modified: 21/july/2012 by cassio@ime.usp.br +# +# parameters are: +# $1 exe_file +# $2 input_file +# $3 timelimit (limit to run all the repetitions, by default only one repetition) +# $4 number_of_repetitions_to_run (optional, can be used for better tuning the timelimit) +# $5 maximum allowed memory (in KBytes) +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened (according to safeexec): +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 +id -u bocajail >/dev/null 2>/dev/null +if [ $? == 0 ]; then + bocau=`id -u bocajail` + bocag=`id -g bocajail` + chown bocajail.nogroup . +else + bocau=`id -u nobody` + bocag=`id -g nobody` + chown nobody.nogroup . +fi +if [ "$bocau" == "" -o "$bocag" == "" ]; then + echo "error finding user to run script" + exit 43 +fi + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then + echo "parameter problem" + exit 43 +fi +name=`basename "$1"` +if [ ! -x "$name" ]; then + echo "$1 not found (or is not in the current dir) or it's not executable" + exit 44 +fi +if [ "${name##*.}" != "exe" -a "${name##*.}" != "EXE" ]; then + echo "WARNING: executable file extension is not .exe" +fi +input=`basename "$2"` +if [ ! -r "$input" ]; then + echo "$2 not found (or is not in the current dir) or it's not readable" + exit 45 +fi +if [ ! -x $sf ]; then + echo "$sf not found or it's not executable" + exit 46 +fi + +time=$3 +if [ "$time" -gt "0" ]; then + let "ttime = $time + 30" +else + time=1 + ttime=30 +fi + +nruns=1 +if [ "$4" != "" -a "$4" -gt "0" ]; then +nruns=$4 +fi +maxm=512000 +if [ "$5" != "" -a "$5" -gt "0" ]; then +maxm=${5}000 +fi + +rm -f stdin0 2>/dev/null +mv "$input" stdin0 + +rm -f run.exe 2>/dev/null +mv "$name" run.exe +file run.exe | grep -iq "statically linked" +if [ "$?" != "0" ]; then + echo "Aborting because $name is not statically linked" + exit 47 +fi + +cdir=`pwd` +echo "Current directory is $cdir -- chrooting on it" >&2 +$sf -F10 -r$nruns -n1 -R$cdir -C. -U$bocau -G$bocag -ostdout0 -estderr0 -d$maxm -m$maxm -t$time -T$ttime -istdin0 ./run.exe +ret=$? +if [ $ret -gt 10 ]; then + ret=0 +fi +if [ -f stdout0 ]; then + cat stdout0 +fi +exit $ret diff --git a/boca-1.5.0/doc/problemtemplate/run/cpp b/boca-1.5.0/doc/problemtemplate/run/cpp new file mode 100755 index 0000000..9b2d092 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/run/cpp @@ -0,0 +1,123 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA System (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +#Last modified: 21/july/2012 by cassio@ime.usp.br +# +# parameters are: +# $1 exe_file +# $2 input_file +# $3 timelimit (limit to run all the repetitions, by default only one repetition) +# $4 number_of_repetitions_to_run (optional, can be used for better tuning the timelimit) +# $5 maximum allowed memory (in KBytes) +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened (according to safeexec): +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 +id -u bocajail >/dev/null 2>/dev/null +if [ $? == 0 ]; then + bocau=`id -u bocajail` + bocag=`id -g bocajail` + chown bocajail.nogroup . +else + bocau=`id -u nobody` + bocag=`id -g nobody` + chown nobody.nogroup . +fi +if [ "$bocau" == "" -o "$bocag" == "" ]; then + echo "error finding user to run script" + exit 43 +fi + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then + echo "parameter problem" + exit 43 +fi +if [ ! -x "$1" ]; then + echo "$1 not found or it's not executable" + exit 44 +fi +name="$1" +if [ "${name##*.}" != "exe" -a "${name##*.}" != "EXE" ]; then + echo "WARNING: executable file extension is not .exe" +fi +if [ ! -r "$2" ]; then + echo "$2 not found or it's not readable" + exit 45 +fi +if [ ! -x $sf ]; then + echo "$sf not found or it's not executable" + exit 46 +fi + +time=$3 +if [ "$time" -gt "0" ]; then + let "ttime = $time + 30" +else + time=1 + ttime=30 +fi + +nruns=1 +if [ "$4" != "" -a "$4" -gt "0" ]; then +nruns=$4 +fi +maxm=512000 +if [ "$5" != "" -a "$5" -gt "0" ]; then +maxm=${5}000 +fi + +rm -f stdin0 2>/dev/null +mv "$2" stdin0 + +rm -f run.exe 2>/dev/null +mv "$name" run.exe +file run.exe | grep -iq "statically linked" +if [ "$?" != "0" ]; then + echo "Aborting because $name is not statically linked" + exit 47 +fi + +cdir=`pwd` +echo "Current directory is $cdir -- chrooting on it" >&2 +$sf -F10 -r$nruns -n1 -R$cdir -C. -U$bocau -G$bocag -ostdout0 -estderr0 -d$maxm -m$maxm -t$time -T$ttime -istdin0 ./run.exe +ret=$? +if [ $ret -gt 10 ]; then + ret=0 +fi +if [ -f stdout0 ]; then + cat stdout0 +fi +exit $ret diff --git a/boca-1.5.0/doc/problemtemplate/run/java b/boca-1.5.0/doc/problemtemplate/run/java new file mode 100755 index 0000000..945f15d --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/run/java @@ -0,0 +1,163 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA System (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +#Last modified: 21/july/2012 by cassio@ime.usp.br +# +# parameters are: +# $1 main_class +# $2 input_file +# $3 timelimit (limit to run all the repetitions, by default only one repetition) +# $4 number_of_repetitions_to_run (optional, can be used for better tuning the timelimit) +# $5 maximum allowed memory (in KBytes) +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened (according to safeexec): +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 +id -u bocajail >/dev/null 2>/dev/null +if [ $? == 0 ]; then + bocau=`id -u bocajail` + bocag=`id -g bocajail` + chown bocajail.nogroup . +else + bocau=`id -u nobody` + bocag=`id -g nobody` + chown nobody.nogroup . +fi +if [ "$bocau" == "" -o "$bocag" == "" ]; then + echo "error finding user to run script" + exit 43 +fi + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then + echo "parameter problem" + exit 43 +fi +if [ ! -r run.jar ]; then + echo "ERROR: file run.jar not found - possible error during compilation" + exit 1 +fi +name="$1" +if [ "${name##*.}" == "class" -a "${name##*.}" == "CLASS" ]; then + echo "WARNING: removing .class file extension" +fi +if [ "${name##*.}" == "class" ]; then + name=`basename "$1" .class` +fi +if [ "${name##*.}" == "CLASS" ]; then + name=`basename "$1" .CLASS` +fi +input=`basename "$2"` +if [ ! -r "$input" ]; then + echo "$2 not found (or is not in the current dir) or it's not readable" + exit 45 +fi +if [ ! -x $sf ]; then + echo "$sf not found or it's not executable" + exit 46 +fi + +time=$3 +if [ "$time" -gt "0" ]; then + let "ttime = $time + 30" +else + time=1 + ttime=30 +fi + +nruns=1 +if [ "$4" != "" -a "$4" -gt "0" ]; then +nruns=$4 +fi +maxm=512 +if [ "$5" != "" -a "$5" -gt "0" ]; then +maxm=${5} +fi + +rm -f stdin0 2>/dev/null +mv "$input" stdin0 + +cdir=`pwd` +echo "Current directory is $cdir" >&2 +echo $cdir | grep -q "/bocajail" +if [ $? == 0 ]; then + cdir=`echo $cdir | sed "s/.*\/bocajail//"` + cat <<EOF > runit.sh +#!/bin/bash +[ -f /proc/cpuinfo ] || /bin/mount -t proc proc /proc +#/bin/mount --bind /dev /dev +[ -d /sys/kernel ] || /bin/mount -t sysfs sysfs /sys +java=`which java` +[ -x "$java" ] || java=/usr/bin/java +if [ ! -x $java ]; then + echo "$java not found or it's not executable" + exit 47 +fi +export CLASSPATH=.:./run.jar:$CLASSPATH +cd $cdir +$sf -r$nruns -t$time -T$ttime -istdin0 -F256 -u256 -ostdout0 -estderr0 -U$bocau -G$bocag -n0 -C. -f20000 -d20000000 -m20000000 -- $java -Xmx${maxm}M -Xms${maxm}M "$name" +echo \$? > runit.retcode +/bin/umount /proc 2>/dev/null +#/bin/umount /dev +/bin/umount /sys 2>/dev/null +EOF + chmod 755 runit.sh + chroot /bocajail $cdir/runit.sh + ret=`cat runit.retcode` + if [ "$ret" == "" ]; then + echo "Execution error - check autojudging" + exit 49 + fi + if [ $ret -gt 10 ]; then + echo "> > > > > > > Nonzero return code - possible runtime error - I'M GUESSING IT IS RUNTIME ERROR < < < < < < < <" + exit 9 + fi + else + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 +# $java "$name" < stdin0 + $sf -r$nruns -t$time -T$ttime -istdin0 -F256 -u256 -U$bocau -G$bocag -ostdout0 -estderr0 -n0 -C. -d20000000 -m20000000 -- $java -cp run.jar -Xmx${maxm}M -Xms${maxm}M "$name" + ret=$? + fi + if [ $ret -gt 10 ]; then + echo "> > > > > > > Nonzero return code - possible runtime error - I'M GUESSING IT IS RUNTIME ERROR < < < < < < < <" + ret=9 + fi +fi +if [ -f stdout0 ]; then + cat stdout0 +fi +exit $ret diff --git a/boca-1.5.0/doc/problemtemplate/tests/c b/boca-1.5.0/doc/problemtemplate/tests/c new file mode 100755 index 0000000..1a0ca95 --- /dev/null +++ b/boca-1.5.0/doc/problemtemplate/tests/c @@ -0,0 +1,24 @@ +#!/bin/bash + +cat > test.c <<EOF +int main() { + char s[100]; + scanf("%s", s); + printf("%s\n",s); + return 0; +} +EOF +cat > test.in <<EOF +inputdata +EOF + +TL=2 +REP=10 +../compile/c test.c test.exe TL +../run/c test.exe test.in TL REP +output=`cat stdout0` +if [ "$output" != "inputdata" ]; then + echo "ERROR" + exit 1 +fi +exit 0 diff --git a/boca-1.5.0/doc/tests/fontes/abacaxi-yes.c b/boca-1.5.0/doc/tests/fontes/abacaxi-yes.c new file mode 100644 index 0000000..3b9d1a0 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/abacaxi-yes.c @@ -0,0 +1,48 @@ +/* Copyright 2001 Maratona de Programacao do IME-USP -- cef@ime.usp.br + */ + +#include <stdio.h> + +int main(int argc, char *argv[]) +{ + FILE * ent; + int cont = 0; + int n, num, rec[1000], desp[1000], soma, i, inic, somamax, imax, fmax; + + ent = stdin; + fscanf(ent, "%d", &n); + while (n > 0){ + cont++; + printf("Fazenda %d\n", cont); + for (i = 0; i < n; i++) fscanf(ent, "%d", &rec[i]); + for (i = 0; i < n; i++) fscanf(ent, "%d", &desp[i]); + somamax = -1; + imax = 0; + fmax = 0; + soma = 0; + inic = 1; + for (i = 0; i < n; i++){ + num = rec[i] - desp[i]; + if (soma + num >= 0){ + soma += num; + if (soma > somamax){ + imax = inic; + fmax = i + 1; + somamax = soma; + } + } + else{ + inic = i + 2; + soma = 0; + } + } + if(somamax >= 0) + printf("Inicio %d Fim %d\n\n", imax, fmax); + else + printf("O produtor so teve prejuizo nesta fazenda\n\n"); + + fscanf(ent, "%d", &n); + } + return(0); +} + diff --git a/boca-1.5.0/doc/tests/fontes/bits-compile.c b/boca-1.5.0/doc/tests/fontes/bits-compile.c new file mode 100644 index 0000000..ad979fd --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-compile.c @@ -0,0 +1,5 @@ +int main(void) { + int n; + n = 42 + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-compile.cpp b/boca-1.5.0/doc/tests/fontes/bits-compile.cpp new file mode 100644 index 0000000..ad979fd --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-compile.cpp @@ -0,0 +1,5 @@ +int main(void) { + int n; + n = 42 + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-compile.java b/boca-1.5.0/doc/tests/fontes/bits-compile.java new file mode 100644 index 0000000..dcfa1eb --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-compile.java @@ -0,0 +1,23 @@ +import java.io.*; +class bits { + public static void main(String args[]) { + StreamTokenizer st = new StreamTokenizer(System.in); + int i, j, n, max, inst=0; + while(42==42) { + st.nextToken(); + n = (int) st.nval; + if(n==0) break; + max=1; + for(i=0; i<n; i++) { + st.nextToken(); + j = (int) st.nval; + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + inst++; + System.out.println("Instancia " + inst); + System.out.println(i*n + "\n"); + } + } +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-compile.pas b/boca-1.5.0/doc/tests/fontes/bits-compile.pas new file mode 100644 index 0000000..ad2765f --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-compile.pas @@ -0,0 +1,27 @@ +program bits; +var i, j, n, max, inst: Longint; +begin + inst=0; + while true do + begin + read(n); + if n=0 then break; + max:=1; + for i:=0 to n-1 do + begin + read(j); + if j>max then max:=j + end; + i:=0; + while max>0 do + begin + max := max div 2; + i := i + 1 + end; + write('Instancia '); + inst := inst + 1; + writeln(inst); + writeln(i*n); + writeln() + end +end. diff --git a/boca-1.5.0/doc/tests/fontes/bits-diffbug.c b/boca-1.5.0/doc/tests/fontes/bits-diffbug.c new file mode 100644 index 0000000..3703152 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-diffbug.c @@ -0,0 +1,25 @@ +/* this file illustrate a bug in diff that, even using -w -B -b, + * it will think that the files are different and will return + * exit code 1, when the only difference between them is a line + * in the end with a single white space. + * Author: cassio@ime.usp.br + * Last updated: 18/aug/2008 + */ +#include <stdio.h> +int main(void) { + int i, j, n, max, inst=0; + while(42) { + scanf("%d", &n); + if(!n) break; + max=1; + for(i=0; i<n; i++) { + scanf("%d", &j); + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + printf("Instancia %d\n%d\n\n", ++inst, i*n); + } + printf(" \n"); + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-incorrect.c b/boca-1.5.0/doc/tests/fontes/bits-incorrect.c new file mode 100644 index 0000000..de05583 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-incorrect.c @@ -0,0 +1,17 @@ +#include <stdio.h> +int main(void) { + int i, j, n, max, inst=0; + while(42) { + scanf("%d", &n); + if(!n) break; + max=0; + for(i=0; i<n; i++) { + scanf("%d", &j); + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + printf("Instancia %d\n%d\n\n", ++inst, i*n); + } + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-incorrect.cpp b/boca-1.5.0/doc/tests/fontes/bits-incorrect.cpp new file mode 100644 index 0000000..3b38845 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-incorrect.cpp @@ -0,0 +1,18 @@ +#include <iostream> +using namespace std; +int main(void) { + int i, j, n, max, inst=0; + while(42) { + cin >> n; + if(!n) break; + max=0; + for(i=0; i<n; i++) { + cin >> j; + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + cout << "Instancia " << ++inst << endl << (i*n) << endl << endl; + } + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-incorrect.java b/boca-1.5.0/doc/tests/fontes/bits-incorrect.java new file mode 100644 index 0000000..30b388d --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-incorrect.java @@ -0,0 +1,23 @@ +import java.io.*; +class bits { + public static void main(String args[]) throws Exception { + StreamTokenizer st = new StreamTokenizer(System.in); + int i, j, n, max, inst=0; + while(42==42) { + st.nextToken(); + n = (int) st.nval; + if(n==0) break; + max=0; + for(i=0; i<n; i++) { + st.nextToken(); + j = (int) st.nval; + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + inst++; + System.out.println("Instancia " + inst); + System.out.println(i*n + "\n"); + } + } +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-incorrect.pas b/boca-1.5.0/doc/tests/fontes/bits-incorrect.pas new file mode 100644 index 0000000..7dbcd4b --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-incorrect.pas @@ -0,0 +1,27 @@ +program bits; +var i, j, n, max, inst: Longint; +begin + inst:=0; + while true do + begin + read(n); + if n=0 then break; + max:=1; + for i:=0 to n-1 do + begin + read(j); + if j>max then max:=j + end; + i:=0; + while max>0 do + begin + max := max div 2; + i := i + 1 + end; + write('Instancia '); + inst := inst + 1; + writeln(inst); + writeln(i); + writeln() + end +end. diff --git a/boca-1.5.0/doc/tests/fontes/bits-outputformat.c b/boca-1.5.0/doc/tests/fontes/bits-outputformat.c new file mode 100644 index 0000000..62d11f5 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-outputformat.c @@ -0,0 +1,17 @@ +#include <stdio.h> +int main(void) { + int i, j, n, max, inst=0; + while(42) { + scanf("%d", &n); + if(!n) break; + max=1; + for(i=0; i<n; i++) { + scanf("%d", &j); + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + printf("INStanCIA %d\n%d\n\n", ++inst, i*n); + } + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-outputformat.cpp b/boca-1.5.0/doc/tests/fontes/bits-outputformat.cpp new file mode 100644 index 0000000..62d11f5 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-outputformat.cpp @@ -0,0 +1,17 @@ +#include <stdio.h> +int main(void) { + int i, j, n, max, inst=0; + while(42) { + scanf("%d", &n); + if(!n) break; + max=1; + for(i=0; i<n; i++) { + scanf("%d", &j); + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + printf("INStanCIA %d\n%d\n\n", ++inst, i*n); + } + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-outputformat.java b/boca-1.5.0/doc/tests/fontes/bits-outputformat.java new file mode 100644 index 0000000..7a3d144 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-outputformat.java @@ -0,0 +1,23 @@ +import java.io.*; +class bits { + public static void main(String args[]) throws Exception { + StreamTokenizer st = new StreamTokenizer(System.in); + int i, j, n, max, inst=0; + while(42==42) { + st.nextToken(); + n = (int) st.nval; + if(n==0) break; + max=1; + for(i=0; i<n; i++) { + st.nextToken(); + j = (int) st.nval; + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + inst++; + System.out.println("Instancia " + inst); + System.out.println(i*n); + } + } +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-outputformat.pas b/boca-1.5.0/doc/tests/fontes/bits-outputformat.pas new file mode 100644 index 0000000..e5094d2 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-outputformat.pas @@ -0,0 +1,27 @@ +program bits; +var i, j, n, max, inst: Longint; +begin + inst:=0; + while true do + begin + read(n); + if n=0 then break; + max:=1; + for i:=0 to n-1 do + begin + read(j); + if j>max then max:=j + end; + i:=0; + while max>0 do + begin + max := max div 2; + i := i + 1 + end; + write('Instacia '); + inst := inst + 1; + writeln(inst); + writeln(i*n); + writeln() + end +end. diff --git a/boca-1.5.0/doc/tests/fontes/bits-runtime.c b/boca-1.5.0/doc/tests/fontes/bits-runtime.c new file mode 100644 index 0000000..9fe074f --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-runtime.c @@ -0,0 +1,5 @@ +int main(void) { + int *n= (int *)42; + *n = 42; + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-runtime.cpp b/boca-1.5.0/doc/tests/fontes/bits-runtime.cpp new file mode 100644 index 0000000..9fe074f --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-runtime.cpp @@ -0,0 +1,5 @@ +int main(void) { + int *n= (int *)42; + *n = 42; + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-runtime.java b/boca-1.5.0/doc/tests/fontes/bits-runtime.java new file mode 100644 index 0000000..f7bffc5 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-runtime.java @@ -0,0 +1,24 @@ +import java.io.*; +class bits { + public static void main(String args[]) throws Exception { + StreamTokenizer st = new StreamTokenizer(System.in); + int i, j, n, max, inst=0; + while(42==42) { + st.nextToken(); + n = (int) st.nval; + if(n==0) break; + max=1; + for(i=0; i<n; i++) { + st.nextToken(); + j = (int) st.nval; + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + inst++; + System.out.println("Instancia " + inst); + System.out.println(i*n + "\n"); + throw new Exception("OPA! Runtime error, hehehe..."); + } + } +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-runtime.pas b/boca-1.5.0/doc/tests/fontes/bits-runtime.pas new file mode 100644 index 0000000..ed496c0 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-runtime.pas @@ -0,0 +1,27 @@ +program bits; +var i, inst, max, n: Longint; + v: array[0..1] of Longint; +begin + while true do + begin + read(n); + if n=0 then break; + max := 1; + for i:=0 to n-1 do + begin + read(v[i]); + if v[i]>max then max:=v[i] + end; + i:=0; + while max>0 do + begin + max := max div 2; + i := i + 1 + end; + write('Instancia '); + inst := inst + 1; + writeln(inst); + writeln(i*n); + writeln() + end +end. diff --git a/boca-1.5.0/doc/tests/fontes/bits-timelimit.c b/boca-1.5.0/doc/tests/fontes/bits-timelimit.c new file mode 100644 index 0000000..19e1c57 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-timelimit.c @@ -0,0 +1,8 @@ +#include <stdio.h> +int main(void) { + int n=0; + while(42) { + n++; + } + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-timelimit.cpp b/boca-1.5.0/doc/tests/fontes/bits-timelimit.cpp new file mode 100644 index 0000000..25cb517 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-timelimit.cpp @@ -0,0 +1,8 @@ +#include <iostream> +int main(void) { + int n=0; + while(42) { + n++; + } + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-timelimit.java b/boca-1.5.0/doc/tests/fontes/bits-timelimit.java new file mode 100644 index 0000000..4330bb3 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-timelimit.java @@ -0,0 +1,10 @@ +import java.io.*; +class bits { + public static void main(String args[]) throws Exception { + StreamTokenizer st = new StreamTokenizer(System.in); + int inst=0; + while(42==42) { + inst++; + } + } +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-timelimit.pas b/boca-1.5.0/doc/tests/fontes/bits-timelimit.pas new file mode 100644 index 0000000..d0b496d --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-timelimit.pas @@ -0,0 +1,8 @@ +program bits; +var inst: Longint; +begin + inst:=0; + while true do + begin + end +end. diff --git a/boca-1.5.0/doc/tests/fontes/bits-yes.c b/boca-1.5.0/doc/tests/fontes/bits-yes.c new file mode 100644 index 0000000..ab23f83 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-yes.c @@ -0,0 +1,17 @@ +#include <stdio.h> +int main(void) { + int i, j, n, max, inst=0; + while(42) { + scanf("%d", &n); + if(!n) break; + max=1; + for(i=0; i<n; i++) { + scanf("%d", &j); + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + printf("Instancia %d\n%d\n\n", ++inst, i*n); + } + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-yes.cpp b/boca-1.5.0/doc/tests/fontes/bits-yes.cpp new file mode 100644 index 0000000..11a32b5 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-yes.cpp @@ -0,0 +1,18 @@ +#include <iostream> +using namespace std; +int main(void) { + int i, j, n, max, inst=0; + while(42) { + cin >> n; + if(!n) break; + max=1; + for(i=0; i<n; i++) { + cin >> j; + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + cout << "Instancia " << ++inst << endl << (i*n) << endl << endl; + } + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-yes.java b/boca-1.5.0/doc/tests/fontes/bits-yes.java new file mode 100644 index 0000000..3448484 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-yes.java @@ -0,0 +1,23 @@ +import java.io.*; +class bits { + public static void main(String args[]) throws Exception { + StreamTokenizer st = new StreamTokenizer(System.in); + int i, j, n, max, inst=0; + while(42==42) { + st.nextToken(); + n = (int) st.nval; + if(n==0) break; + max=1; + for(i=0; i<n; i++) { + st.nextToken(); + j = (int) st.nval; + if(j>max) max=j; + } + for(i=0; max>0; i++) + max >>= 1; + inst++; + System.out.println("Instancia " + inst); + System.out.println(i*n + "\n"); + } + } +} diff --git a/boca-1.5.0/doc/tests/fontes/bits-yes.pas b/boca-1.5.0/doc/tests/fontes/bits-yes.pas new file mode 100644 index 0000000..0970c43 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/bits-yes.pas @@ -0,0 +1,27 @@ +program bits; +var i, j, n, max, inst: Longint; +begin + inst:=0; + while true do + begin + read(n); + if n=0 then break; + max:=1; + for i:=0 to n-1 do + begin + read(j); + if j>max then max:=j + end; + i:=0; + while max>0 do + begin + max := max div 2; + i := i + 1 + end; + write('Instancia '); + inst := inst + 1; + writeln(inst); + writeln(i*n); + writeln() + end +end. diff --git a/boca-1.5.0/doc/tests/fontes/formiga-yes.c b/boca-1.5.0/doc/tests/fontes/formiga-yes.c new file mode 100644 index 0000000..7640d75 --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/formiga-yes.c @@ -0,0 +1,68 @@ +/* Copyright 2002 Maratona de Programacao do IME-USP -- cef@ime.usp.br (written by S.G.Tavares) + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <math.h> + +FILE *in, *out; + +long mdc(long a, long b){ + long i, mdca=1; + for(i=2; ((i<=a) && (i<=b)) ; i++) + if ((!(a%i)) && (!(b%i))) mdca = i; + return mdca; +} + + +int main(){ + long x, y, i, j, k; + char p1[8]; + double db1; + int dh, dv; + in = stdin; + out = stdout; + + while(42){ + fscanf(in, "%ld%ld\n", &x, &y); + if (!x || !y) break; + fscanf(in, "%s\n", &p1[0]); + if (p1[0]=='N') { + dh = 0; + dv = 0; + } + else if (p1[0]=='S') { + dh = 1; + dv = 1; + } + else if (p1[0]=='L') { + dh = 1; + dv = 0; + } + else { + dh = 0; + dv = 1; + } + for (i=x, j=y; ((!(i%2)) && (!(j%2))); i /= 2, j /= 2 ); + if (i%2) dh = !dh; + if (j%2) dv = !dv; + k = mdc(x, y); + db1 = 100.0/(double)k; + i = floor(100.0/(double)k); + if (db1-(double)i > 0.5) i++; + + j = x/k + y/k -2; + fprintf(out, "%3ld%%%10ld", i, j); + if (dh){ + if (dv) fprintf(out, " Sul\n"); + else fprintf(out, " Leste\n"); + } + else { + if (dv) fprintf(out, " Oeste\n"); + else fprintf(out, " Norte\n"); + } + } + + return 0; +} diff --git a/boca-1.5.0/doc/tests/fontes/multas-yes.c b/boca-1.5.0/doc/tests/fontes/multas-yes.c new file mode 100644 index 0000000..3729d0b --- /dev/null +++ b/boca-1.5.0/doc/tests/fontes/multas-yes.c @@ -0,0 +1,85 @@ +/* Copyright 2001 Maratona de Programacao do IME-USP -- cef@ime.usp.br + */ + +#include <stdio.h> + +typedef struct +{ + char nome[100]; + char nomeconv[100]; + + int pontos; +} +m_familia; + +#define MAX 21 + +char conv(char c) +{ + if(c >= 'A' && c <= 'Z') return (c += 'a' - 'A'); + return(c); + +} + + +int menor(char v[80], char w[80]) +{ + int i=0; + + while(i < 80 && v[i] == w[i])i++; + return(v[i] < w[i]); +} + + +int main(int argc, char *argv[]) +{ + FILE * ent; + int cont = 0; + int n, i,j, multa, nmult, min; + m_familia familia[20]; + + ent = stdin; + + fscanf(ent, "%d", &n); + while (n > 0){ + cont++; + printf("Familia %d\n", cont); + + for (i = 0; i < n; i++){ + fscanf(ent, "%s", &(familia[i].nome[0])); + j = 0; + while(familia[i].nome[j] != 0) { + familia[i].nomeconv[j]=conv(familia[i].nome[j]); + j++; + } + familia[i].nomeconv[j]=0; + + familia[i].pontos = 0; + } + fscanf(ent, "%d", &multa); + nmult = 0; + + while(multa > 0){ + nmult++; + min = 0; + for (i = 0; i < n; i++) + if (familia[i].pontos < familia[min].pontos || + (familia[i].pontos == familia[min].pontos && + menor(familia[i].nomeconv, familia[min].nomeconv))) + min = i; + printf("Multa %d %s", nmult, familia[min].nome); + familia[min].pontos += multa; + if ( familia[min].pontos >= MAX) + printf(" carteira suspensa\n"); + else printf("\n"); + fscanf(ent, "%d", &multa); + } + printf("\n"); + + fscanf(ent, "%d", &n); + } + fclose(ent); + return(0); +} + + diff --git a/boca-1.5.0/doc/tests/in_out/abacaxi.in b/boca-1.5.0/doc/tests/in_out/abacaxi.in new file mode 100644 index 0000000..26d3afe --- /dev/null +++ b/boca-1.5.0/doc/tests/in_out/abacaxi.in @@ -0,0 +1,25 @@ +5
+32 37 82 46 32
+13 40 75 62 19
+8
+14 22 29 41 72 25 68 90
+22 19 21 45 70 46 66 80
+3
+2 4 5
+8 8 8
+8
+12 1 0 8 5 0 9 4
+0 0 13 0 0 13 0 0
+8
+8 8 8 8 8 8 8 8
+7 9 5 8 9 5 9 7
+1
+0
+0
+999
+1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+999
+ 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000 2000
+ 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
+0
diff --git a/boca-1.5.0/doc/tests/in_out/abacaxi.sol b/boca-1.5.0/doc/tests/in_out/abacaxi.sol new file mode 100644 index 0000000..2e9fd8b --- /dev/null +++ b/boca-1.5.0/doc/tests/in_out/abacaxi.sol @@ -0,0 +1,24 @@ +Fazenda 1
+Inicio 1 Fim 3
+
+Fazenda 2
+Inicio 7 Fim 8
+
+Fazenda 3
+O produtor so teve prejuizo nesta fazenda
+
+Fazenda 4
+Inicio 1 Fim 2
+
+Fazenda 5
+Inicio 1 Fim 6
+
+Fazenda 6
+Inicio 1 Fim 1
+
+Fazenda 7
+Inicio 1 Fim 999
+
+Fazenda 8
+Inicio 1 Fim 999
+
diff --git a/boca-1.5.0/doc/tests/in_out/bits.in b/boca-1.5.0/doc/tests/in_out/bits.in new file mode 100644 index 0000000..ef548be --- /dev/null +++ b/boca-1.5.0/doc/tests/in_out/bits.in @@ -0,0 +1,9 @@ +1 7 +4 1 10 20 30 +2 2000 999 +3 0 0 0 +2 1 1000 +1000 1073741824 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 +1 0 +1 8 +0 diff --git a/boca-1.5.0/doc/tests/in_out/bits.sol b/boca-1.5.0/doc/tests/in_out/bits.sol new file mode 100644 index 0000000..7749442 --- /dev/null +++ b/boca-1.5.0/doc/tests/in_out/bits.sol @@ -0,0 +1,24 @@ +Instancia 1 +3 + +Instancia 2 +20 + +Instancia 3 +22 + +Instancia 4 +3 + +Instancia 5 +20 + +Instancia 6 +31000 + +Instancia 7 +1 + +Instancia 8 +4 + diff --git a/boca-1.5.0/doc/tests/in_out/formiga.in b/boca-1.5.0/doc/tests/in_out/formiga.in new file mode 100644 index 0000000..c9a59b2 --- /dev/null +++ b/boca-1.5.0/doc/tests/in_out/formiga.in @@ -0,0 +1,15 @@ +1 1 Norte +4 8 Norte +3 2 Sul +100000 100000 Oeste +6 6 Sul +4 13 Oeste +4 14 Sul +4 13 Leste +640 648 Norte +45 99998 Leste +45 99995 Oeste +99999 99998 Norte +99999 99996 Oeste +445 1157 Sul +100000 0 Qqlixo diff --git a/boca-1.5.0/doc/tests/in_out/formiga.sol b/boca-1.5.0/doc/tests/in_out/formiga.sol new file mode 100644 index 0000000..499641c --- /dev/null +++ b/boca-1.5.0/doc/tests/in_out/formiga.sol @@ -0,0 +1,14 @@ +100% 0 Sul + 25% 1 Leste +100% 3 Oeste + 0% 0 Leste + 17% 0 Norte +100% 15 Norte + 50% 7 Leste +100% 15 Sul + 12% 159 Oeste +100% 100041 Norte + 20% 20006 Leste +100% 199995 Leste + 33% 66663 Sul + 1% 16 Norte diff --git a/boca-1.5.0/doc/tests/in_out/multas.in b/boca-1.5.0/doc/tests/in_out/multas.in new file mode 100644 index 0000000..bb947cd --- /dev/null +++ b/boca-1.5.0/doc/tests/in_out/multas.in @@ -0,0 +1,518 @@ +5 +john +mary +bob +rick +donna +4 +4 +5 +7 +7 +7 +-2 +3 +paul +irene +charlie +5 +5 +5 +5 +5 +4 +7 +7 +4 +4 +4 +4 +-3 +19 +Zzzzzzzzzzzzzzzzzzzs +zzzzzzzzzzzzzzzzzzzr +zzzzzzzzzzzzzzzzzzzq +zzzzzzzzzzzzzzzzzzzpzzzzzzzzzzzzzzzzzzzpzzzzzzzzzzzzzzzzzzzpzzzzzzzzzzzzzzzzzzzp +zzzzzzzzzzzzzzzzzzzo +zzzzzzzzzzzzzzzzzzzn +zzzzzzzzzzzzzzzzzzzm +zzzzzzzzzzzzzzzzzzzl +zzzzzzzzzzzzzzzzzzzk +zzzzzzzzzzzzzzzzzzzj +zzzzzzzzzzzzzzzzzzzi +zzzzzzzzzzzzzzzzzzzh +zzzzzzzzzzzzzzzzzzzg +zzzzzzzzzzzzzzzzzzzf +zzzzzzzzzzzzzzzzzzze +zzzzzzzzzzzzzzzzzzzd +zzzzzzzzzzzzzzzzzzzc +zzzzzzzzzzzzzzzzzzzb +Zzzzzzzzzzzzzzzzzzza +250 +250 +250 +250 +250 +250 +250 +250 +250 +250 +250 +250 +250 +250 +250 +250 +250 +250 +250 +-50 +19 +Zzzzzzzzzzzzzzzzzzzs +zzzzzzzzzzzzzzzzzzzr +zzzzzzzzzzzzzzzzzzzq +zzzzzzzzzzzzzzzzzzzp +zzzzzzzzzzzzzzzzzzzo +zzzzzzzzzzzzzzzzzzzn +zzzzzzzzzzzzzzzzzzzm +zzzzzzzzzzzzzzzzzzzl +zzzzzzzzzzzzzzzzzzzk +zzzzzzzzzzzzzzzzzzzj +zzzzzzzzzzzzzzzzzzzi +zzzzzzzzzzzzzzzzzzzh +zzzzzzzzzzzzzzzzzzzg +zzzzzzzzzzzzzzzzzzzf +zzzzzzzzzzzzzzzzzzze +zzzzzzzzzzzzzzzzzzzd +zzzzzzzzzzzzzzzzzzzc +zzzzzzzzzzzzzzzzzzzb +Zzzzzzzzzzzzzzzzzzza +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +-50 +5 +a +b +c +d +e +5 +4 +3 +2 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +-3 +0 diff --git a/boca-1.5.0/doc/tests/in_out/multas.sol b/boca-1.5.0/doc/tests/in_out/multas.sol new file mode 100644 index 0000000..5855c90 --- /dev/null +++ b/boca-1.5.0/doc/tests/in_out/multas.sol @@ -0,0 +1,466 @@ +Familia 1
+Multa 1 bob
+Multa 2 donna
+Multa 3 john
+Multa 4 mary
+Multa 5 rick
+Multa 6 bob
+
+Familia 2
+Multa 1 charlie
+Multa 2 irene
+Multa 3 paul
+Multa 4 charlie
+Multa 5 irene
+Multa 6 paul
+Multa 7 paul
+Multa 8 charlie
+Multa 9 irene
+Multa 10 irene
+Multa 11 paul
+Multa 12 charlie carteira suspensa
+
+Familia 3
+Multa 1 Zzzzzzzzzzzzzzzzzzza carteira suspensa
+Multa 2 zzzzzzzzzzzzzzzzzzzb carteira suspensa
+Multa 3 zzzzzzzzzzzzzzzzzzzc carteira suspensa
+Multa 4 zzzzzzzzzzzzzzzzzzzd carteira suspensa
+Multa 5 zzzzzzzzzzzzzzzzzzze carteira suspensa
+Multa 6 zzzzzzzzzzzzzzzzzzzf carteira suspensa
+Multa 7 zzzzzzzzzzzzzzzzzzzg carteira suspensa
+Multa 8 zzzzzzzzzzzzzzzzzzzh carteira suspensa
+Multa 9 zzzzzzzzzzzzzzzzzzzi carteira suspensa
+Multa 10 zzzzzzzzzzzzzzzzzzzj carteira suspensa
+Multa 11 zzzzzzzzzzzzzzzzzzzk carteira suspensa
+Multa 12 zzzzzzzzzzzzzzzzzzzl carteira suspensa
+Multa 13 zzzzzzzzzzzzzzzzzzzm carteira suspensa
+Multa 14 zzzzzzzzzzzzzzzzzzzn carteira suspensa
+Multa 15 zzzzzzzzzzzzzzzzzzzo carteira suspensa
+Multa 16 zzzzzzzzzzzzzzzzzzzpzzzzzzzzzzzzzzzzzzzpzzzzzzzzzzzzzzzzzzzpzzzzzzzzzzzzzzzzzzzp carteira suspensa
+Multa 17 zzzzzzzzzzzzzzzzzzzq carteira suspensa
+Multa 18 zzzzzzzzzzzzzzzzzzzr carteira suspensa
+Multa 19 Zzzzzzzzzzzzzzzzzzzs carteira suspensa
+
+Familia 4
+Multa 1 Zzzzzzzzzzzzzzzzzzza
+Multa 2 zzzzzzzzzzzzzzzzzzzb
+Multa 3 zzzzzzzzzzzzzzzzzzzc
+Multa 4 zzzzzzzzzzzzzzzzzzzd
+Multa 5 zzzzzzzzzzzzzzzzzzze
+Multa 6 zzzzzzzzzzzzzzzzzzzf
+Multa 7 zzzzzzzzzzzzzzzzzzzg
+Multa 8 zzzzzzzzzzzzzzzzzzzh
+Multa 9 zzzzzzzzzzzzzzzzzzzi
+Multa 10 zzzzzzzzzzzzzzzzzzzj
+Multa 11 zzzzzzzzzzzzzzzzzzzk
+Multa 12 zzzzzzzzzzzzzzzzzzzl
+Multa 13 zzzzzzzzzzzzzzzzzzzm
+Multa 14 zzzzzzzzzzzzzzzzzzzn
+Multa 15 zzzzzzzzzzzzzzzzzzzo
+Multa 16 zzzzzzzzzzzzzzzzzzzp
+Multa 17 zzzzzzzzzzzzzzzzzzzq
+Multa 18 zzzzzzzzzzzzzzzzzzzr
+Multa 19 Zzzzzzzzzzzzzzzzzzzs
+Multa 20 Zzzzzzzzzzzzzzzzzzza
+Multa 21 zzzzzzzzzzzzzzzzzzzb
+Multa 22 zzzzzzzzzzzzzzzzzzzc
+Multa 23 zzzzzzzzzzzzzzzzzzzd
+Multa 24 zzzzzzzzzzzzzzzzzzze
+Multa 25 zzzzzzzzzzzzzzzzzzzf
+Multa 26 zzzzzzzzzzzzzzzzzzzg
+Multa 27 zzzzzzzzzzzzzzzzzzzh
+Multa 28 zzzzzzzzzzzzzzzzzzzi
+Multa 29 zzzzzzzzzzzzzzzzzzzj
+Multa 30 zzzzzzzzzzzzzzzzzzzk
+Multa 31 zzzzzzzzzzzzzzzzzzzl
+Multa 32 zzzzzzzzzzzzzzzzzzzm
+Multa 33 zzzzzzzzzzzzzzzzzzzn
+Multa 34 zzzzzzzzzzzzzzzzzzzo
+Multa 35 zzzzzzzzzzzzzzzzzzzp
+Multa 36 zzzzzzzzzzzzzzzzzzzq
+Multa 37 zzzzzzzzzzzzzzzzzzzr
+Multa 38 Zzzzzzzzzzzzzzzzzzzs
+Multa 39 Zzzzzzzzzzzzzzzzzzza
+Multa 40 zzzzzzzzzzzzzzzzzzzb
+Multa 41 zzzzzzzzzzzzzzzzzzzc
+Multa 42 zzzzzzzzzzzzzzzzzzzd
+Multa 43 zzzzzzzzzzzzzzzzzzze
+Multa 44 zzzzzzzzzzzzzzzzzzzf
+Multa 45 zzzzzzzzzzzzzzzzzzzg
+Multa 46 zzzzzzzzzzzzzzzzzzzh
+Multa 47 zzzzzzzzzzzzzzzzzzzi
+Multa 48 zzzzzzzzzzzzzzzzzzzj
+Multa 49 zzzzzzzzzzzzzzzzzzzk
+Multa 50 zzzzzzzzzzzzzzzzzzzl
+Multa 51 zzzzzzzzzzzzzzzzzzzm
+Multa 52 zzzzzzzzzzzzzzzzzzzn
+Multa 53 zzzzzzzzzzzzzzzzzzzo
+Multa 54 zzzzzzzzzzzzzzzzzzzp
+Multa 55 zzzzzzzzzzzzzzzzzzzq
+Multa 56 zzzzzzzzzzzzzzzzzzzr
+Multa 57 Zzzzzzzzzzzzzzzzzzzs
+Multa 58 Zzzzzzzzzzzzzzzzzzza
+Multa 59 zzzzzzzzzzzzzzzzzzzb
+Multa 60 zzzzzzzzzzzzzzzzzzzc
+Multa 61 zzzzzzzzzzzzzzzzzzzd
+Multa 62 zzzzzzzzzzzzzzzzzzze
+Multa 63 zzzzzzzzzzzzzzzzzzzf
+Multa 64 zzzzzzzzzzzzzzzzzzzg
+Multa 65 zzzzzzzzzzzzzzzzzzzh
+Multa 66 zzzzzzzzzzzzzzzzzzzi
+Multa 67 zzzzzzzzzzzzzzzzzzzj
+Multa 68 zzzzzzzzzzzzzzzzzzzk
+Multa 69 zzzzzzzzzzzzzzzzzzzl
+Multa 70 zzzzzzzzzzzzzzzzzzzm
+Multa 71 zzzzzzzzzzzzzzzzzzzn
+Multa 72 zzzzzzzzzzzzzzzzzzzo
+Multa 73 zzzzzzzzzzzzzzzzzzzp
+Multa 74 zzzzzzzzzzzzzzzzzzzq
+Multa 75 zzzzzzzzzzzzzzzzzzzr
+Multa 76 Zzzzzzzzzzzzzzzzzzzs
+Multa 77 Zzzzzzzzzzzzzzzzzzza
+Multa 78 zzzzzzzzzzzzzzzzzzzb
+Multa 79 zzzzzzzzzzzzzzzzzzzc
+Multa 80 zzzzzzzzzzzzzzzzzzzd
+Multa 81 zzzzzzzzzzzzzzzzzzze
+Multa 82 zzzzzzzzzzzzzzzzzzzf
+Multa 83 zzzzzzzzzzzzzzzzzzzg
+Multa 84 zzzzzzzzzzzzzzzzzzzh
+Multa 85 zzzzzzzzzzzzzzzzzzzi
+Multa 86 zzzzzzzzzzzzzzzzzzzj
+Multa 87 zzzzzzzzzzzzzzzzzzzk
+Multa 88 zzzzzzzzzzzzzzzzzzzl
+Multa 89 zzzzzzzzzzzzzzzzzzzm
+Multa 90 zzzzzzzzzzzzzzzzzzzn
+Multa 91 zzzzzzzzzzzzzzzzzzzo
+Multa 92 zzzzzzzzzzzzzzzzzzzp
+Multa 93 zzzzzzzzzzzzzzzzzzzq
+Multa 94 zzzzzzzzzzzzzzzzzzzr
+Multa 95 Zzzzzzzzzzzzzzzzzzzs
+Multa 96 Zzzzzzzzzzzzzzzzzzza
+Multa 97 zzzzzzzzzzzzzzzzzzzb
+Multa 98 zzzzzzzzzzzzzzzzzzzc
+Multa 99 zzzzzzzzzzzzzzzzzzzd
+Multa 100 zzzzzzzzzzzzzzzzzzze
+Multa 101 zzzzzzzzzzzzzzzzzzzf
+Multa 102 zzzzzzzzzzzzzzzzzzzg
+Multa 103 zzzzzzzzzzzzzzzzzzzh
+Multa 104 zzzzzzzzzzzzzzzzzzzi
+Multa 105 zzzzzzzzzzzzzzzzzzzj
+Multa 106 zzzzzzzzzzzzzzzzzzzk
+Multa 107 zzzzzzzzzzzzzzzzzzzl
+Multa 108 zzzzzzzzzzzzzzzzzzzm
+Multa 109 zzzzzzzzzzzzzzzzzzzn
+Multa 110 zzzzzzzzzzzzzzzzzzzo
+Multa 111 zzzzzzzzzzzzzzzzzzzp
+Multa 112 zzzzzzzzzzzzzzzzzzzq
+Multa 113 zzzzzzzzzzzzzzzzzzzr
+Multa 114 Zzzzzzzzzzzzzzzzzzzs
+Multa 115 Zzzzzzzzzzzzzzzzzzza
+Multa 116 zzzzzzzzzzzzzzzzzzzb
+Multa 117 zzzzzzzzzzzzzzzzzzzc
+Multa 118 zzzzzzzzzzzzzzzzzzzd
+Multa 119 zzzzzzzzzzzzzzzzzzze
+Multa 120 zzzzzzzzzzzzzzzzzzzf
+Multa 121 zzzzzzzzzzzzzzzzzzzg
+Multa 122 zzzzzzzzzzzzzzzzzzzh
+Multa 123 zzzzzzzzzzzzzzzzzzzi
+Multa 124 zzzzzzzzzzzzzzzzzzzj
+Multa 125 zzzzzzzzzzzzzzzzzzzk
+Multa 126 zzzzzzzzzzzzzzzzzzzl
+Multa 127 zzzzzzzzzzzzzzzzzzzm
+Multa 128 zzzzzzzzzzzzzzzzzzzn
+Multa 129 zzzzzzzzzzzzzzzzzzzo
+Multa 130 zzzzzzzzzzzzzzzzzzzp
+Multa 131 zzzzzzzzzzzzzzzzzzzq
+Multa 132 zzzzzzzzzzzzzzzzzzzr
+Multa 133 Zzzzzzzzzzzzzzzzzzzs
+Multa 134 Zzzzzzzzzzzzzzzzzzza
+Multa 135 zzzzzzzzzzzzzzzzzzzb
+Multa 136 zzzzzzzzzzzzzzzzzzzc
+Multa 137 zzzzzzzzzzzzzzzzzzzd
+Multa 138 zzzzzzzzzzzzzzzzzzze
+Multa 139 zzzzzzzzzzzzzzzzzzzf
+Multa 140 zzzzzzzzzzzzzzzzzzzg
+Multa 141 zzzzzzzzzzzzzzzzzzzh
+Multa 142 zzzzzzzzzzzzzzzzzzzi
+Multa 143 zzzzzzzzzzzzzzzzzzzj
+Multa 144 zzzzzzzzzzzzzzzzzzzk
+Multa 145 zzzzzzzzzzzzzzzzzzzl
+Multa 146 zzzzzzzzzzzzzzzzzzzm
+Multa 147 zzzzzzzzzzzzzzzzzzzn
+Multa 148 zzzzzzzzzzzzzzzzzzzo
+Multa 149 zzzzzzzzzzzzzzzzzzzp
+Multa 150 zzzzzzzzzzzzzzzzzzzq
+Multa 151 zzzzzzzzzzzzzzzzzzzr
+Multa 152 Zzzzzzzzzzzzzzzzzzzs
+Multa 153 Zzzzzzzzzzzzzzzzzzza
+Multa 154 zzzzzzzzzzzzzzzzzzzb
+Multa 155 zzzzzzzzzzzzzzzzzzzc
+Multa 156 zzzzzzzzzzzzzzzzzzzd
+Multa 157 zzzzzzzzzzzzzzzzzzze
+Multa 158 zzzzzzzzzzzzzzzzzzzf
+Multa 159 zzzzzzzzzzzzzzzzzzzg
+Multa 160 zzzzzzzzzzzzzzzzzzzh
+Multa 161 zzzzzzzzzzzzzzzzzzzi
+Multa 162 zzzzzzzzzzzzzzzzzzzj
+Multa 163 zzzzzzzzzzzzzzzzzzzk
+Multa 164 zzzzzzzzzzzzzzzzzzzl
+Multa 165 zzzzzzzzzzzzzzzzzzzm
+Multa 166 zzzzzzzzzzzzzzzzzzzn
+Multa 167 zzzzzzzzzzzzzzzzzzzo
+Multa 168 zzzzzzzzzzzzzzzzzzzp
+Multa 169 zzzzzzzzzzzzzzzzzzzq
+Multa 170 zzzzzzzzzzzzzzzzzzzr
+Multa 171 Zzzzzzzzzzzzzzzzzzzs
+Multa 172 Zzzzzzzzzzzzzzzzzzza
+Multa 173 zzzzzzzzzzzzzzzzzzzb
+Multa 174 zzzzzzzzzzzzzzzzzzzc
+Multa 175 zzzzzzzzzzzzzzzzzzzd
+Multa 176 zzzzzzzzzzzzzzzzzzze
+Multa 177 zzzzzzzzzzzzzzzzzzzf
+Multa 178 zzzzzzzzzzzzzzzzzzzg
+Multa 179 zzzzzzzzzzzzzzzzzzzh
+Multa 180 zzzzzzzzzzzzzzzzzzzi
+Multa 181 zzzzzzzzzzzzzzzzzzzj
+Multa 182 zzzzzzzzzzzzzzzzzzzk
+Multa 183 zzzzzzzzzzzzzzzzzzzl
+Multa 184 zzzzzzzzzzzzzzzzzzzm
+Multa 185 zzzzzzzzzzzzzzzzzzzn
+Multa 186 zzzzzzzzzzzzzzzzzzzo
+Multa 187 zzzzzzzzzzzzzzzzzzzp
+Multa 188 zzzzzzzzzzzzzzzzzzzq
+Multa 189 zzzzzzzzzzzzzzzzzzzr
+Multa 190 Zzzzzzzzzzzzzzzzzzzs
+Multa 191 Zzzzzzzzzzzzzzzzzzza
+Multa 192 zzzzzzzzzzzzzzzzzzzb
+Multa 193 zzzzzzzzzzzzzzzzzzzc
+Multa 194 zzzzzzzzzzzzzzzzzzzd
+Multa 195 zzzzzzzzzzzzzzzzzzze
+Multa 196 zzzzzzzzzzzzzzzzzzzf
+Multa 197 zzzzzzzzzzzzzzzzzzzg
+Multa 198 zzzzzzzzzzzzzzzzzzzh
+Multa 199 zzzzzzzzzzzzzzzzzzzi
+Multa 200 zzzzzzzzzzzzzzzzzzzj
+Multa 201 zzzzzzzzzzzzzzzzzzzk
+Multa 202 zzzzzzzzzzzzzzzzzzzl
+Multa 203 zzzzzzzzzzzzzzzzzzzm
+Multa 204 zzzzzzzzzzzzzzzzzzzn
+Multa 205 zzzzzzzzzzzzzzzzzzzo
+Multa 206 zzzzzzzzzzzzzzzzzzzp
+Multa 207 zzzzzzzzzzzzzzzzzzzq
+Multa 208 zzzzzzzzzzzzzzzzzzzr
+Multa 209 Zzzzzzzzzzzzzzzzzzzs
+Multa 210 Zzzzzzzzzzzzzzzzzzza
+Multa 211 zzzzzzzzzzzzzzzzzzzb
+Multa 212 zzzzzzzzzzzzzzzzzzzc
+Multa 213 zzzzzzzzzzzzzzzzzzzd
+Multa 214 zzzzzzzzzzzzzzzzzzze
+Multa 215 zzzzzzzzzzzzzzzzzzzf
+Multa 216 zzzzzzzzzzzzzzzzzzzg
+Multa 217 zzzzzzzzzzzzzzzzzzzh
+Multa 218 zzzzzzzzzzzzzzzzzzzi
+Multa 219 zzzzzzzzzzzzzzzzzzzj
+Multa 220 zzzzzzzzzzzzzzzzzzzk
+Multa 221 zzzzzzzzzzzzzzzzzzzl
+Multa 222 zzzzzzzzzzzzzzzzzzzm
+Multa 223 zzzzzzzzzzzzzzzzzzzn
+Multa 224 zzzzzzzzzzzzzzzzzzzo
+Multa 225 zzzzzzzzzzzzzzzzzzzp
+Multa 226 zzzzzzzzzzzzzzzzzzzq
+Multa 227 zzzzzzzzzzzzzzzzzzzr
+Multa 228 Zzzzzzzzzzzzzzzzzzzs
+Multa 229 Zzzzzzzzzzzzzzzzzzza
+Multa 230 zzzzzzzzzzzzzzzzzzzb
+Multa 231 zzzzzzzzzzzzzzzzzzzc
+Multa 232 zzzzzzzzzzzzzzzzzzzd
+Multa 233 zzzzzzzzzzzzzzzzzzze
+Multa 234 zzzzzzzzzzzzzzzzzzzf
+Multa 235 zzzzzzzzzzzzzzzzzzzg
+Multa 236 zzzzzzzzzzzzzzzzzzzh
+Multa 237 zzzzzzzzzzzzzzzzzzzi
+Multa 238 zzzzzzzzzzzzzzzzzzzj
+Multa 239 zzzzzzzzzzzzzzzzzzzk
+Multa 240 zzzzzzzzzzzzzzzzzzzl
+Multa 241 zzzzzzzzzzzzzzzzzzzm
+Multa 242 zzzzzzzzzzzzzzzzzzzn
+Multa 243 zzzzzzzzzzzzzzzzzzzo
+Multa 244 zzzzzzzzzzzzzzzzzzzp
+Multa 245 zzzzzzzzzzzzzzzzzzzq
+Multa 246 zzzzzzzzzzzzzzzzzzzr
+Multa 247 Zzzzzzzzzzzzzzzzzzzs
+Multa 248 Zzzzzzzzzzzzzzzzzzza
+Multa 249 zzzzzzzzzzzzzzzzzzzb
+Multa 250 zzzzzzzzzzzzzzzzzzzc
+Multa 251 zzzzzzzzzzzzzzzzzzzd
+Multa 252 zzzzzzzzzzzzzzzzzzze
+Multa 253 zzzzzzzzzzzzzzzzzzzf
+Multa 254 zzzzzzzzzzzzzzzzzzzg
+Multa 255 zzzzzzzzzzzzzzzzzzzh
+Multa 256 zzzzzzzzzzzzzzzzzzzi
+Multa 257 zzzzzzzzzzzzzzzzzzzj
+Multa 258 zzzzzzzzzzzzzzzzzzzk
+Multa 259 zzzzzzzzzzzzzzzzzzzl
+Multa 260 zzzzzzzzzzzzzzzzzzzm
+Multa 261 zzzzzzzzzzzzzzzzzzzn
+Multa 262 zzzzzzzzzzzzzzzzzzzo
+Multa 263 zzzzzzzzzzzzzzzzzzzp
+Multa 264 zzzzzzzzzzzzzzzzzzzq
+Multa 265 zzzzzzzzzzzzzzzzzzzr
+Multa 266 Zzzzzzzzzzzzzzzzzzzs
+Multa 267 Zzzzzzzzzzzzzzzzzzza
+Multa 268 zzzzzzzzzzzzzzzzzzzb
+Multa 269 zzzzzzzzzzzzzzzzzzzc
+Multa 270 zzzzzzzzzzzzzzzzzzzd
+Multa 271 zzzzzzzzzzzzzzzzzzze
+Multa 272 zzzzzzzzzzzzzzzzzzzf
+Multa 273 zzzzzzzzzzzzzzzzzzzg
+Multa 274 zzzzzzzzzzzzzzzzzzzh
+Multa 275 zzzzzzzzzzzzzzzzzzzi
+Multa 276 zzzzzzzzzzzzzzzzzzzj
+Multa 277 zzzzzzzzzzzzzzzzzzzk
+Multa 278 zzzzzzzzzzzzzzzzzzzl
+Multa 279 zzzzzzzzzzzzzzzzzzzm
+Multa 280 zzzzzzzzzzzzzzzzzzzn
+Multa 281 zzzzzzzzzzzzzzzzzzzo
+Multa 282 zzzzzzzzzzzzzzzzzzzp
+Multa 283 zzzzzzzzzzzzzzzzzzzq
+Multa 284 zzzzzzzzzzzzzzzzzzzr
+Multa 285 Zzzzzzzzzzzzzzzzzzzs
+Multa 286 Zzzzzzzzzzzzzzzzzzza
+Multa 287 zzzzzzzzzzzzzzzzzzzb
+Multa 288 zzzzzzzzzzzzzzzzzzzc
+Multa 289 zzzzzzzzzzzzzzzzzzzd
+Multa 290 zzzzzzzzzzzzzzzzzzze
+Multa 291 zzzzzzzzzzzzzzzzzzzf
+Multa 292 zzzzzzzzzzzzzzzzzzzg
+Multa 293 zzzzzzzzzzzzzzzzzzzh
+Multa 294 zzzzzzzzzzzzzzzzzzzi
+Multa 295 zzzzzzzzzzzzzzzzzzzj
+Multa 296 zzzzzzzzzzzzzzzzzzzk
+Multa 297 zzzzzzzzzzzzzzzzzzzl
+Multa 298 zzzzzzzzzzzzzzzzzzzm
+Multa 299 zzzzzzzzzzzzzzzzzzzn
+Multa 300 zzzzzzzzzzzzzzzzzzzo
+Multa 301 zzzzzzzzzzzzzzzzzzzp
+Multa 302 zzzzzzzzzzzzzzzzzzzq
+Multa 303 zzzzzzzzzzzzzzzzzzzr
+Multa 304 Zzzzzzzzzzzzzzzzzzzs
+Multa 305 Zzzzzzzzzzzzzzzzzzza
+Multa 306 zzzzzzzzzzzzzzzzzzzb
+Multa 307 zzzzzzzzzzzzzzzzzzzc
+Multa 308 zzzzzzzzzzzzzzzzzzzd
+Multa 309 zzzzzzzzzzzzzzzzzzze
+Multa 310 zzzzzzzzzzzzzzzzzzzf
+Multa 311 zzzzzzzzzzzzzzzzzzzg
+Multa 312 zzzzzzzzzzzzzzzzzzzh
+Multa 313 zzzzzzzzzzzzzzzzzzzi
+Multa 314 zzzzzzzzzzzzzzzzzzzj
+Multa 315 zzzzzzzzzzzzzzzzzzzk
+Multa 316 zzzzzzzzzzzzzzzzzzzl
+Multa 317 zzzzzzzzzzzzzzzzzzzm
+Multa 318 zzzzzzzzzzzzzzzzzzzn
+Multa 319 zzzzzzzzzzzzzzzzzzzo
+Multa 320 zzzzzzzzzzzzzzzzzzzp
+Multa 321 zzzzzzzzzzzzzzzzzzzq
+Multa 322 zzzzzzzzzzzzzzzzzzzr
+Multa 323 Zzzzzzzzzzzzzzzzzzzs
+Multa 324 Zzzzzzzzzzzzzzzzzzza
+Multa 325 zzzzzzzzzzzzzzzzzzzb
+Multa 326 zzzzzzzzzzzzzzzzzzzc
+Multa 327 zzzzzzzzzzzzzzzzzzzd
+Multa 328 zzzzzzzzzzzzzzzzzzze
+Multa 329 zzzzzzzzzzzzzzzzzzzf
+Multa 330 zzzzzzzzzzzzzzzzzzzg
+Multa 331 zzzzzzzzzzzzzzzzzzzh
+Multa 332 zzzzzzzzzzzzzzzzzzzi
+Multa 333 zzzzzzzzzzzzzzzzzzzj
+Multa 334 zzzzzzzzzzzzzzzzzzzk
+Multa 335 zzzzzzzzzzzzzzzzzzzl
+Multa 336 zzzzzzzzzzzzzzzzzzzm
+Multa 337 zzzzzzzzzzzzzzzzzzzn
+Multa 338 zzzzzzzzzzzzzzzzzzzo
+Multa 339 zzzzzzzzzzzzzzzzzzzp
+Multa 340 zzzzzzzzzzzzzzzzzzzq
+Multa 341 zzzzzzzzzzzzzzzzzzzr
+Multa 342 Zzzzzzzzzzzzzzzzzzzs
+Multa 343 Zzzzzzzzzzzzzzzzzzza
+Multa 344 zzzzzzzzzzzzzzzzzzzb
+Multa 345 zzzzzzzzzzzzzzzzzzzc
+Multa 346 zzzzzzzzzzzzzzzzzzzd
+Multa 347 zzzzzzzzzzzzzzzzzzze
+Multa 348 zzzzzzzzzzzzzzzzzzzf
+Multa 349 zzzzzzzzzzzzzzzzzzzg
+Multa 350 zzzzzzzzzzzzzzzzzzzh
+Multa 351 zzzzzzzzzzzzzzzzzzzi
+Multa 352 zzzzzzzzzzzzzzzzzzzj
+Multa 353 zzzzzzzzzzzzzzzzzzzk
+Multa 354 zzzzzzzzzzzzzzzzzzzl
+Multa 355 zzzzzzzzzzzzzzzzzzzm
+Multa 356 zzzzzzzzzzzzzzzzzzzn
+Multa 357 zzzzzzzzzzzzzzzzzzzo
+Multa 358 zzzzzzzzzzzzzzzzzzzp
+Multa 359 zzzzzzzzzzzzzzzzzzzq
+Multa 360 zzzzzzzzzzzzzzzzzzzr
+Multa 361 Zzzzzzzzzzzzzzzzzzzs
+Multa 362 Zzzzzzzzzzzzzzzzzzza
+Multa 363 zzzzzzzzzzzzzzzzzzzb
+Multa 364 zzzzzzzzzzzzzzzzzzzc
+Multa 365 zzzzzzzzzzzzzzzzzzzd
+Multa 366 zzzzzzzzzzzzzzzzzzze
+Multa 367 zzzzzzzzzzzzzzzzzzzf
+Multa 368 zzzzzzzzzzzzzzzzzzzg
+Multa 369 zzzzzzzzzzzzzzzzzzzh
+Multa 370 zzzzzzzzzzzzzzzzzzzi
+Multa 371 zzzzzzzzzzzzzzzzzzzj
+Multa 372 zzzzzzzzzzzzzzzzzzzk
+Multa 373 zzzzzzzzzzzzzzzzzzzl
+Multa 374 zzzzzzzzzzzzzzzzzzzm
+Multa 375 zzzzzzzzzzzzzzzzzzzn
+Multa 376 zzzzzzzzzzzzzzzzzzzo
+Multa 377 zzzzzzzzzzzzzzzzzzzp
+Multa 378 zzzzzzzzzzzzzzzzzzzq
+Multa 379 zzzzzzzzzzzzzzzzzzzr
+Multa 380 Zzzzzzzzzzzzzzzzzzzs
+Multa 381 Zzzzzzzzzzzzzzzzzzza carteira suspensa
+Multa 382 zzzzzzzzzzzzzzzzzzzb carteira suspensa
+Multa 383 zzzzzzzzzzzzzzzzzzzc carteira suspensa
+Multa 384 zzzzzzzzzzzzzzzzzzzd carteira suspensa
+Multa 385 zzzzzzzzzzzzzzzzzzze carteira suspensa
+Multa 386 zzzzzzzzzzzzzzzzzzzf carteira suspensa
+Multa 387 zzzzzzzzzzzzzzzzzzzg carteira suspensa
+Multa 388 zzzzzzzzzzzzzzzzzzzh carteira suspensa
+Multa 389 zzzzzzzzzzzzzzzzzzzi carteira suspensa
+Multa 390 zzzzzzzzzzzzzzzzzzzj carteira suspensa
+Multa 391 zzzzzzzzzzzzzzzzzzzk carteira suspensa
+Multa 392 zzzzzzzzzzzzzzzzzzzl carteira suspensa
+Multa 393 zzzzzzzzzzzzzzzzzzzm carteira suspensa
+Multa 394 zzzzzzzzzzzzzzzzzzzn carteira suspensa
+Multa 395 zzzzzzzzzzzzzzzzzzzo carteira suspensa
+Multa 396 zzzzzzzzzzzzzzzzzzzp carteira suspensa
+Multa 397 zzzzzzzzzzzzzzzzzzzq carteira suspensa
+Multa 398 zzzzzzzzzzzzzzzzzzzr carteira suspensa
+Multa 399 Zzzzzzzzzzzzzzzzzzzs carteira suspensa
+
+Familia 5
+Multa 1 a
+Multa 2 b
+Multa 3 c
+Multa 4 d
+Multa 5 e
+Multa 6 e
+Multa 7 d
+Multa 8 e
+Multa 9 c
+Multa 10 d
+Multa 11 e
+Multa 12 b
+Multa 13 c
+Multa 14 d
+Multa 15 e
+Multa 16 a
+Multa 17 b
+Multa 18 c
+Multa 19 d
+Multa 20 e
+
diff --git a/boca-1.5.0/index.html b/boca-1.5.0/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/boca-1.5.0/index.html diff --git a/boca-1.5.0/old/C.compare b/boca-1.5.0/old/C.compare new file mode 100755 index 0000000..cc4c63b --- /dev/null +++ b/boca-1.5.0/old/C.compare @@ -0,0 +1,129 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 31/oct/2011 by cassio@ime.usp.br +# +# This script receives: +# $1 team_output +# $2 sol_output +# $3 languagename +# $4 problemname +# $5 problem_input +# +# BOCA reads the last line of the standard output +# and pass it to judges +# +if [ ! -r "$1" -o ! -r "$2" ]; then + echo "Parameter problem" + exit 43 +fi + +# if there is an special checker, use it. It can be defined by an sol_output +# which has .sh extension (which makes it be executed instead of compared to) +# or by the existence of the file bocachecker.$4 in the execution path (here +# $4 is in fact the short problename, which has to match with the spec in BOCA) +schecker= +if [ ${2: -3} == ".sh" ]; then + schecker=$2 + chmod 755 "$schecker" +else + if [ "$4" != "" ]; then + schecker=`which "bocachecker.$4"` + fi +fi +if [ -x "$schecker" ]; then + echo "Calling special checker $schecker" + "$schecker" "$@" + ret=$? + if [ "$ret" == "0" ]; then + echo "Checker answered YES" + exit 4 + fi + if [ "$ret" == "1" ]; then + echo "Checker answered WRONG ANSWER" + exit 6 + fi + if [ "$ret" == "2" ]; then + echo "Checker answered OUTPUT FORMAT ERROR" + exit 5 + fi + echo "special checker returned unknown code" + exit 43 +fi + +# Next lines of this script just compares team_output and sol_output, +# although it is possible to change them to more complex evaluations. + +diff -q "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff \"$1\" \"$2\" # files match" + echo "Files match exactly" + exit 4 +fi +diff -q -b "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b \"$1\" \"$2\" # files match" + echo -e "diff -c \"$1\" \"$2\" # files dont match - see output" + diff -c "$1" "$2" + echo "Files match with differences in the amount of white spaces" + exit 5 +fi +diff -q -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b \"$1\" \"$2\" # files dont match - see output" + diff -c -b "$1" "$2" + echo "Files match with differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -i -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B "$1" "$2" + echo "Files match if we ignore case and differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B "$1" "$2" + echo "Files match if we discard all white spaces" + exit 5 +fi +diff -q -i -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B -w "$1" "$2" + echo "Files match if we ignore case and discard all white spaces" + exit 5 +fi +wd=`which wdiff` +if [ "$wd" != "" ]; then + wdiff \"$1\" \"$2\" >/dev/null 2>/dev/null + if [ "$?" == "0" ]; then + echo -e "wdiff \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B -w "$1" "$2" + echo "BUT Files match if we compare word by word, ignoring everything else, using wdiff" + echo "diff has a bug that, if a line contains a single space, this is not discarded by -w" + exit 5 + fi +fi +echo -e "### files dont match - see output" +diff -c -i -b -B -w "$1" "$2" +echo "Differences found" +exit 6 diff --git a/boca-1.5.0/old/C.run b/boca-1.5.0/old/C.run new file mode 100755 index 0000000..6336c09 --- /dev/null +++ b/boca-1.5.0/old/C.run @@ -0,0 +1,141 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 17/oct/2011 by cassio@ime.usp.br +# +# parameters are: +# $1 base_filename +# $2 source_file +# $3 input_file +# $4 languagename +# $5 problemname +# $6 timelimit +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened (according to safeexec): +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 +id -u bocajail >/dev/null 2>/dev/null +if [ $? == 0 ]; then + bocau=`id -u bocajail` + bocag=`id -g bocajail` + chown bocajail.nogroup . +else + bocau=`id -u nobody` + bocag=`id -g nobody` + chown nobody.nogroup . +fi +if [ "$bocau" == "" -o "$bocag" == "" ]; then + echo "error finding user to run script" + exit 43 +fi + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec +gcc=`which gcc` +[ -x "$gcc" ] || gcc=/usr/bin/gcc + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then + echo "parameter problem" + exit 43 +fi +if [ ! -r $2 ]; then + echo "$2 not found or it's not readable" + exit 44 +fi +if [ ! -r $3 ]; then + echo "$3 not found or it's not readable" + exit 45 +fi +if [ ! -x $sf ]; then + echo "$sf not found or it's not executable" + exit 46 +fi +if [ ! -x $gcc ]; then + echo "$gcc not found or it's not executable" + exit 47 +fi + +prefix=$1 +name=$2 +input=$3 + +# setting up the timelimit according to the problem +if [ "$6" == "" ]; then +time=5 +else +time=$6 +fi +let ttime=$time+30 + +$gcc -O2 -lm -o $prefix "$name" +ret=$? +if [ "$ret" != "0" ]; then + echo "Compilation Error: $ret" + exit 1 +else + cdir=`pwd` + echo "Current directory is $cdir" >&2 + echo $cdir | grep -q "/bocajail" + if [ $? == 0 ]; then + cdir=`echo $cdir | sed "s/.*\/bocajail//"` + cat <<EOF > runit.sh +#!/bin/bash +[ -f /proc/cpuinfo ] || /bin/mount -t proc proc /proc +#/bin/mount --bind /dev /dev +[ -d /sys/kernel ] || /bin/mount -t sysfs sysfs /sys +cd $cdir +$sf -F10 -n0 -U$bocau -G$bocag -C. -ostdout0 -estderr0 -d512000 -m512000 -f20000 -t$time -T$ttime -i$input ./$prefix +echo \$? > runit.retcode +/bin/umount /proc 2>/dev/null +#/bin/umount /dev +/bin/umount /sys 2>/dev/null +EOF + chmod 755 runit.sh + chroot /bocajail $cdir/runit.sh + ret=`cat runit.retcode` + if [ "$ret" == "" ]; then + echo "Execution error - check autojudging" + exit 49 + fi + else + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 + $sf -F10 -n0 -C. -U$bocau -G$bocag -ostdout0 -estderr0 -d512000000 -m512000000 -t$time -T$ttime -i$input ./$prefix + ret=$? + fi + if [ $ret -gt 10 ]; then + ret=0 + fi +fi +if [ -f stdout0 ]; then + cat stdout0 +fi +exit $ret diff --git a/boca-1.5.0/old/Cpp.compare b/boca-1.5.0/old/Cpp.compare new file mode 100755 index 0000000..cc4c63b --- /dev/null +++ b/boca-1.5.0/old/Cpp.compare @@ -0,0 +1,129 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 31/oct/2011 by cassio@ime.usp.br +# +# This script receives: +# $1 team_output +# $2 sol_output +# $3 languagename +# $4 problemname +# $5 problem_input +# +# BOCA reads the last line of the standard output +# and pass it to judges +# +if [ ! -r "$1" -o ! -r "$2" ]; then + echo "Parameter problem" + exit 43 +fi + +# if there is an special checker, use it. It can be defined by an sol_output +# which has .sh extension (which makes it be executed instead of compared to) +# or by the existence of the file bocachecker.$4 in the execution path (here +# $4 is in fact the short problename, which has to match with the spec in BOCA) +schecker= +if [ ${2: -3} == ".sh" ]; then + schecker=$2 + chmod 755 "$schecker" +else + if [ "$4" != "" ]; then + schecker=`which "bocachecker.$4"` + fi +fi +if [ -x "$schecker" ]; then + echo "Calling special checker $schecker" + "$schecker" "$@" + ret=$? + if [ "$ret" == "0" ]; then + echo "Checker answered YES" + exit 4 + fi + if [ "$ret" == "1" ]; then + echo "Checker answered WRONG ANSWER" + exit 6 + fi + if [ "$ret" == "2" ]; then + echo "Checker answered OUTPUT FORMAT ERROR" + exit 5 + fi + echo "special checker returned unknown code" + exit 43 +fi + +# Next lines of this script just compares team_output and sol_output, +# although it is possible to change them to more complex evaluations. + +diff -q "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff \"$1\" \"$2\" # files match" + echo "Files match exactly" + exit 4 +fi +diff -q -b "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b \"$1\" \"$2\" # files match" + echo -e "diff -c \"$1\" \"$2\" # files dont match - see output" + diff -c "$1" "$2" + echo "Files match with differences in the amount of white spaces" + exit 5 +fi +diff -q -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b \"$1\" \"$2\" # files dont match - see output" + diff -c -b "$1" "$2" + echo "Files match with differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -i -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B "$1" "$2" + echo "Files match if we ignore case and differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B "$1" "$2" + echo "Files match if we discard all white spaces" + exit 5 +fi +diff -q -i -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B -w "$1" "$2" + echo "Files match if we ignore case and discard all white spaces" + exit 5 +fi +wd=`which wdiff` +if [ "$wd" != "" ]; then + wdiff \"$1\" \"$2\" >/dev/null 2>/dev/null + if [ "$?" == "0" ]; then + echo -e "wdiff \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B -w "$1" "$2" + echo "BUT Files match if we compare word by word, ignoring everything else, using wdiff" + echo "diff has a bug that, if a line contains a single space, this is not discarded by -w" + exit 5 + fi +fi +echo -e "### files dont match - see output" +diff -c -i -b -B -w "$1" "$2" +echo "Differences found" +exit 6 diff --git a/boca-1.5.0/old/Cpp.run b/boca-1.5.0/old/Cpp.run new file mode 100755 index 0000000..6c6d7ea --- /dev/null +++ b/boca-1.5.0/old/Cpp.run @@ -0,0 +1,142 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 17/oct/2011 by cassio@ime.usp.br +# +# parameters are: +# $1 base_filename +# $2 source_file +# $3 input_file +# $4 languagename +# $5 problemname +# $6 timelimit +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened: +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 +id -u bocajail >/dev/null 2>/dev/null +if [ $? == 0 ]; then + bocau=`id -u bocajail` + bocag=`id -g bocajail` + chown bocajail.nogroup . +else + bocau=`id -u nobody` + bocag=`id -g nobody` + chown nobody.nogroup . +fi +if [ "$bocau" == "" -o "$bocag" == "" ]; then + echo "error finding user to run script" + exit 43 +fi + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec +gpp=`which g++` +[ -x "$gpp" ] || gcc=/usr/bin/g++ + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then + echo "parameter problem" + exit 43 +fi +if [ ! -r $2 ]; then + echo "$2 not found or it's not readable" + exit 44 +fi +if [ ! -r $3 ]; then + echo "$3 not found or it's not readable" + exit 45 +fi +if [ ! -x $sf ]; then + echo "$sf not found or it's not executable" + exit 46 +fi +if [ ! -x $gpp ]; then + echo "$gpp not found or it's not executable" + exit 47 +fi + +prefix=$1 +name=$2 +input=$3 + +# setting up the timelimit according to the problem +# note that problems should spelling the same as inside BOCA +if [ "$6" == "" ]; then +time=5 +else +time=$6 +fi +let ttime=$time+30 + +$gpp -O2 -lm -o $prefix "$name" +ret=$? +if [ "$ret" != "0" ]; then + echo "Compiling Error: $ret" + exit 1 +else + cdir=`pwd` + echo "Current directory is $cdir" >&2 + echo $cdir | grep -q "/bocajail" + if [ $? == 0 ]; then + cdir=`echo $cdir | sed "s/.*\/bocajail//"` + cat <<EOF > runit.sh +#!/bin/bash +[ -f /proc/cpuinfo ] || /bin/mount -t proc proc /proc +#/bin/mount --bind /dev /dev +[ -d /sys/kernel ] || /bin/mount -t sysfs sysfs /sys +cd $cdir +$sf -F10 -t$time -T$ttime -i$input -ostdout0 -estderr0 -U$bocau -G$bocag -n0 -C. -f20000 -d512000 -m512000 ./$prefix +echo \$? > runit.retcode +/bin/umount /proc 2>/dev/null +#/bin/umount /dev +/bin/umount /sys 2>/dev/null +EOF + chmod 755 runit.sh + chroot /bocajail $cdir/runit.sh + ret=`cat runit.retcode` + if [ "$ret" == "" ]; then + echo "Execution error - check autojudging" + exit 49 + fi + else + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 + $sf -F10 -n0 -C. -U$bocau -G$bocag -ostdout0 -estderr0 -d512000000 -m512000000 -t$time -T$ttime -i$input ./$prefix + ret=$? + fi + if [ $ret -gt 10 ]; then + ret=0 + fi +fi +if [ -f stdout0 ]; then + cat stdout0 +fi +exit $ret diff --git a/boca-1.5.0/old/Java.compare b/boca-1.5.0/old/Java.compare new file mode 100755 index 0000000..cc4c63b --- /dev/null +++ b/boca-1.5.0/old/Java.compare @@ -0,0 +1,129 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 31/oct/2011 by cassio@ime.usp.br +# +# This script receives: +# $1 team_output +# $2 sol_output +# $3 languagename +# $4 problemname +# $5 problem_input +# +# BOCA reads the last line of the standard output +# and pass it to judges +# +if [ ! -r "$1" -o ! -r "$2" ]; then + echo "Parameter problem" + exit 43 +fi + +# if there is an special checker, use it. It can be defined by an sol_output +# which has .sh extension (which makes it be executed instead of compared to) +# or by the existence of the file bocachecker.$4 in the execution path (here +# $4 is in fact the short problename, which has to match with the spec in BOCA) +schecker= +if [ ${2: -3} == ".sh" ]; then + schecker=$2 + chmod 755 "$schecker" +else + if [ "$4" != "" ]; then + schecker=`which "bocachecker.$4"` + fi +fi +if [ -x "$schecker" ]; then + echo "Calling special checker $schecker" + "$schecker" "$@" + ret=$? + if [ "$ret" == "0" ]; then + echo "Checker answered YES" + exit 4 + fi + if [ "$ret" == "1" ]; then + echo "Checker answered WRONG ANSWER" + exit 6 + fi + if [ "$ret" == "2" ]; then + echo "Checker answered OUTPUT FORMAT ERROR" + exit 5 + fi + echo "special checker returned unknown code" + exit 43 +fi + +# Next lines of this script just compares team_output and sol_output, +# although it is possible to change them to more complex evaluations. + +diff -q "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff \"$1\" \"$2\" # files match" + echo "Files match exactly" + exit 4 +fi +diff -q -b "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b \"$1\" \"$2\" # files match" + echo -e "diff -c \"$1\" \"$2\" # files dont match - see output" + diff -c "$1" "$2" + echo "Files match with differences in the amount of white spaces" + exit 5 +fi +diff -q -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b \"$1\" \"$2\" # files dont match - see output" + diff -c -b "$1" "$2" + echo "Files match with differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -i -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B "$1" "$2" + echo "Files match if we ignore case and differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B "$1" "$2" + echo "Files match if we discard all white spaces" + exit 5 +fi +diff -q -i -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B -w "$1" "$2" + echo "Files match if we ignore case and discard all white spaces" + exit 5 +fi +wd=`which wdiff` +if [ "$wd" != "" ]; then + wdiff \"$1\" \"$2\" >/dev/null 2>/dev/null + if [ "$?" == "0" ]; then + echo -e "wdiff \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B -w "$1" "$2" + echo "BUT Files match if we compare word by word, ignoring everything else, using wdiff" + echo "diff has a bug that, if a line contains a single space, this is not discarded by -w" + exit 5 + fi +fi +echo -e "### files dont match - see output" +diff -c -i -b -B -w "$1" "$2" +echo "Differences found" +exit 6 diff --git a/boca-1.5.0/old/Java.run b/boca-1.5.0/old/Java.run new file mode 100755 index 0000000..7708811 --- /dev/null +++ b/boca-1.5.0/old/Java.run @@ -0,0 +1,160 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 17/oct/2011 by cassio@ime.usp.br +# +# parameters are: +# $1 base_filename +# $2 source_file +# $3 input_file +# $4 languagename +# $5 problemname +# $6 timelimit +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened: +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 +id -u bocajail >/dev/null 2>/dev/null +if [ $? == 0 ]; then + bocau=`id -u bocajail` + bocag=`id -g bocajail` + chown bocajail.nogroup . +else + bocau=`id -u nobody` + bocag=`id -g nobody` + chown nobody.nogroup . +fi +if [ "$bocau" == "" -o "$bocag" == "" ]; then + echo "error finding user to run script" + exit 43 +fi + +export CLASSPATH=.:$CLASSPATH + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec +java=`which java` +[ -x "$java" ] || java=/usr/java/bin/java +javac=`which javac` +[ -x "$javac" ] || javac=/usr/java/bin/javac + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then + echo "parameter problem" + exit 43 +fi +if [ ! -r $2 ]; then + echo "$2 not found or it's not readable" + exit 44 +fi +if [ ! -r $3 ]; then + echo "$3 not found or it's not readable" + exit 45 +fi +if [ ! -x $sf ]; then + echo "$sf not found or it's not executable" + exit 46 +fi +if [ ! -x $java ]; then + echo "$java not found or it's not executable" + exit 47 +fi +if [ ! -x $javac ]; then + echo "$javac not found or it's not executable" + exit 47 +fi + +prefix=$1 +name=$2 +input=$3 + +# setting up the timelimit according to the problem +# note that problems should spelling the same as inside BOCA +if [ "$6" == "" ]; then +time=5 +else +time=$6 +fi +let ttime=$time+30 + +$javac "$name" +ret=$? +if [ "$ret" != "0" ]; then + echo "Compilation Error: $ret" + exit 1 +else + if [ ! -f "$prefix.class" ]; then + echo "Class file $prefix.class not generated - possible name mismatch" + exit 48 + fi + cdir=`pwd` + echo "Current directory is $cdir" >&2 + echo $cdir | grep -q "/bocajail" + if [ $? == 0 ]; then + cdir=`echo $cdir | sed "s/.*\/bocajail//"` + cat <<EOF > runit.sh +#!/bin/bash +[ -f /proc/cpuinfo ] || /bin/mount -t proc proc /proc +#/bin/mount --bind /dev /dev +[ -d /sys/kernel ] || /bin/mount -t sysfs sysfs /sys +cd $cdir +$sf -t$time -T$ttime -i$input -F256 -u256 -ostdout0 -estderr0 -U$bocau -G$bocag -n0 -C. -f20000 -d1000000 -m1000000 -- $java -Xmx512M -Xms512M $prefix +echo \$? > runit.retcode +/bin/umount /proc 2>/dev/null +#/bin/umount /dev +/bin/umount /sys 2>/dev/null +EOF + chmod 755 runit.sh + chroot /bocajail $cdir/runit.sh + ret=`cat runit.retcode` + if [ "$ret" == "" ]; then + echo "Execution error - check autojudging" + exit 49 + fi + if [ $ret -gt 10 ]; then + echo "> > > > > > > Nonzero return code - possible runtime error - GUESSING IT IS RUNTIME ERROR! < < < < < < < <" + exit 9 + fi + else + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 + echo "CODE NOT BEING CHROOTED. DO NOT RUN THIS ON THE MAIN SERVER" >&2 +# $java $prefix < $input + $sf -t$time -T$ttime -i$input -F256 -u256 -U$bocau -G$bocag -ostdout0 -estderr0 -n0 -C. -d900000000 -m900000000 -- $java -Xmx512M -Xms512M $prefix + ret=$? + fi + if [ $ret -gt 10 ]; then + echo "> > > > > > > Nonzero return code - possible runtime error - GUESSING IT IS RUNTIME ERROR! < < < < < < < <" + ret=9 + fi +fi +if [ -f stdout0 ]; then + cat stdout0 +fi +exit $ret diff --git a/boca-1.5.0/old/Pascal.compare b/boca-1.5.0/old/Pascal.compare new file mode 100755 index 0000000..cc4c63b --- /dev/null +++ b/boca-1.5.0/old/Pascal.compare @@ -0,0 +1,129 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 31/oct/2011 by cassio@ime.usp.br +# +# This script receives: +# $1 team_output +# $2 sol_output +# $3 languagename +# $4 problemname +# $5 problem_input +# +# BOCA reads the last line of the standard output +# and pass it to judges +# +if [ ! -r "$1" -o ! -r "$2" ]; then + echo "Parameter problem" + exit 43 +fi + +# if there is an special checker, use it. It can be defined by an sol_output +# which has .sh extension (which makes it be executed instead of compared to) +# or by the existence of the file bocachecker.$4 in the execution path (here +# $4 is in fact the short problename, which has to match with the spec in BOCA) +schecker= +if [ ${2: -3} == ".sh" ]; then + schecker=$2 + chmod 755 "$schecker" +else + if [ "$4" != "" ]; then + schecker=`which "bocachecker.$4"` + fi +fi +if [ -x "$schecker" ]; then + echo "Calling special checker $schecker" + "$schecker" "$@" + ret=$? + if [ "$ret" == "0" ]; then + echo "Checker answered YES" + exit 4 + fi + if [ "$ret" == "1" ]; then + echo "Checker answered WRONG ANSWER" + exit 6 + fi + if [ "$ret" == "2" ]; then + echo "Checker answered OUTPUT FORMAT ERROR" + exit 5 + fi + echo "special checker returned unknown code" + exit 43 +fi + +# Next lines of this script just compares team_output and sol_output, +# although it is possible to change them to more complex evaluations. + +diff -q "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff \"$1\" \"$2\" # files match" + echo "Files match exactly" + exit 4 +fi +diff -q -b "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b \"$1\" \"$2\" # files match" + echo -e "diff -c \"$1\" \"$2\" # files dont match - see output" + diff -c "$1" "$2" + echo "Files match with differences in the amount of white spaces" + exit 5 +fi +diff -q -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b \"$1\" \"$2\" # files dont match - see output" + diff -c -b "$1" "$2" + echo "Files match with differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -i -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B "$1" "$2" + echo "Files match if we ignore case and differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B "$1" "$2" + echo "Files match if we discard all white spaces" + exit 5 +fi +diff -q -i -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B -w "$1" "$2" + echo "Files match if we ignore case and discard all white spaces" + exit 5 +fi +wd=`which wdiff` +if [ "$wd" != "" ]; then + wdiff \"$1\" \"$2\" >/dev/null 2>/dev/null + if [ "$?" == "0" ]; then + echo -e "wdiff \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B -w "$1" "$2" + echo "BUT Files match if we compare word by word, ignoring everything else, using wdiff" + echo "diff has a bug that, if a line contains a single space, this is not discarded by -w" + exit 5 + fi +fi +echo -e "### files dont match - see output" +diff -c -i -b -B -w "$1" "$2" +echo "Differences found" +exit 6 diff --git a/boca-1.5.0/old/Pascal.run b/boca-1.5.0/old/Pascal.run new file mode 100755 index 0000000..df98e41 --- /dev/null +++ b/boca-1.5.0/old/Pascal.run @@ -0,0 +1,107 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 25/may/2010 by cassiopc +# +# parameters are: +# $1 base_filename +# $2 source_file +# $3 input_file +# $4 languagename +# $5 problemname +# $6 timelimit +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened: +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 +chown nobody.nogroup . + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +grep=`which grep` +[ -x "$grep" ] || grep=/bin/grep +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec +pascal=`which fpc` +[ -x "$pascal" ] || pascal=/usr/bin/fpc + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then + echo "parameter problem" + exit 43 +fi +if [ ! -r $2 ]; then + echo "$2 not found or it's not readable" + exit 44 +fi +if [ ! -r $3 ]; then + echo "$3 not found or it's not readable" + exit 45 +fi +if [ ! -x $sf ]; then + echo "$sf not found or it's not executable" + exit 46 +fi +if [ ! -x $pascal ]; then + echo "$pascal not found or it's not executable" + exit 47 +fi + +prefix=$1 +name=$2 +input=$3 + +# setting up the timelimit according to the problem +# note that problems should spelling the same as inside BOCA +if [ "$6" == "" ]; then +time=5 +else +time=$6 +fi +let ttime=$time+30 + +$pascal -o$prefix $name >compiler.out 2>compiler.out +$grep -irq linking compiler.out +ret=$? +$grep -irq "lines compiled" compiler.out +ret2=$? +if [ "$ret" != "0" -o "$ret2" != "0" ]; then + cat compiler.out + echo "Compiling Error: $ret" + exit 1 +else + $sf -F10 -t$time -T$ttime -i$input -opascal.out -n0 -R. ./$prefix + ret=$? + if [ -f pascal.out ]; then + cat pascal.out + $grep -irq "runtime error" pascal.out + ret2=$? + if [ "$ret2" = "0" ]; then + echo "Strange output - possible runtime error" + if [ $ret -lt 4 ]; then + ret=48 + fi + fi + else + echo "Output file not found - possible runtime error" + fi +fi +exit $ret diff --git a/boca-1.5.0/old/compare.sh b/boca-1.5.0/old/compare.sh new file mode 100755 index 0000000..cc4c63b --- /dev/null +++ b/boca-1.5.0/old/compare.sh @@ -0,0 +1,129 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 31/oct/2011 by cassio@ime.usp.br +# +# This script receives: +# $1 team_output +# $2 sol_output +# $3 languagename +# $4 problemname +# $5 problem_input +# +# BOCA reads the last line of the standard output +# and pass it to judges +# +if [ ! -r "$1" -o ! -r "$2" ]; then + echo "Parameter problem" + exit 43 +fi + +# if there is an special checker, use it. It can be defined by an sol_output +# which has .sh extension (which makes it be executed instead of compared to) +# or by the existence of the file bocachecker.$4 in the execution path (here +# $4 is in fact the short problename, which has to match with the spec in BOCA) +schecker= +if [ ${2: -3} == ".sh" ]; then + schecker=$2 + chmod 755 "$schecker" +else + if [ "$4" != "" ]; then + schecker=`which "bocachecker.$4"` + fi +fi +if [ -x "$schecker" ]; then + echo "Calling special checker $schecker" + "$schecker" "$@" + ret=$? + if [ "$ret" == "0" ]; then + echo "Checker answered YES" + exit 4 + fi + if [ "$ret" == "1" ]; then + echo "Checker answered WRONG ANSWER" + exit 6 + fi + if [ "$ret" == "2" ]; then + echo "Checker answered OUTPUT FORMAT ERROR" + exit 5 + fi + echo "special checker returned unknown code" + exit 43 +fi + +# Next lines of this script just compares team_output and sol_output, +# although it is possible to change them to more complex evaluations. + +diff -q "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff \"$1\" \"$2\" # files match" + echo "Files match exactly" + exit 4 +fi +diff -q -b "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b \"$1\" \"$2\" # files match" + echo -e "diff -c \"$1\" \"$2\" # files dont match - see output" + diff -c "$1" "$2" + echo "Files match with differences in the amount of white spaces" + exit 5 +fi +diff -q -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b \"$1\" \"$2\" # files dont match - see output" + diff -c -b "$1" "$2" + echo "Files match with differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -i -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B "$1" "$2" + echo "Files match if we ignore case and differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B "$1" "$2" + echo "Files match if we discard all white spaces" + exit 5 +fi +diff -q -i -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B -w "$1" "$2" + echo "Files match if we ignore case and discard all white spaces" + exit 5 +fi +wd=`which wdiff` +if [ "$wd" != "" ]; then + wdiff \"$1\" \"$2\" >/dev/null 2>/dev/null + if [ "$?" == "0" ]; then + echo -e "wdiff \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B -w "$1" "$2" + echo "BUT Files match if we compare word by word, ignoring everything else, using wdiff" + echo "diff has a bug that, if a line contains a single space, this is not discarded by -w" + exit 5 + fi +fi +echo -e "### files dont match - see output" +diff -c -i -b -B -w "$1" "$2" +echo "Differences found" +exit 6 diff --git a/boca-1.5.0/old/connect.php b/boca-1.5.0/old/connect.php new file mode 100644 index 0000000..1ee33da --- /dev/null +++ b/boca-1.5.0/old/connect.php @@ -0,0 +1,44 @@ +<?php +////////////////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +/////////////////////////////////////////////////////////////////////////////////////////// +// created 14/June/2011 by cassio@ime.usp.br +require('header.php'); + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); +if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +$fn = tempnam("/tmp","bkp-"); +$fout = fopen($fn,"wb"); +echo $_POST; +echo $_POST['data']; +fwrite($fout,base64_decode($_POST['data'])); +fclose($fout); +$size=filesize($fn); +$name=$_POST['name']; +if ($size > $ct["contestmaxfilesize"] || strlen($name)>100 || strlen($name)<1) { + LOGLevel("User {$_SESSION["usertable"]["username"]} tried to submit file " . + ":${name}: with $size bytes.", 1); + MSGError("File size exceeds the limit allowed or invalid name."); +} else + + DBNewBkp ($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], + $name, + $fn, $size); +@unlink($fn); +ForceLoad("../index.php"); +?> diff --git a/boca-1.5.0/old/create-import-file.sh b/boca-1.5.0/old/create-import-file.sh new file mode 100755 index 0000000..0d3ca9e --- /dev/null +++ b/boca-1.5.0/old/create-import-file.sh @@ -0,0 +1,197 @@ +#!/bin/bash +# Copyright (c) 2007- C. P. de Campos (cassio@ime.usp.br). All rights reserved. +# Licensed under Q Public License version 1.0. See http://www.opensource.org/licenses/qtpl.php + +for i in /usr/bin/cut /bin/cat /bin/date /usr/bin/basename /bin/true /usr/bin/uuencode /usr/bin/wc /usr/bin/tail; do + if [ ! -x $i ]; then + echo "$i not found. Aborting" + exit 1 + fi +done + +if [ "$1" == "" -o "$2" == "" -o ! -d "$2" -o ! -r "$2" ]; then + echo "Usage $0 <filename> <directory>" + echo "filename will be overwritten." + echo "directory must contain the following files:" + echo " *.run: where * is a language name." + echo " *.compare: where * is a language name." + echo " *.in: where * is a problem name." + echo " *.out: where * is a problem name." + echo " *.pdf: where * is a problem name." + echo " For better compatibility, use only letters in filenames (avoid spaces, symbols, etc)." + exit 1 +fi +file=$1 +dir=$2 + +d=`/bin/date +%s` +endmark=endmark$d + +echo -n "Enter the contest name: " +read name + +echo -n "Enter your site name: " +read site + +st=$d +while /bin/true; do + echo -n "Enter starting date (format complying with /bin/date. For example, '12/25/2007 13:34'): " + read data + st=`/bin/date -d "$data" +%s` + if [ $? == 0 ]; then + break + fi +done + +echo "Creating contest, site and answer sections" +/bin/cat << EOFEOF > $file +$endmark + +[contest] +contestname=$name +scorelevel=4 +sitename=$site +startdate=$st + +[site] + +[answer] +answernumber=1 +answername=NO - Compile error +answeryes=f + +answernumber=2 +answername=NO - Runtime error +answeryes=f + +answernumber=3 +answername=NO - Time limit exceeded +answeryes=f + +answernumber=4 +answername=YES +answeryes=t + +answernumber=5 +answername=NO - Presentation error +answeryes=f + +answernumber=6 +answername=NO - Wrong answer +answeryes=f + +answernumber=7 +answername=NO - Contact staff +answeryes=f + +answernumber=8 +answername=NO - Problem/File name mismatch +answeryes=f + +EOFEOF + +echo "Creating language section" +echo "[language]" >> $file + +j=1 +for i in $dir/*.run ; do + lang=`/usr/bin/basename "$i" .run` + echo "Creating $lang" + mds=`/usr/bin/md5sum $i | /usr/bin/cut -d" " -f1` + mdc=`/usr/bin/md5sum $dir/$lang.compare | /usr/bin/cut -d" " -f1` + + echo -n "Enter language name: " + read name + + /usr/bin/uuencode -m x < $dir/$lang.run > $file.tmp + lin=`/usr/bin/wc -l $file.tmp | /usr/bin/cut -d" " -f1` + let lin="$lin - 1" + + /bin/cat << EOFEOF >> $file +langnumber=$j +langname=$name +langscriptmd5=$mds +langcompscriptmd5=$mdc +langscript=base64:$lang.run +EOFEOF + /usr/bin/tail -n $lin $file.tmp >> $file + echo "***${endmark}***" >> $file + + /usr/bin/uuencode -m x < $dir/$lang.compare > $file.tmp + lin=`/usr/bin/wc -l $file.tmp | /usr/bin/cut -d" " -f1` + let lin="$lin - 1" + echo "langcompscript=base64:$lang.compare" >> $file + /usr/bin/tail -n $lin $file.tmp >> $file + echo "***${endmark}***" >> $file + + echo "" >> $file + let j="$j + 1" +done + +echo "Creating problem section" +echo "[problem]" >> $file +letters="A B C D E F G H I J K L M N O P Q R S T U V W X Y Z" + +j=1 +for i in $dir/*.out ; do + prob=`/usr/bin/basename "$i" .out` + letter=`echo $letters | /usr/bin/cut -d" " -f$j` + echo "Creating problem $letter (basename=$prob)" + + echo -n "Enter full name: " + read full + echo -n "Enter time limit: " + read tl + echo -n "Enter Color name: " + read cn + echo -n "Enter Color (html RGB format): " + read rgb + + /bin/cat << EOFEOF >> $file +probnumber=$j +probname=$letter +probfullname=$full +probbasename=$prob +probtimelimit=$tl +probcolorname=$cn +probcolor=$rgb +EOFEOF + + if [ -r $dir/$prob.in ]; then + mds=`/usr/bin/md5sum $dir/$prob.in | /usr/bin/cut -d" " -f1` + echo "probinputfilemd5=$mds" >> $file + echo "probinputfile=base64:$prob.in" >> $file + /usr/bin/uuencode -m x < $dir/$prob.in > $file.tmp + lin=`/usr/bin/wc -l $file.tmp | /usr/bin/cut -d" " -f1` + let lin="$lin - 1" + /usr/bin/tail -n $lin $file.tmp >> $file + echo "***${endmark}***" >> $file + fi + if [ -r $dir/$prob.out ]; then + mds=`/usr/bin/md5sum $dir/$prob.out | /usr/bin/cut -d" " -f1` + echo "probsolfilemd5=$mds" >> $file + echo "probsolfile=base64:$prob.out" >> $file + /usr/bin/uuencode -m x < $dir/$prob.out > $file.tmp + lin=`/usr/bin/wc -l $file.tmp | /usr/bin/cut -d" " -f1` + let lin="$lin - 1" + /usr/bin/tail -n $lin $file.tmp >> $file + echo "***${endmark}***" >> $file + fi + if [ -r $dir/$prob.pdf ]; then + mds=`/usr/bin/md5sum $dir/$prob.pdf | /usr/bin/cut -d" " -f1` + echo "probdescfilemd5=$mds" >> $file + echo "probdescfile=base64:$prob.pdf" >> $file + /usr/bin/uuencode -m x < $dir/$prob.pdf > $file.tmp + lin=`/usr/bin/wc -l $file.tmp | /usr/bin/cut -d" " -f1` + let lin="$lin - 1" + /usr/bin/tail -n $lin $file.tmp >> $file + echo "***${endmark}***" >> $file + fi + + echo "" >> $file + let j="$j + 1" +done + +echo "[end]" >> $file +rm -f $file.tmp +echo "Done." diff --git a/boca-1.5.0/old/getextdata.old b/boca-1.5.0/old/getextdata.old new file mode 100644 index 0000000..7c9955d --- /dev/null +++ b/boca-1.5.0/old/getextdata.old @@ -0,0 +1,931 @@ +<?php +////////////////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator. Copyright (c) 2003-2004 Cassio Polpo de Campos. +//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +/////////////////////////////////////////////////////////////////////////////////////////// + +//retorna ip do cliente +function getIP() { + if (getenv("HTTP_CLIENT_IP")) + $ip = getenv("HTTP_CLIENT_IP"); + else + if(getenv("HTTP_X_FORWARDED_FOR")) + $ip = getenv("HTTP_X_FORWARDED_FOR"); + else + if(getenv("REMOTE_ADDR")) + $ip = getenv("REMOTE_ADDR"); + else + $ip = "UNKNOWN"; + $ip = strtok ($ip, ","); + return $ip; +} +//para compatibilidade com versoes velhas e novas do php +function DB_lo_open($conn, $file, $mode) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loopen ($conn, $file, $mode); + else + return pg_lo_open ($conn, $file, $mode); +} +function DB_lo_read_all($id) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loreadall ($id); + else + return pg_lo_read_all ($id); +} +function DB_lo_import($conn, $file) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loimport ($file, $conn); + else + return pg_lo_import ($conn, $file); +} +function DB_lo_close($id) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loclose ($id); + else + return pg_lo_close ($id); +} +function DB_lo_unlink($c,$id) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_lounlink ($id,$c); + else + return pg_lo_unlink ($c,$id); +} +function DB_lo_create($conn) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_locreate ($conn); + else + return pg_lo_create ($conn); +} +function DB_lo_write($fp, $data) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_lowrite ($fp, $data); + else + return pg_lo_write ($fp, $data); +} +function DB_lo_read($fp, $len) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loread ($fp, $len); + else + return pg_lo_read ($fp, $len); +} + +//abrir conexao com o banco de dados +function DBConnect() { + $dbconn="host=localhost dbname=bocadb user=bocauser password=boca"; + $conn = pg_connect ($dbconn); + if (!$conn) { + echo "Unable to connect to local database\n"; + return null; + } + return $conn; +} +function DBExtConnect($c, $contest, $site) { + $r = DBExec($c, "select * from sitetable where sitenumber=$site and contestnumber=$contest"); + if (DBnLines($r)==0) { + echo "Unable to find the site in the database (site=$site, contest=$contest).\n"; + exit; + } + $st = DBRow($r,0); + + if(($f = file("sqlpass.php"))===false) $pass="boca"; + else $pass=trim($f[1]); + + // gambiarra para testar se a conexao esta de pe + $fp = fsockopen ($st["siteip"], 5432, $errno, $errstr, 10); + if (!$fp) { + echo "$errstr ($errno). Aborting this connection (ip=".$st["siteip"].").\n"; + return null; + } + fclose ($fp); + // se a conexao cair entre o teste acima e o connect abaixo, esse script pode demorar ate + // dar o timeout (no meu teste foram cerca de 3min para cada timeout) + + $conn = pg_connect ("host=" . $st["siteip"] . " dbname=bocadb user=bocauser password=$pass"); + if (!$conn) { + echo "Unable to connect to site $site (ip=".$st["siteip"].")\n"; + return null; + } + echo "Connected to " .$st["siteip"].". Let's exchange data...\n"; + return $conn; +} + +function GetExternalData ($contest) { + $c = DBConnect(); + if ($c==null) return; + $r = DBExec($c, "select * from contesttable where contestnumber=$contest"); + if (DBnLines($r)==0) { + echo "Unable to find the contest $contest in the database.\n"; + exit; + } + $ct = DBRow($r,0); + $localsite = $ct["contestlocalsite"]; + $mainsite = $ct["contestmainsite"]; + + if ($mainsite!=$localsite) { + $r = DBExec($c, "select * from sitetable where sitenumber=".$ct["contestmainsite"]." and contestnumber=$contest"); + if (DBnLines($r)==0) { + echo "Unable to find the main site in the database (site=$site, contest=$contest).\n"; + exit; + } + $st = DBRow($r,0); + if (($t = DBExtConnect($c, $contest, $st["sitenumber"]))!=null) { + DBExec($c, "begin work"); + + // sincronizando contest + $r = DBExec ($t, "select * from contesttable where contestnumber=$contest"); + $n = DBnLines ($r); + $atual = DBRow($r,0); + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + DBExec ($c, "update contesttable set ". + "contestduration=".$atual["contestduration"].",". + "conteststartdate=".$atual["conteststartdate"].",". + "contestmaxfilesize=".$atual["contestmaxfilesize"].",". + "contestactive='".$atual["contestactive"]."',". + //"contestmainsite=".$atual["contestmainsite"].",". + "contestname='".escape_string($atual["contestname"])."',". + "contestlastmileanswer=".$atual["contestlastmileanswer"].",". + "contestlastmilescore=".$atual["contestlastmilescore"].",". + "contestpenalty=".$atual["contestpenalty"].",". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and updatetime<".$atual["updatetime"]); + + // sincronizando answers + $r = DBExec ($t, "select * from answertable where contestnumber=$contest"); + $rr = DBExec ($c, "select * from answertable where contestnumber=$contest for update"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "answers: external(site=$mainsite, reading=$mainsite)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["answernumber"]==$aqui["answernumber"] && $la["contestnumber"]==$aqui["contestnumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; $upd=0; $ins=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + DBExec($c, "delete from answertable where contestnumber=$contest and answernumber=".$atual["answernumber"]); + $del++; + } + } + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + $upd++; + DBExec ($c, "update answertable set ". + "runanswer='".$atual["runanswer"]."',". + "yes='".$atual["yes"]."',". + "fake='".$atual["fake"]."',". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and answernumber=".$atual["answernumber"]. + " and updatetime<".$atual["updatetime"]); + } else if ($situacao[$j]=="inserir") { + $ins++; + DBExec($c,"insert into answertable (contestnumber, answernumber, runanswer, yes, fake, updatetime) values (" . + $contest.",".$atual["answernumber"].",'".$atual["runanswer"]."','".$atual["yes"]."',". + "'".$atual["fake"]."',".$atual["updatetime"].")"); + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + + // sincronizando languages + $r = DBExec ($t, "select * from langtable where contestnumber=$contest"); + $rr = DBExec ($c, "select * from langtable where contestnumber=$contest for update"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "languages: external(site=$mainsite, reading=$mainsite)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["langnumber"]==$aqui["langnumber"] && $la["contestnumber"]==$aqui["contestnumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; $upd=0; $ins=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + DBExec($c, "delete from langtable where contestnumber=$contest and langnumber=".$atual["langnumber"]); + $del++; + } + } + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + $upd++; + DBExec ($c, "update langtable set ". + "langname='".escape_string($atual["langname"])."',". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and langnumber=".$atual["langnumber"]. + " and updatetime<".$atual["updatetime"]); + } else if ($situacao[$j]=="inserir") { + $ins++; + DBExec($c,"insert into langtable (contestnumber, langnumber, langname, updatetime) values ($contest,".$atual["langnumber"]. + ",'".escape_string($atual["langname"])."',".$atual["updatetime"].")"); + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + + // sincronizando problems + $r = DBExec ($t, "select * from problemtable where contestnumber=$contest"); + $rr = DBExec ($c, "select * from problemtable where contestnumber=$contest for update"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "problems: external(site=$mainsite, reading=$mainsite)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["problemnumber"]==$aqui["problemnumber"] && $la["contestnumber"]==$aqui["contestnumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; $upd=0; $ins=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + DBExec($c, "delete from problemtable where contestnumber=$contest and problemnumber=".$atual["problemnumber"]); + $del++; + } + } + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="inserir") { + $ins++; $upd--; + DBExec($c,"insert into problemtable (contestnumber, problemnumber, problemname, updatetime) values ($contest,". + $atual["problemnumber"].",'".escape_string($atual["problemname"])."', 0)"); + } + if ($situacao[$j]=="atualizar" || $situacao[$j]=="inserir") { + $upd++; + $p = DBRow($r2, 0); + if ($p["probleminputfile"]>0) DB_lo_unlink($c, $p["probleminputfile"]); + if ($p["problemsolfile"]>0) DB_lo_unlink($c, $p["problemsolfile"]); + DBExec($t, "begin work"); + if ($atual["probleminputfile"]=="") $inputfile="null"; + else { + $in = DB_lo_open($t, $atual["probleminputfile"], "r"); + if (!$in) $inputfile="null"; + else { + $inputfile = DB_lo_create ($c); + $out = DB_lo_open ($c, $inputfile, "w"); + while (($buf = DB_lo_read ($in, 100000)) != false) + DB_lo_write ($out, $buf); + DB_lo_close ($out); + DB_lo_close ($in); + } + } + if ($atual["problemsolfile"]=="") $solfile="null"; + else { + $in = DB_lo_open($t, $atual["problemsolfile"], "r"); + if (!$in) $solfile="null"; + else { + $solfile = DB_lo_create ($c); + $out = DB_lo_open ($c, $solfile, "w"); + while (($buf = DB_lo_read ($in, 100000)) != false) + DB_lo_write ($out, $buf); + DB_lo_close ($out); + DB_lo_close ($in); + } + } + DBExec ($t, "commit work"); + + DBExec ($c, "update problemtable set ". + "problemname='".escape_string($atual["problemname"])."',". + "problemfullname='".escape_string($atual["problemfullname"])."',". + "problembasefilename='".escape_string($atual["problembasefilename"])."',". + "probleminputfilename='".escape_string($atual["probleminputfilename"])."',". + "problemsolfilename='".escape_string($atual["problemsolfilename"])."',". + "fake='".$atual["fake"]."',". + "probleminputfile=".$inputfile.",". + "problemsolfile=".$solfile.",". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and problemnumber=".$atual["problemnumber"]. + " and updatetime<".$atual["updatetime"]); + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + DBExec($c, "commit work"); + } + + } + + $r = DBExec ($c, "select * from sitetable where contestnumber=$contest"); + $n = DBnlines($r); + if ($n == 0) { + echo "Unable to find sites in the database.\n"; + exit; + } + $st = array(); + for ($i=0;$i<$n;$i++) { + $st[$i] = DBRow($r,$i); + } + + for ($i=0; $i<count($st); $i++) { + $site=$st[$i]["sitenumber"]; + if ($site==$ct["contestlocalsite"]) continue; + if (($t = DBExtConnect($c, $contest, $site))==null) continue; + DBExec($c, "begin work"); + + // sincronizando site + $r = DBExec ($t, "select * from sitetable where contestnumber=$contest and sitenumber=$site"); + $rr = DBExec ($c, "select * from sitetable where contestnumber=$contest and sitenumber=$site for update"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + $atual = DBRow($r,0); + $p = DBRow($rr,0); +// if ($p["updatetime"]<$atual["updatetime"]) { + if ($atual["sitestartdate"]=="") $atual["sitestartdate"]="null"; + if ($atual["sitelastmilescore"]=="") $atual["sitelastmilescore"]="null"; + if ($atual["sitelastmileanswer"]=="") $atual["sitelastmileanswer"]="null"; + if ($atual["siteenddate"]=="") $atual["siteenddate"]="null"; + if ($atual["siteendeddate"]=="") $atual["siteendeddate"]="null"; + if ($atual["siteautoend"]!="t") $atual["siteautoend"]="f"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + DBExec ($c, "update sitetable set ". + //"siteip='".escape_string($atual["siteip"])."',". + "sitename='".escape_string($atual["sitename"])."',". + "siteactive='".escape_string($atual["siteactive"])."',". + "sitepermitlogins='".escape_string($atual["sitepermitlogins"])."',". + "sitestartdate=".$atual["sitestartdate"].",". + "sitelastmilescore=".$atual["sitelastmilescore"].",". + "sitelastmileanswer=".$atual["sitelastmileanswer"].",". + "siteenddate=".$atual["siteenddate"].",". + "siteendeddate=".$atual["siteendeddate"].",". + "siteautoend='".escape_string($atual["siteautoend"])."',". + "sitejudging='".escape_string($atual["sitejudging"])."',". + "siteglobalscore='".escape_string($atual["siteglobalscore"])."',". + "sitescorelevel=".$atual["sitescorelevel"].",". + "sitenextuser=".$atual["sitenextuser"].",". + "sitenextclar=".$atual["sitenextclar"].",". + "sitenextrun=".$atual["sitenextrun"].",". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and sitenumber=".$atual["sitenumber"]); +// ." and updatetime<".$atual["updatetime"]); +// } + + // sincronizando users + $r = DBExec ($t, "select * from usertable where contestnumber=$contest and usersitenumber=$site"); + $rr = DBExec ($c, "select * from usertable where contestnumber=$contest and usersitenumber=$site"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "users: external(site=$site, reading=$site)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["usernumber"]==$aqui["usernumber"] && $la["contestnumber"]==$aqui["contestnumber"] && + $la["usersitenumber"]==$aqui["usersitenumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + DBExec($c, "delete from usertable where contestnumber=$contest and usersitenumber=$site and usernumber=". + $atual["usernumber"]); + $del++; + } + } + $upd=0; $ins=0; + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["userlastlogin"]=="") $atual["userlastlogin"]="null"; + if ($atual["userlastlogout"]=="") $atual["userlastlogout"]="null"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + DBExec ($c, "update usertable set ". + "username='".escape_string($atual["username"])."',". + "userfullname='".escape_string($atual["userfullname"])."',". + "userdesc='".escape_string($atual["userdesc"])."',". + "usertype='".escape_string($atual["usertype"])."',". + "userenabled='".$atual["userenabled"]."',". + "usermultilogin='".$atual["usermultilogin"]."',". + "userpassword='".$atual["userpassword"]."',". + "userip='".$atual["userip"]."',". + "userlastlogin=".$atual["userlastlogin"].",". + "userlastlogout=".$atual["userlastlogout"].",". + "usersession='".$atual["usersession"]."',". + "userpermitip='".$atual["userpermitip"]."',". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and usersitenumber=".$atual["usersitenumber"]. + " and usernumber=".$atual["usernumber"]." and updatetime<".$atual["updatetime"]); + $upd++; + } else if ($situacao[$j]=="inserir") { + DBExec ($c, "insert into usertable (username, userfullname, userdesc, usertype, userenabled, usermultilogin, ". + "userpassword, userip, userlastlogin, userlastlogout, usersession, userpermitip, updatetime, ". + "contestnumber, usersitenumber, usernumber) values (". + "'".escape_string($atual["username"])."',". + "'".escape_string($atual["userfullname"])."',". + "'".escape_string($atual["userdesc"])."',". + "'".$atual["usertype"]."',". + "'".$atual["userenabled"]."',". + "'".$atual["usermultilogin"]."',". + "'".$atual["userpassword"]."',". + "'".$atual["userip"]."',". + $atual["userlastlogin"].",". + $atual["userlastlogout"].",". + "'".$atual["usersession"]."',". + "'".$atual["userpermitip"]."',". + $atual["updatetime"].",$contest,".$atual["usersitenumber"].",".$atual["usernumber"].")"); + $ins++; + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + + // sincronizando clars + $r = DBExec ($t, "select * from clartable where contestnumber=$contest and clarsitenumber=$site"); + $rr = DBExec ($c, "select * from clartable where contestnumber=$contest and clarsitenumber=$site"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "clars: external(site=$site, reading=$site)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["clarnumber"]==$aqui["clarnumber"] && $la["contestnumber"]==$aqui["contestnumber"] && + $la["clarsitenumber"]==$aqui["clarsitenumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + DBExec($c, "delete from clartable where contestnumber=$contest and clarsitenumber=$site and clarnumber=". + $atual["clarnumber"]); + $del++; + } + } + $upd=0; $ins=0; + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["claranswer"]=="") $atual["claranswer"]="null"; + else $atual["claranswer"]="'".escape_string($atual["claranswer"])."'"; + if ($atual["clarjudge"]=="") $atual["clarjudge"]="null"; + if ($atual["clarjudgesite"]=="") $atual["clarjudgesite"]="null"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + DBExec ($c, "update clartable set ". + "usernumber=".$atual["usernumber"].",". + "clardate=".$atual["clardate"].",". + "clardatediff=".$atual["clardatediff"].",". + "clardatediffans=".$atual["clardatediffans"].",". + "clarproblem=".$atual["clarproblem"].",". + "clardata='".escape_string($atual["clardata"])."',". + "claranswer=".$atual["claranswer"].",". + "clarstatus='".escape_string($atual["clarstatus"])."',". + "clarjudge=".$atual["clarjudge"].",". + "clarjudgesite=".$atual["clarjudgesite"].",". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and clarsitenumber=".$atual["clarsitenumber"]. + " and clarnumber=".$atual["clarnumber"]." and updatetime<".$atual["updatetime"]); + $upd++; + } else if($situacao[$j]=="inserir") { + DBExec ($c, "insert into clartable (contestnumber, clarsitenumber, clarnumber, usernumber, clardate,". + "clardatediff, clardatediffans, clarproblem, clardata, claranswer, clarstatus, clarjudge, clarjudgesite, updatetime) ". + "values (".$contest.",".$atual["clarsitenumber"].",".$atual["clarnumber"].",".$atual["usernumber"].",". + $atual["clardate"].",". + $atual["clardatediff"].",". + $atual["clardatediffans"].",". + $atual["clarproblem"].",". + "'".escape_string($atual["clardata"])."',". + $atual["claranswer"].",". + "'".escape_string($atual["clarstatus"])."',". + $atual["clarjudge"].",". + $atual["clarjudgesite"].",". + $atual["updatetime"].")"); + $ins++; + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + + // sincronizando clars + $r = DBExec ($t, "select * from clartable where contestnumber=$contest and clarsitenumber=$localsite"); + $rr = DBExec ($c, "select * from clartable where contestnumber=$contest and clarsitenumber=$localsite"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "clars: external(site=$site, reading=$localsite)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["clarnumber"]==$aqui["clarnumber"] && $la["contestnumber"]==$aqui["contestnumber"] && + $la["clarsitenumber"]==$aqui["clarsitenumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $upd=0; $ins=0; + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["claranswer"]=="") $atual["claranswer"]="null"; + else $atual["claranswer"]="'".escape_string($atual["claranswer"])."'"; + if ($atual["clarjudge"]=="") $atual["clarjudge"]="null"; + if ($atual["clarjudgesite"]=="") $atual["clarjudgesite"]="null"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + DBExec ($c, "update clartable set ". + "usernumber=".$atual["usernumber"].",". + "clardate=".$atual["clardate"].",". + "clardatediff=".$atual["clardatediff"].",". + "clardatediffans=".$atual["clardatediffans"].",". + "clarproblem=".$atual["clarproblem"].",". + "clardata='".escape_string($atual["clardata"])."',". + "claranswer=".$atual["claranswer"].",". + "clarstatus='".escape_string($atual["clarstatus"])."',". + "clarjudge=".$atual["clarjudge"].",". + "clarjudgesite=".$atual["clarjudgesite"].",". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and clarsitenumber=".$atual["clarsitenumber"]. + " and clarnumber=".$atual["clarnumber"]." and updatetime<".$atual["updatetime"]); + $upd++; + } else if($situacao[$j]=="inserir") { + $ins++; + echo "Clar inserts shouldn't exist (clarnumber=".$atual["clarnumber"].")...\n"; + } + } + echo " updates=$upd, insertions=$ins\n\n"; + + // sincronizando runs + $r = DBExec ($t, "select * from runtable where contestnumber=$contest and runsitenumber=$site"); + $rr = DBExec ($c, "select * from runtable where contestnumber=$contest and runsitenumber=$site"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "runs: external(site=$site, reading=$site)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["runnumber"]==$aqui["runnumber"] && $la["contestnumber"]==$aqui["contestnumber"] && + $la["runsitenumber"]==$aqui["runsitenumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) { + $situacao[$j]="atualizar"; + } + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + $del++; + DBExec($c, "delete from runtable where contestnumber=$contest and runsitenumber=$site and runnumber=". + $atual["runnumber"]); + } + } + $upd=0; $ins=0; + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); +/* + $r2 = DBExec ($c,"select * from runtable where contestnumber=$contest and runsitenumber=".$atual["runsitenumber"]. + " and runnumber=".$atual["runnumber"]." for update"); + if (DBnLines($r2)>0) { + $p = DBRow($r2, 0); + DB_lo_unlink($c, $p["rundata"]); + } +*/ + if ($atual["runjudge"]=="") $atual["runjudge"]="null"; + if ($atual["runjudgesite"]=="") $atual["runjudgesite"]="null"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + $upd++; + DBExec ($c, "update runtable set ". + "usernumber=".$atual["usernumber"].",". + "rundate=".$atual["rundate"].",". + "rundatediff=".$atual["rundatediff"].",". + "rundatediffans=".$atual["rundatediffans"].",". + "runproblem=".$atual["runproblem"].",". + "runlangnumber=".$atual["runlangnumber"].",". + "runanswer=".$atual["runanswer"].",". + "runstatus='".escape_string($atual["runstatus"])."',". + "runjudge=".$atual["runjudge"].",". + "runjudgesite=".$atual["runjudgesite"].",". + "runfilename='".escape_string($atual["runfilename"])."',". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and runsitenumber=".$atual["runsitenumber"]. + " and runnumber=".$atual["runnumber"]." and updatetime<".$atual["updatetime"]); + } else if ($situacao[$j]=="inserir") { + $ins++; + DBExec($t, "begin work"); + $in = DB_lo_open($t, $atual["rundata"], "r"); + if (!$in) $o="0"; + else { + $o = DB_lo_create ($c); + $out = DB_lo_open ($c, $o, "w"); + while (($buf = DB_lo_read ($in, 1000)) != false) + DB_lo_write ($out, $buf); + DB_lo_close ($out); + DB_lo_close ($in); + + $in = DB_lo_open($t, $atual["rundata"], "r"); + if (!$in) { + $o="0"; + LOGLevel("Run not saved as file (run=".$atual["runnumber"].",site=".$atual["runsitenumber"]. + ",contest=$contest", 1); + } else { + $sitess=$atual["runsitenumber"]; + $nss=$atual["runnumber"]; + $user=$atual["usernumber"]; + $problem=$atual["runproblem"]; + $filename=escape_string($atual["runfilename"]); + $ttimet=$atual["rundate"]; + $fp = fopen("/tmp/boca/contest${contest}.site${sitess}.run${nss}.user${user}.". + "problem${problem}.time${ttimet}.${filename}", "w"); + if ($fp) { + while (($buf = DB_lo_read ($in, 1000)) != false) + fwrite ($fp, $buf); + fclose ($fp); + $fp = fopen("/tmp/check/contest${contest}.site${sitess}.run${nss}.user${user}.". + "problem${problem}.time${ttimet}.${filename}.check", "w"); + if ($fp) { + fwrite($fp, "1"); + fclose ($fp); + } + else + LOGLevel("Run not saved as check file (run=".$atual["runnumber"].",site=".$atual["runsitenumber"]. + ",contest=$contest", 1); + } else + LOGLevel("Run not saved as file (run=".$atual["runnumber"].",site=".$atual["runsitenumber"]. + ",contest=$contest", 1); + DB_lo_close ($out); + } + + } + DBExec ($c, "insert into runtable (contestnumber, runsitenumber, runnumber, usernumber, rundate,". + "rundatediff, rundatediffans, runproblem, runfilename, rundata, runanswer, runstatus, runjudge,". + "runjudgesite, runlangnumber, updatetime) ". + "values (".$contest.",".$atual["runsitenumber"].",".$atual["runnumber"].",".$atual["usernumber"].",". + $atual["rundate"].",". + $atual["rundatediff"].",". + $atual["rundatediffans"].",". + $atual["runproblem"].",". + "'".escape_string($atual["runfilename"])."',$o,". + $atual["runanswer"].",". + "'".escape_string($atual["runstatus"])."',". + $atual["runjudge"].",". + $atual["runjudgesite"].",". + $atual["runlangnumber"].",". + $atual["updatetime"].")"); + DBExec ($t, "commit work"); + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + + // sincronizando runs + $r = DBExec ($t, "select * from runtable where contestnumber=$contest and runsitenumber=$localsite"); + $rr = DBExec ($c, "select * from runtable where contestnumber=$contest and runsitenumber=$localsite"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "runs: external(site=$site, reading=$localsite)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["runnumber"]==$aqui["runnumber"] && $la["contestnumber"]==$aqui["contestnumber"] && + $la["runsitenumber"]==$aqui["runsitenumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) { + $situacao[$j]="atualizar"; + + + if ($la["runanswer"] != "") { + $rrr = DBExec($c, "select * from answertable where answernumber=".$la["runanswer"]. + " and contestnumber=".$la["contestnumber"]); + $ans = (DBnLines($rrr)>0)? DBRow($rrr, 0) : null; + if ($ans == null) { + echo "Problem with the answer table. Unable to send balloon because the answer was " . + "not found (run=".$la["runnumber"].", site=".$la["runsite"].", contest=" . + $la["contestnumber"].", answer=".$la["runanswer"].")."; + $yesla = 'x'; + } else $yesla = $ans["yes"]; + } else $yesla='f'; + if ($aqui["runanswer"] != "") { + $rrr = DBExec($c, "select * from answertable where answernumber=".$aqui["runanswer"]. + " and contestnumber=".$aqui["contestnumber"]); + $ans = (DBnLines($rrr)>0)? DBRow($rrr, 0) : null; + if ($ans == null) { + echo "Problem with the answer table. Unable to send balloon because the answer was " . + "not found (run=".$aqui["runnumber"].", site=".$aqui["runsite"].", contest=" . + $aqui["contestnumber"].", answer=".$aqui["runanswer"].")."; + $yesaqui = 'x'; + } else $yesaqui = $ans["yes"]; + } else $yesaqui='f'; + + if ($yesla == 't' && $yesaqui == 'f') { + $rrr = DBExec ($c, "select * from sitetable where contestnumber=".$aqui["contestnumber"]. + " and sitenumber=$localsite"); + if (DBnLines($rrr)<=0) + echo "Site info not found (contest=${aqui["contestnumber"]}, site=$localsite)."; + else { + $b = DBRow($rrr,0); + $ti = $b["sitestartdate"]; + $tempo = time(); + $ta = $tempo - $ti; + $tf = $b["sitelastmileanswer"]; +// if ($ta < $tf) { + $rrr = DBExec ($c, "select * from usertable where contestnumber=". + $aqui["contestnumber"]." and usersitenumber=$localsite and usernumber=". + $aqui["usernumber"]); + if (DBnLines($rrr)<=0) + echo "User info not found (contest=${aqui["contestnumber"]}, ". + "site=$localsite, user=${aqui["runusernumber"]})."; + else { + $u = DBRow ($rrr,0); + $rrr = DBExec ($c, "select * from problemtable where contestnumber=". + $aqui["contestnumber"]." and problemnumber=". + $aqui["runproblem"]); + if (DBnLines($rrr)<=0) + echo "Problem info not found (contest=${aqui["contestnumber"]}, ". + "problem=${aqui["runproblem"]})."; + else { + $p = DBRow ($rrr,0); + mail("balloon@mainserver", "YES: team=" . $u["username"] . + ", problem=" . $p["problemname"], + "User ".$u["username"] ." should receive a balloon for ". + $p["problemfullname"]."\n"); + } + } +// } + } + } else if ($yesla == 'f' && $yesaqui == 't') { + $rrr = DBExec ($c, "select * from usertable where contestnumber=". + $aqui["contestnumber"]." and usersitenumber=$localsite and usernumber=". + $aqui["usernumber"]); + if (DBnLines($rrr)<=0) + echo "User info not found (contest=${aqui["contestnumber"]}, ". + "site=$localsite, user=${aqui["runusernumber"]})."; + else { + $u = DBRow ($rrr,0); + $rrr = DBExec ($c, "select * from problemtable where contestnumber=". + $aqui["contestnumber"]." and problemnumber=". + $aqui["runproblem"]); + if (DBnLines($rrr)<=0) + echo "Problem info not found (contest=${aqui["contestnumber"]}, ". + "problem=${aqui["runproblem"]})."; + else { + $p = DBRow ($rrr,0); + mail("balloon@mainserver", "NO: team=" . $u["username"] . + ", problem=" . $p["problemname"], + "Remove the balloon from user ". $u["username"] . + " for ".$p["problemfullname"]."\n"); + } + } + } + + + } + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $upd=0; $ins=0; + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + + if ($atual["runjudge"]=="") $atual["runjudge"]="null"; + if ($atual["runjudgesite"]=="") $atual["runjudgesite"]="null"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + $upd++; + DBExec ($c, "update runtable set ". + "usernumber=".$atual["usernumber"].",". + "rundate=".$atual["rundate"].",". + "rundatediff=".$atual["rundatediff"].",". + "rundatediffans=".$atual["rundatediffans"].",". + "runproblem=".$atual["runproblem"].",". + "runlangnumber=".$atual["runlangnumber"].",". + "runanswer=".$atual["runanswer"].",". + "runstatus='".escape_string($atual["runstatus"])."',". + "runjudge=".$atual["runjudge"].",". + "runjudgesite=".$atual["runjudgesite"].",". + "runfilename='".escape_string($atual["runfilename"])."',". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and runsitenumber=".$atual["runsitenumber"]. + " and runnumber=".$atual["runnumber"]." and updatetime<".$atual["updatetime"]); + } else if ($situacao[$j]=="inserir") { + $ins++; + echo "Run Inserts shouldn't exist (run=".$atual["runnumber"].")..."; + } + } + echo " updates=$upd, insertions=$ins\n\n"; + + DBExec($c, "commit work"); + DBClose($t); + } + DBClose($c); +} + +//fecha a conexao com o banco (isso nao eh realmente necessario, ja que o php/apache cuidam do servico) +function DBClose($c) { + if ($c) pg_close($c); +} +//executar instrucao no banco de dados, parando em caso de erro quando $stop=1 +function DBExec($conn,$sql) { +// echo $sql . "\n"; + $result = pg_exec ($conn, $sql); + if (!$result) { + echo "Unable to exec SQL in the database. SQL=(" . $sql . ")," . + " Error=(" . pg_errormessage($conn) . ")\n"; + exit; + } + return $result; +} +//devolve o numero de linhas da consulta +function DBnlines ($result) { + return pg_numrows ($result); +} +//pega uma linha da consulta no formato de array +function DBRow ($r, $i) { + return pg_fetch_array ($r, $i); +} +function escape_string($s) { + return str_replace("'", "''", $s); +} +if (getIP()!="UNKNOWN") exit; + +$x = DBConnect(); +if ($x==null) exit; +$y = DBExec($x, "select * from contesttable where contestactive='t'"); +if (DBnLines($y)==0) { + echo "Unable to find the active contest in the database.\n"; + exit; +} +$ct = DBRow($y,0); +DBClose($x); +GetExternalData($ct["contestnumber"]); + +?> diff --git a/boca-1.5.0/old/getextdata.php b/boca-1.5.0/old/getextdata.php new file mode 100644 index 0000000..7c9955d --- /dev/null +++ b/boca-1.5.0/old/getextdata.php @@ -0,0 +1,931 @@ +<?php +////////////////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator. Copyright (c) 2003-2004 Cassio Polpo de Campos. +//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +/////////////////////////////////////////////////////////////////////////////////////////// + +//retorna ip do cliente +function getIP() { + if (getenv("HTTP_CLIENT_IP")) + $ip = getenv("HTTP_CLIENT_IP"); + else + if(getenv("HTTP_X_FORWARDED_FOR")) + $ip = getenv("HTTP_X_FORWARDED_FOR"); + else + if(getenv("REMOTE_ADDR")) + $ip = getenv("REMOTE_ADDR"); + else + $ip = "UNKNOWN"; + $ip = strtok ($ip, ","); + return $ip; +} +//para compatibilidade com versoes velhas e novas do php +function DB_lo_open($conn, $file, $mode) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loopen ($conn, $file, $mode); + else + return pg_lo_open ($conn, $file, $mode); +} +function DB_lo_read_all($id) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loreadall ($id); + else + return pg_lo_read_all ($id); +} +function DB_lo_import($conn, $file) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loimport ($file, $conn); + else + return pg_lo_import ($conn, $file); +} +function DB_lo_close($id) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loclose ($id); + else + return pg_lo_close ($id); +} +function DB_lo_unlink($c,$id) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_lounlink ($id,$c); + else + return pg_lo_unlink ($c,$id); +} +function DB_lo_create($conn) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_locreate ($conn); + else + return pg_lo_create ($conn); +} +function DB_lo_write($fp, $data) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_lowrite ($fp, $data); + else + return pg_lo_write ($fp, $data); +} +function DB_lo_read($fp, $len) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loread ($fp, $len); + else + return pg_lo_read ($fp, $len); +} + +//abrir conexao com o banco de dados +function DBConnect() { + $dbconn="host=localhost dbname=bocadb user=bocauser password=boca"; + $conn = pg_connect ($dbconn); + if (!$conn) { + echo "Unable to connect to local database\n"; + return null; + } + return $conn; +} +function DBExtConnect($c, $contest, $site) { + $r = DBExec($c, "select * from sitetable where sitenumber=$site and contestnumber=$contest"); + if (DBnLines($r)==0) { + echo "Unable to find the site in the database (site=$site, contest=$contest).\n"; + exit; + } + $st = DBRow($r,0); + + if(($f = file("sqlpass.php"))===false) $pass="boca"; + else $pass=trim($f[1]); + + // gambiarra para testar se a conexao esta de pe + $fp = fsockopen ($st["siteip"], 5432, $errno, $errstr, 10); + if (!$fp) { + echo "$errstr ($errno). Aborting this connection (ip=".$st["siteip"].").\n"; + return null; + } + fclose ($fp); + // se a conexao cair entre o teste acima e o connect abaixo, esse script pode demorar ate + // dar o timeout (no meu teste foram cerca de 3min para cada timeout) + + $conn = pg_connect ("host=" . $st["siteip"] . " dbname=bocadb user=bocauser password=$pass"); + if (!$conn) { + echo "Unable to connect to site $site (ip=".$st["siteip"].")\n"; + return null; + } + echo "Connected to " .$st["siteip"].". Let's exchange data...\n"; + return $conn; +} + +function GetExternalData ($contest) { + $c = DBConnect(); + if ($c==null) return; + $r = DBExec($c, "select * from contesttable where contestnumber=$contest"); + if (DBnLines($r)==0) { + echo "Unable to find the contest $contest in the database.\n"; + exit; + } + $ct = DBRow($r,0); + $localsite = $ct["contestlocalsite"]; + $mainsite = $ct["contestmainsite"]; + + if ($mainsite!=$localsite) { + $r = DBExec($c, "select * from sitetable where sitenumber=".$ct["contestmainsite"]." and contestnumber=$contest"); + if (DBnLines($r)==0) { + echo "Unable to find the main site in the database (site=$site, contest=$contest).\n"; + exit; + } + $st = DBRow($r,0); + if (($t = DBExtConnect($c, $contest, $st["sitenumber"]))!=null) { + DBExec($c, "begin work"); + + // sincronizando contest + $r = DBExec ($t, "select * from contesttable where contestnumber=$contest"); + $n = DBnLines ($r); + $atual = DBRow($r,0); + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + DBExec ($c, "update contesttable set ". + "contestduration=".$atual["contestduration"].",". + "conteststartdate=".$atual["conteststartdate"].",". + "contestmaxfilesize=".$atual["contestmaxfilesize"].",". + "contestactive='".$atual["contestactive"]."',". + //"contestmainsite=".$atual["contestmainsite"].",". + "contestname='".escape_string($atual["contestname"])."',". + "contestlastmileanswer=".$atual["contestlastmileanswer"].",". + "contestlastmilescore=".$atual["contestlastmilescore"].",". + "contestpenalty=".$atual["contestpenalty"].",". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and updatetime<".$atual["updatetime"]); + + // sincronizando answers + $r = DBExec ($t, "select * from answertable where contestnumber=$contest"); + $rr = DBExec ($c, "select * from answertable where contestnumber=$contest for update"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "answers: external(site=$mainsite, reading=$mainsite)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["answernumber"]==$aqui["answernumber"] && $la["contestnumber"]==$aqui["contestnumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; $upd=0; $ins=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + DBExec($c, "delete from answertable where contestnumber=$contest and answernumber=".$atual["answernumber"]); + $del++; + } + } + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + $upd++; + DBExec ($c, "update answertable set ". + "runanswer='".$atual["runanswer"]."',". + "yes='".$atual["yes"]."',". + "fake='".$atual["fake"]."',". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and answernumber=".$atual["answernumber"]. + " and updatetime<".$atual["updatetime"]); + } else if ($situacao[$j]=="inserir") { + $ins++; + DBExec($c,"insert into answertable (contestnumber, answernumber, runanswer, yes, fake, updatetime) values (" . + $contest.",".$atual["answernumber"].",'".$atual["runanswer"]."','".$atual["yes"]."',". + "'".$atual["fake"]."',".$atual["updatetime"].")"); + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + + // sincronizando languages + $r = DBExec ($t, "select * from langtable where contestnumber=$contest"); + $rr = DBExec ($c, "select * from langtable where contestnumber=$contest for update"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "languages: external(site=$mainsite, reading=$mainsite)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["langnumber"]==$aqui["langnumber"] && $la["contestnumber"]==$aqui["contestnumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; $upd=0; $ins=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + DBExec($c, "delete from langtable where contestnumber=$contest and langnumber=".$atual["langnumber"]); + $del++; + } + } + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + $upd++; + DBExec ($c, "update langtable set ". + "langname='".escape_string($atual["langname"])."',". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and langnumber=".$atual["langnumber"]. + " and updatetime<".$atual["updatetime"]); + } else if ($situacao[$j]=="inserir") { + $ins++; + DBExec($c,"insert into langtable (contestnumber, langnumber, langname, updatetime) values ($contest,".$atual["langnumber"]. + ",'".escape_string($atual["langname"])."',".$atual["updatetime"].")"); + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + + // sincronizando problems + $r = DBExec ($t, "select * from problemtable where contestnumber=$contest"); + $rr = DBExec ($c, "select * from problemtable where contestnumber=$contest for update"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "problems: external(site=$mainsite, reading=$mainsite)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["problemnumber"]==$aqui["problemnumber"] && $la["contestnumber"]==$aqui["contestnumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; $upd=0; $ins=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + DBExec($c, "delete from problemtable where contestnumber=$contest and problemnumber=".$atual["problemnumber"]); + $del++; + } + } + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="inserir") { + $ins++; $upd--; + DBExec($c,"insert into problemtable (contestnumber, problemnumber, problemname, updatetime) values ($contest,". + $atual["problemnumber"].",'".escape_string($atual["problemname"])."', 0)"); + } + if ($situacao[$j]=="atualizar" || $situacao[$j]=="inserir") { + $upd++; + $p = DBRow($r2, 0); + if ($p["probleminputfile"]>0) DB_lo_unlink($c, $p["probleminputfile"]); + if ($p["problemsolfile"]>0) DB_lo_unlink($c, $p["problemsolfile"]); + DBExec($t, "begin work"); + if ($atual["probleminputfile"]=="") $inputfile="null"; + else { + $in = DB_lo_open($t, $atual["probleminputfile"], "r"); + if (!$in) $inputfile="null"; + else { + $inputfile = DB_lo_create ($c); + $out = DB_lo_open ($c, $inputfile, "w"); + while (($buf = DB_lo_read ($in, 100000)) != false) + DB_lo_write ($out, $buf); + DB_lo_close ($out); + DB_lo_close ($in); + } + } + if ($atual["problemsolfile"]=="") $solfile="null"; + else { + $in = DB_lo_open($t, $atual["problemsolfile"], "r"); + if (!$in) $solfile="null"; + else { + $solfile = DB_lo_create ($c); + $out = DB_lo_open ($c, $solfile, "w"); + while (($buf = DB_lo_read ($in, 100000)) != false) + DB_lo_write ($out, $buf); + DB_lo_close ($out); + DB_lo_close ($in); + } + } + DBExec ($t, "commit work"); + + DBExec ($c, "update problemtable set ". + "problemname='".escape_string($atual["problemname"])."',". + "problemfullname='".escape_string($atual["problemfullname"])."',". + "problembasefilename='".escape_string($atual["problembasefilename"])."',". + "probleminputfilename='".escape_string($atual["probleminputfilename"])."',". + "problemsolfilename='".escape_string($atual["problemsolfilename"])."',". + "fake='".$atual["fake"]."',". + "probleminputfile=".$inputfile.",". + "problemsolfile=".$solfile.",". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and problemnumber=".$atual["problemnumber"]. + " and updatetime<".$atual["updatetime"]); + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + DBExec($c, "commit work"); + } + + } + + $r = DBExec ($c, "select * from sitetable where contestnumber=$contest"); + $n = DBnlines($r); + if ($n == 0) { + echo "Unable to find sites in the database.\n"; + exit; + } + $st = array(); + for ($i=0;$i<$n;$i++) { + $st[$i] = DBRow($r,$i); + } + + for ($i=0; $i<count($st); $i++) { + $site=$st[$i]["sitenumber"]; + if ($site==$ct["contestlocalsite"]) continue; + if (($t = DBExtConnect($c, $contest, $site))==null) continue; + DBExec($c, "begin work"); + + // sincronizando site + $r = DBExec ($t, "select * from sitetable where contestnumber=$contest and sitenumber=$site"); + $rr = DBExec ($c, "select * from sitetable where contestnumber=$contest and sitenumber=$site for update"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + $atual = DBRow($r,0); + $p = DBRow($rr,0); +// if ($p["updatetime"]<$atual["updatetime"]) { + if ($atual["sitestartdate"]=="") $atual["sitestartdate"]="null"; + if ($atual["sitelastmilescore"]=="") $atual["sitelastmilescore"]="null"; + if ($atual["sitelastmileanswer"]=="") $atual["sitelastmileanswer"]="null"; + if ($atual["siteenddate"]=="") $atual["siteenddate"]="null"; + if ($atual["siteendeddate"]=="") $atual["siteendeddate"]="null"; + if ($atual["siteautoend"]!="t") $atual["siteautoend"]="f"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + DBExec ($c, "update sitetable set ". + //"siteip='".escape_string($atual["siteip"])."',". + "sitename='".escape_string($atual["sitename"])."',". + "siteactive='".escape_string($atual["siteactive"])."',". + "sitepermitlogins='".escape_string($atual["sitepermitlogins"])."',". + "sitestartdate=".$atual["sitestartdate"].",". + "sitelastmilescore=".$atual["sitelastmilescore"].",". + "sitelastmileanswer=".$atual["sitelastmileanswer"].",". + "siteenddate=".$atual["siteenddate"].",". + "siteendeddate=".$atual["siteendeddate"].",". + "siteautoend='".escape_string($atual["siteautoend"])."',". + "sitejudging='".escape_string($atual["sitejudging"])."',". + "siteglobalscore='".escape_string($atual["siteglobalscore"])."',". + "sitescorelevel=".$atual["sitescorelevel"].",". + "sitenextuser=".$atual["sitenextuser"].",". + "sitenextclar=".$atual["sitenextclar"].",". + "sitenextrun=".$atual["sitenextrun"].",". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and sitenumber=".$atual["sitenumber"]); +// ." and updatetime<".$atual["updatetime"]); +// } + + // sincronizando users + $r = DBExec ($t, "select * from usertable where contestnumber=$contest and usersitenumber=$site"); + $rr = DBExec ($c, "select * from usertable where contestnumber=$contest and usersitenumber=$site"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "users: external(site=$site, reading=$site)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["usernumber"]==$aqui["usernumber"] && $la["contestnumber"]==$aqui["contestnumber"] && + $la["usersitenumber"]==$aqui["usersitenumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + DBExec($c, "delete from usertable where contestnumber=$contest and usersitenumber=$site and usernumber=". + $atual["usernumber"]); + $del++; + } + } + $upd=0; $ins=0; + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["userlastlogin"]=="") $atual["userlastlogin"]="null"; + if ($atual["userlastlogout"]=="") $atual["userlastlogout"]="null"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + DBExec ($c, "update usertable set ". + "username='".escape_string($atual["username"])."',". + "userfullname='".escape_string($atual["userfullname"])."',". + "userdesc='".escape_string($atual["userdesc"])."',". + "usertype='".escape_string($atual["usertype"])."',". + "userenabled='".$atual["userenabled"]."',". + "usermultilogin='".$atual["usermultilogin"]."',". + "userpassword='".$atual["userpassword"]."',". + "userip='".$atual["userip"]."',". + "userlastlogin=".$atual["userlastlogin"].",". + "userlastlogout=".$atual["userlastlogout"].",". + "usersession='".$atual["usersession"]."',". + "userpermitip='".$atual["userpermitip"]."',". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and usersitenumber=".$atual["usersitenumber"]. + " and usernumber=".$atual["usernumber"]." and updatetime<".$atual["updatetime"]); + $upd++; + } else if ($situacao[$j]=="inserir") { + DBExec ($c, "insert into usertable (username, userfullname, userdesc, usertype, userenabled, usermultilogin, ". + "userpassword, userip, userlastlogin, userlastlogout, usersession, userpermitip, updatetime, ". + "contestnumber, usersitenumber, usernumber) values (". + "'".escape_string($atual["username"])."',". + "'".escape_string($atual["userfullname"])."',". + "'".escape_string($atual["userdesc"])."',". + "'".$atual["usertype"]."',". + "'".$atual["userenabled"]."',". + "'".$atual["usermultilogin"]."',". + "'".$atual["userpassword"]."',". + "'".$atual["userip"]."',". + $atual["userlastlogin"].",". + $atual["userlastlogout"].",". + "'".$atual["usersession"]."',". + "'".$atual["userpermitip"]."',". + $atual["updatetime"].",$contest,".$atual["usersitenumber"].",".$atual["usernumber"].")"); + $ins++; + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + + // sincronizando clars + $r = DBExec ($t, "select * from clartable where contestnumber=$contest and clarsitenumber=$site"); + $rr = DBExec ($c, "select * from clartable where contestnumber=$contest and clarsitenumber=$site"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "clars: external(site=$site, reading=$site)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["clarnumber"]==$aqui["clarnumber"] && $la["contestnumber"]==$aqui["contestnumber"] && + $la["clarsitenumber"]==$aqui["clarsitenumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + DBExec($c, "delete from clartable where contestnumber=$contest and clarsitenumber=$site and clarnumber=". + $atual["clarnumber"]); + $del++; + } + } + $upd=0; $ins=0; + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["claranswer"]=="") $atual["claranswer"]="null"; + else $atual["claranswer"]="'".escape_string($atual["claranswer"])."'"; + if ($atual["clarjudge"]=="") $atual["clarjudge"]="null"; + if ($atual["clarjudgesite"]=="") $atual["clarjudgesite"]="null"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + DBExec ($c, "update clartable set ". + "usernumber=".$atual["usernumber"].",". + "clardate=".$atual["clardate"].",". + "clardatediff=".$atual["clardatediff"].",". + "clardatediffans=".$atual["clardatediffans"].",". + "clarproblem=".$atual["clarproblem"].",". + "clardata='".escape_string($atual["clardata"])."',". + "claranswer=".$atual["claranswer"].",". + "clarstatus='".escape_string($atual["clarstatus"])."',". + "clarjudge=".$atual["clarjudge"].",". + "clarjudgesite=".$atual["clarjudgesite"].",". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and clarsitenumber=".$atual["clarsitenumber"]. + " and clarnumber=".$atual["clarnumber"]." and updatetime<".$atual["updatetime"]); + $upd++; + } else if($situacao[$j]=="inserir") { + DBExec ($c, "insert into clartable (contestnumber, clarsitenumber, clarnumber, usernumber, clardate,". + "clardatediff, clardatediffans, clarproblem, clardata, claranswer, clarstatus, clarjudge, clarjudgesite, updatetime) ". + "values (".$contest.",".$atual["clarsitenumber"].",".$atual["clarnumber"].",".$atual["usernumber"].",". + $atual["clardate"].",". + $atual["clardatediff"].",". + $atual["clardatediffans"].",". + $atual["clarproblem"].",". + "'".escape_string($atual["clardata"])."',". + $atual["claranswer"].",". + "'".escape_string($atual["clarstatus"])."',". + $atual["clarjudge"].",". + $atual["clarjudgesite"].",". + $atual["updatetime"].")"); + $ins++; + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + + // sincronizando clars + $r = DBExec ($t, "select * from clartable where contestnumber=$contest and clarsitenumber=$localsite"); + $rr = DBExec ($c, "select * from clartable where contestnumber=$contest and clarsitenumber=$localsite"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "clars: external(site=$site, reading=$localsite)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["clarnumber"]==$aqui["clarnumber"] && $la["contestnumber"]==$aqui["contestnumber"] && + $la["clarsitenumber"]==$aqui["clarsitenumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) + $situacao[$j]="atualizar"; + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $upd=0; $ins=0; + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + if ($atual["claranswer"]=="") $atual["claranswer"]="null"; + else $atual["claranswer"]="'".escape_string($atual["claranswer"])."'"; + if ($atual["clarjudge"]=="") $atual["clarjudge"]="null"; + if ($atual["clarjudgesite"]=="") $atual["clarjudgesite"]="null"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + DBExec ($c, "update clartable set ". + "usernumber=".$atual["usernumber"].",". + "clardate=".$atual["clardate"].",". + "clardatediff=".$atual["clardatediff"].",". + "clardatediffans=".$atual["clardatediffans"].",". + "clarproblem=".$atual["clarproblem"].",". + "clardata='".escape_string($atual["clardata"])."',". + "claranswer=".$atual["claranswer"].",". + "clarstatus='".escape_string($atual["clarstatus"])."',". + "clarjudge=".$atual["clarjudge"].",". + "clarjudgesite=".$atual["clarjudgesite"].",". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and clarsitenumber=".$atual["clarsitenumber"]. + " and clarnumber=".$atual["clarnumber"]." and updatetime<".$atual["updatetime"]); + $upd++; + } else if($situacao[$j]=="inserir") { + $ins++; + echo "Clar inserts shouldn't exist (clarnumber=".$atual["clarnumber"].")...\n"; + } + } + echo " updates=$upd, insertions=$ins\n\n"; + + // sincronizando runs + $r = DBExec ($t, "select * from runtable where contestnumber=$contest and runsitenumber=$site"); + $rr = DBExec ($c, "select * from runtable where contestnumber=$contest and runsitenumber=$site"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "runs: external(site=$site, reading=$site)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["runnumber"]==$aqui["runnumber"] && $la["contestnumber"]==$aqui["contestnumber"] && + $la["runsitenumber"]==$aqui["runsitenumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) { + $situacao[$j]="atualizar"; + } + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $del=0; + for ($k=0; $k<$nn; $k++) { + $atual = DBRow($rr, $k); + if (!$needed[$k]) { + $del++; + DBExec($c, "delete from runtable where contestnumber=$contest and runsitenumber=$site and runnumber=". + $atual["runnumber"]); + } + } + $upd=0; $ins=0; + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); +/* + $r2 = DBExec ($c,"select * from runtable where contestnumber=$contest and runsitenumber=".$atual["runsitenumber"]. + " and runnumber=".$atual["runnumber"]." for update"); + if (DBnLines($r2)>0) { + $p = DBRow($r2, 0); + DB_lo_unlink($c, $p["rundata"]); + } +*/ + if ($atual["runjudge"]=="") $atual["runjudge"]="null"; + if ($atual["runjudgesite"]=="") $atual["runjudgesite"]="null"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + $upd++; + DBExec ($c, "update runtable set ". + "usernumber=".$atual["usernumber"].",". + "rundate=".$atual["rundate"].",". + "rundatediff=".$atual["rundatediff"].",". + "rundatediffans=".$atual["rundatediffans"].",". + "runproblem=".$atual["runproblem"].",". + "runlangnumber=".$atual["runlangnumber"].",". + "runanswer=".$atual["runanswer"].",". + "runstatus='".escape_string($atual["runstatus"])."',". + "runjudge=".$atual["runjudge"].",". + "runjudgesite=".$atual["runjudgesite"].",". + "runfilename='".escape_string($atual["runfilename"])."',". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and runsitenumber=".$atual["runsitenumber"]. + " and runnumber=".$atual["runnumber"]." and updatetime<".$atual["updatetime"]); + } else if ($situacao[$j]=="inserir") { + $ins++; + DBExec($t, "begin work"); + $in = DB_lo_open($t, $atual["rundata"], "r"); + if (!$in) $o="0"; + else { + $o = DB_lo_create ($c); + $out = DB_lo_open ($c, $o, "w"); + while (($buf = DB_lo_read ($in, 1000)) != false) + DB_lo_write ($out, $buf); + DB_lo_close ($out); + DB_lo_close ($in); + + $in = DB_lo_open($t, $atual["rundata"], "r"); + if (!$in) { + $o="0"; + LOGLevel("Run not saved as file (run=".$atual["runnumber"].",site=".$atual["runsitenumber"]. + ",contest=$contest", 1); + } else { + $sitess=$atual["runsitenumber"]; + $nss=$atual["runnumber"]; + $user=$atual["usernumber"]; + $problem=$atual["runproblem"]; + $filename=escape_string($atual["runfilename"]); + $ttimet=$atual["rundate"]; + $fp = fopen("/tmp/boca/contest${contest}.site${sitess}.run${nss}.user${user}.". + "problem${problem}.time${ttimet}.${filename}", "w"); + if ($fp) { + while (($buf = DB_lo_read ($in, 1000)) != false) + fwrite ($fp, $buf); + fclose ($fp); + $fp = fopen("/tmp/check/contest${contest}.site${sitess}.run${nss}.user${user}.". + "problem${problem}.time${ttimet}.${filename}.check", "w"); + if ($fp) { + fwrite($fp, "1"); + fclose ($fp); + } + else + LOGLevel("Run not saved as check file (run=".$atual["runnumber"].",site=".$atual["runsitenumber"]. + ",contest=$contest", 1); + } else + LOGLevel("Run not saved as file (run=".$atual["runnumber"].",site=".$atual["runsitenumber"]. + ",contest=$contest", 1); + DB_lo_close ($out); + } + + } + DBExec ($c, "insert into runtable (contestnumber, runsitenumber, runnumber, usernumber, rundate,". + "rundatediff, rundatediffans, runproblem, runfilename, rundata, runanswer, runstatus, runjudge,". + "runjudgesite, runlangnumber, updatetime) ". + "values (".$contest.",".$atual["runsitenumber"].",".$atual["runnumber"].",".$atual["usernumber"].",". + $atual["rundate"].",". + $atual["rundatediff"].",". + $atual["rundatediffans"].",". + $atual["runproblem"].",". + "'".escape_string($atual["runfilename"])."',$o,". + $atual["runanswer"].",". + "'".escape_string($atual["runstatus"])."',". + $atual["runjudge"].",". + $atual["runjudgesite"].",". + $atual["runlangnumber"].",". + $atual["updatetime"].")"); + DBExec ($t, "commit work"); + } + } + echo " deletions=$del, updates=$upd, insertions=$ins\n\n"; + + // sincronizando runs + $r = DBExec ($t, "select * from runtable where contestnumber=$contest and runsitenumber=$localsite"); + $rr = DBExec ($c, "select * from runtable where contestnumber=$contest and runsitenumber=$localsite"); + $n = DBnLines ($r); + $nn = DBnLines ($rr); + echo "runs: external(site=$site, reading=$localsite)=$n, local=$nn\n"; + for ($k=0; $k<$nn; $k++) $needed[$k]=false; + for ($j=0;$j<$n;$j++) { + $la = DBRow($r,$j); + for ($k=0; $k<$nn; $k++) { + $aqui = DBRow($rr,$k); + if ($la["runnumber"]==$aqui["runnumber"] && $la["contestnumber"]==$aqui["contestnumber"] && + $la["runsitenumber"]==$aqui["runsitenumber"]) { + $needed[$k]=true; + if ($la["updatetime"]>$aqui["updatetime"]) { + $situacao[$j]="atualizar"; + + + if ($la["runanswer"] != "") { + $rrr = DBExec($c, "select * from answertable where answernumber=".$la["runanswer"]. + " and contestnumber=".$la["contestnumber"]); + $ans = (DBnLines($rrr)>0)? DBRow($rrr, 0) : null; + if ($ans == null) { + echo "Problem with the answer table. Unable to send balloon because the answer was " . + "not found (run=".$la["runnumber"].", site=".$la["runsite"].", contest=" . + $la["contestnumber"].", answer=".$la["runanswer"].")."; + $yesla = 'x'; + } else $yesla = $ans["yes"]; + } else $yesla='f'; + if ($aqui["runanswer"] != "") { + $rrr = DBExec($c, "select * from answertable where answernumber=".$aqui["runanswer"]. + " and contestnumber=".$aqui["contestnumber"]); + $ans = (DBnLines($rrr)>0)? DBRow($rrr, 0) : null; + if ($ans == null) { + echo "Problem with the answer table. Unable to send balloon because the answer was " . + "not found (run=".$aqui["runnumber"].", site=".$aqui["runsite"].", contest=" . + $aqui["contestnumber"].", answer=".$aqui["runanswer"].")."; + $yesaqui = 'x'; + } else $yesaqui = $ans["yes"]; + } else $yesaqui='f'; + + if ($yesla == 't' && $yesaqui == 'f') { + $rrr = DBExec ($c, "select * from sitetable where contestnumber=".$aqui["contestnumber"]. + " and sitenumber=$localsite"); + if (DBnLines($rrr)<=0) + echo "Site info not found (contest=${aqui["contestnumber"]}, site=$localsite)."; + else { + $b = DBRow($rrr,0); + $ti = $b["sitestartdate"]; + $tempo = time(); + $ta = $tempo - $ti; + $tf = $b["sitelastmileanswer"]; +// if ($ta < $tf) { + $rrr = DBExec ($c, "select * from usertable where contestnumber=". + $aqui["contestnumber"]." and usersitenumber=$localsite and usernumber=". + $aqui["usernumber"]); + if (DBnLines($rrr)<=0) + echo "User info not found (contest=${aqui["contestnumber"]}, ". + "site=$localsite, user=${aqui["runusernumber"]})."; + else { + $u = DBRow ($rrr,0); + $rrr = DBExec ($c, "select * from problemtable where contestnumber=". + $aqui["contestnumber"]." and problemnumber=". + $aqui["runproblem"]); + if (DBnLines($rrr)<=0) + echo "Problem info not found (contest=${aqui["contestnumber"]}, ". + "problem=${aqui["runproblem"]})."; + else { + $p = DBRow ($rrr,0); + mail("balloon@mainserver", "YES: team=" . $u["username"] . + ", problem=" . $p["problemname"], + "User ".$u["username"] ." should receive a balloon for ". + $p["problemfullname"]."\n"); + } + } +// } + } + } else if ($yesla == 'f' && $yesaqui == 't') { + $rrr = DBExec ($c, "select * from usertable where contestnumber=". + $aqui["contestnumber"]." and usersitenumber=$localsite and usernumber=". + $aqui["usernumber"]); + if (DBnLines($rrr)<=0) + echo "User info not found (contest=${aqui["contestnumber"]}, ". + "site=$localsite, user=${aqui["runusernumber"]})."; + else { + $u = DBRow ($rrr,0); + $rrr = DBExec ($c, "select * from problemtable where contestnumber=". + $aqui["contestnumber"]." and problemnumber=". + $aqui["runproblem"]); + if (DBnLines($rrr)<=0) + echo "Problem info not found (contest=${aqui["contestnumber"]}, ". + "problem=${aqui["runproblem"]})."; + else { + $p = DBRow ($rrr,0); + mail("balloon@mainserver", "NO: team=" . $u["username"] . + ", problem=" . $p["problemname"], + "Remove the balloon from user ". $u["username"] . + " for ".$p["problemfullname"]."\n"); + } + } + } + + + } + else + $situacao[$j]="ok"; + break; + } + } + if ($k>=$nn) $situacao[$j]="inserir"; + } + $upd=0; $ins=0; + for ($j=0;$j<$n;$j++) { + $atual = DBRow($r,$j); + + if ($atual["runjudge"]=="") $atual["runjudge"]="null"; + if ($atual["runjudgesite"]=="") $atual["runjudgesite"]="null"; + if ($atual["updatetime"]=="") $atual["updatetime"]=time(); + if ($situacao[$j]=="atualizar") { + $upd++; + DBExec ($c, "update runtable set ". + "usernumber=".$atual["usernumber"].",". + "rundate=".$atual["rundate"].",". + "rundatediff=".$atual["rundatediff"].",". + "rundatediffans=".$atual["rundatediffans"].",". + "runproblem=".$atual["runproblem"].",". + "runlangnumber=".$atual["runlangnumber"].",". + "runanswer=".$atual["runanswer"].",". + "runstatus='".escape_string($atual["runstatus"])."',". + "runjudge=".$atual["runjudge"].",". + "runjudgesite=".$atual["runjudgesite"].",". + "runfilename='".escape_string($atual["runfilename"])."',". + "updatetime=".$atual["updatetime"]. + " where contestnumber=$contest and runsitenumber=".$atual["runsitenumber"]. + " and runnumber=".$atual["runnumber"]." and updatetime<".$atual["updatetime"]); + } else if ($situacao[$j]=="inserir") { + $ins++; + echo "Run Inserts shouldn't exist (run=".$atual["runnumber"].")..."; + } + } + echo " updates=$upd, insertions=$ins\n\n"; + + DBExec($c, "commit work"); + DBClose($t); + } + DBClose($c); +} + +//fecha a conexao com o banco (isso nao eh realmente necessario, ja que o php/apache cuidam do servico) +function DBClose($c) { + if ($c) pg_close($c); +} +//executar instrucao no banco de dados, parando em caso de erro quando $stop=1 +function DBExec($conn,$sql) { +// echo $sql . "\n"; + $result = pg_exec ($conn, $sql); + if (!$result) { + echo "Unable to exec SQL in the database. SQL=(" . $sql . ")," . + " Error=(" . pg_errormessage($conn) . ")\n"; + exit; + } + return $result; +} +//devolve o numero de linhas da consulta +function DBnlines ($result) { + return pg_numrows ($result); +} +//pega uma linha da consulta no formato de array +function DBRow ($r, $i) { + return pg_fetch_array ($r, $i); +} +function escape_string($s) { + return str_replace("'", "''", $s); +} +if (getIP()!="UNKNOWN") exit; + +$x = DBConnect(); +if ($x==null) exit; +$y = DBExec($x, "select * from contesttable where contestactive='t'"); +if (DBnLines($y)==0) { + echo "Unable to find the active contest in the database.\n"; + exit; +} +$ct = DBRow($y,0); +DBClose($x); +GetExternalData($ct["contestnumber"]); + +?> diff --git a/boca-1.5.0/old/import-system.txt b/boca-1.5.0/old/import-system.txt new file mode 100644 index 0000000..7a23479 --- /dev/null +++ b/boca-1.5.0/old/import-system.txt @@ -0,0 +1,78 @@ +import-system.txt +----------------- +Last modified 20/aug/2007 by cassio@ime.usp.br + +************************************ +OUTDATED INFORMATION. PLEASE WAIT FOR A NEW VERSION OF THIS FILE. +FOR MORE DETAILS, SEE THE EXAMPLE FILE: bits/import.txt +************************************ + + + +It's possible to create a language file +(or use the same user file for it, putting the +languages at the end). Following are some language +examples, but it is recommended to insert the +languages by the web pages directly. See the files +run.sh and compare.sh for compiling/running script and +comparing script respectively. + + +[language] +langnumber=1 +langname=C +langscript=runscriptforlang1.sh +#!/bin/bash +echo este eh o runscript 1... +exit 1 +***END*** +langcompscript=compscriptforlang1.sh +#!/bin/bash +echo este eh o compscript 1... +exit 1 +***END*** + +langnumber=2 +langname=C++ +langscript=runscriptforlang2.sh +#!/bin/bash +echo este eh o runscript 2... +exit 2 +***END*** +langcompscript=compscriptforlang2.sh +#!/bin/bash +echo este eh o compscript 2... +exit 2 +***END*** + +langnumber=3 +langname=Java +langscript=runscriptforlang3.sh +#!/bin/bash +echo este eh o runscript 3... +exit 3 +***END*** +langcompscript=compscriptforlang3.sh +#!/bin/bash +echo este eh o compscript 3... +exit 3 +***END*** + + + +Contacts and Copyrights +----------------------- +BOCA Copyright (c) 2003- Cassio Polpo de Campos (cassio@ime.usp.br) +http://www.ime.usp.br/~cassio/boca + +This software may be distributed under the terms of the Q Public +License version 1.0. A copy of the license can be found with this +software or at http://www.opensource.org/licenses/qtpl.php + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. diff --git a/boca-1.5.0/old/import.php b/boca-1.5.0/old/import.php new file mode 100644 index 0000000..45dd4bd --- /dev/null +++ b/boca-1.5.0/old/import.php @@ -0,0 +1,280 @@ +<?php +////////////////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +// +//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +/////////////////////////////////////////////////////////////////////////////////////////// +//Change list +// 17/aug/2007 by cassio@ime.usp.br: created +// 25/aug/2007 by cassio@ime.usp.br: php initial tag changed to complete form + +require 'header.php'; + +if (isset($_FILES["importfile"]) && isset($_POST["Submit"]) && $_FILES["importfile"]["name"]!="") { + if ($_POST["confirmation"] == "confirm") { + $type=myhtmlspecialchars($_FILES["importfile"]["type"]); + $size=myhtmlspecialchars($_FILES["importfile"]["size"]); + $name=myhtmlspecialchars($_FILES["importfile"]["name"]); + $temp=myhtmlspecialchars($_FILES["importfile"]["tmp_name"]); + if (!is_uploaded_file($temp)) { + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + if (($ar = file($temp)) === false) { + IntrusionNotify("Unable to open the uploaded file."); + ForceLoad("../index.php"); + } + echo "<br>Starting to create the contest<br>"; + $asep = trim($ar[0]); + $i=1; + + for (; $i<count($ar) && strpos($ar[$i], "[contest]") === false; $i++) ; + for ($i++; $i<count($ar) && $ar[$i][0] != "["; $i++) { + $x = trim($ar[$i]); + //contestname, startdate, duration, lastmileanswer, lastmilescore, penalty, contestactive + $tmp = explode("=", $x, 2); + $param[trim($tmp[0])]=trim($tmp[1]); + } + $nc = DBNewContest($param); + echo "<br>Contest $nc created<br>"; + + for (; $i<count($ar) && strpos($ar[$i], "[site]") === false; $i++) ; + while(strpos($ar[$i],"[site]") === true) { + for ($i++; $i<count($ar) && $ar[$i][0] != "["; $i++) { + $x = trim($ar[$i]); + // sitenumber, siteip, sitename, scorelevel + $tmp = explode("=", $x, 2); + $param[trim($tmp[0])]=trim($tmp[1]); + } + DBNewSite($nc, null, $param); + echo "New site created<br>"; + } + + for (; $i<count($ar) && strpos($ar[$i], "[answer]") === false; $i++) ; + for ($i++; $i<count($ar) && $ar[$i][0] != "["; $i++) { + echo "<br>Searching for answers<br>\n"; + $x = trim($ar[$i]); + if (strpos($x, "answ") !== false && strpos($x, "answ") == 0) { + unset($answnumber); + unset($answname); + unset($answyes); + while (strpos($x, "answ") !== false && strpos($x, "answ") == 0) { + $tmp = explode ("=", $x, 2); + switch (trim($tmp[0])) { + case "answernumber": $answnumber =trim($tmp[1]); break; + case "answername": $answname =trim($tmp[1]); break; + case "answeryes": $answyes =trim($tmp[1]); break; + } + $i++; + if ($i>=count($ar)) break; + $x = trim($ar[$i]); + } + if (isset($answnumber) && is_numeric($answnumber) && isset($answname)) { + DBNewAnswer ($nc, $answnumber, $answname, $answyes); + echo "Answer $answnumber created<br>"; + } + } + } + + for (; $i<count($ar) && strpos($ar[$i], "[language]") === false; $i++) ; + for ($i++; $i<count($ar) && $ar[$i][0] != "["; $i++) { + echo "<br>Searching for languages<br>\n"; + $x = trim($ar[$i]); + if (strpos($x, "lang") !== false && strpos($x, "lang") == 0) { + unset($langnumber); + unset($langname); + unset($langproblem); + unset($script); + unset($compscript); + unset($langscript); + unset($langcompscript); + unset($langscripthash); + unset($langcompscripthash); + while (strpos($x, "lang") !== false && strpos($x, "lang") == 0) { + $tmp = explode ("=", $x, 2); + switch (trim($tmp[0])) { + case "langnumber": $langnumber =trim($tmp[1]); break; + case "langname": $langname =trim($tmp[1]); break; + case "langproblem": $langproblem =trim($tmp[1]); break; + case "langscripthash": $langscripthash =trim($tmp[1]); break; + case "langscript": $langscript =trim($tmp[1]); + $i++; + for ($j=1; trim($ar[$i]) != "***$asep***"; $j++) { + if(substr($langscript,0,7)!="base64:") $script .= $ar[$i]; + else $script .= trim($ar[$i]); + $i++; + } + if(substr($langscript,0,7)=="base64:") { + $langscript = substr($langscript,7); + $script = base64_decode($script); + } + if(trim($langscripthash) != "" && myshorthash($script) != trim($langscripthash)) + echo "ERROR: Hash of $langscript does not match $langscripthash, ".myshorthash($script)."<br>\n"; + break; + case "langcompscripthash": $langcompscripthash=trim($tmp[1]); break; + case "langcompscript": $langcompscript =trim($tmp[1]); + $i++; + for ($j=1; trim($ar[$i]) != "***$asep***"; $j++) { + if(substr($langcompscript,0,7)!="base64:") $compscript .= $ar[$i]; + else $compscript .= trim($ar[$i]); + $i++; + } + if(substr($langcompscript,0,7)=="base64:") { + $langcompscript = substr($langcompscript,7); + $compscript = base64_decode($compscript); + } + if(trim($langcompscripthash) != "" && myshorthash($compscript) != trim($langcompscripthash)) + echo "ERROR: Hash of $langcompscript does not match<br>\n"; + break; + } + $i++; + if ($i>=count($ar)) break; + $x = trim($ar[$i]); + } + if (isset($langnumber) && is_numeric($langnumber) && isset($langname)) { + DBNewLanguage ($nc, + $langnumber, $langname, $langproblem, '', '', + $langshowingoutput, $script, $langscript, $compscript, $langcompscript, 1, 1); + echo "Language $langnumber created<br>"; + } + } + } + + for (; $i<count($ar) && strpos($ar[$i], "[problem]") === false; $i++) ; + for ($i++; $i<count($ar) && $ar[$i][0] != "["; $i++) { + echo "<br>Searching for problems<br>\n"; + $x = trim($ar[$i]); + if (strpos($x, "prob") !== false && strpos($x, "prob") == 0) { + unset($probnumber); + unset($probname); + unset($probfullname); + unset($probbasename); + unset($probinputfile); + unset($probinputfilehash); + unset($probinputfilepath); + unset($probsolfile); + unset($probsolfilehash); + unset($probsolfilepath); + unset($probdescfile); + unset($probdescfilehash); + unset($probdescfilepath); + unset($probtimelimit); + unset($probcolorname); + unset($probcolor); + while (strpos($x, "prob") !== false && strpos($x, "prob") == 0) { + $tmp = explode ("=", $x, 2); + switch (trim($tmp[0])) { + case "probnumber": $probnumber =trim($tmp[1]); break; + case "probname": $probname =trim($tmp[1]); break; + case "probfullname": $probfullname =trim($tmp[1]); break; + case "probbasename": $probbasename =trim($tmp[1]); break; + case "probtimelimit": $probtimelimit =trim($tmp[1]); break; + case "probcolorname": $probcolorname =trim($tmp[1]); break; + case "probcolor": $probcolor =trim($tmp[1]); break; + case "probinputfilehash": $probinputfilehash =trim($tmp[1]); break; + case "probinputfile": $probinputfile =trim($tmp[1]); + $i++; + for ($j=1; trim($ar[$i]) != "***$asep***"; $j++) { + if(substr($probinputfile,0,7)!="base64:") $probinputfilepath .= $ar[$i]; + else $probinputfilepath .= trim($ar[$i]); + $i++; + } + if(substr($probinputfile,0,7)=="base64:") { + $probinputfile = substr($probinputfile,7); + $probinputfilepath = base64_decode($probinputfilepath); + } + if(trim($probinputfilehash) != "" && myshorthash($probinputfilepath) != trim($probinputfilehash)) + echo "ERROR: Hash of $probinputfile does not match<br>\n"; + break; + case "probsolfilehash": $probsolfilehash =trim($tmp[1]); break; + case "probsolfile": $probsolfile =trim($tmp[1]); + $i++; + for ($j=1; trim($ar[$i]) != "***$asep***"; $j++) { + if(substr($probsolfile,0,7)!="base64:") $probsolfilepath .= $ar[$i]; + else $probsolfilepath .= trim($ar[$i]); + $i++; + } + if(substr($probsolfile,0,7)=="base64:") { + $probsolfile = substr($probsolfile,7); + $probsolfilepath = base64_decode($probsolfilepath); + } + if(trim($probsolfilehash) != "" && myshorthash($probsolfilepath) != trim($probsolfilehash)) + echo "ERROR: Hash of $probsolfile does not match<br>\n"; + break; + case "probdescfilehash": $probdescfilehash=trim($tmp[1]); break; + case "probdescfile": $probdescfile =trim($tmp[1]); + $i++; + for ($j=1; trim($ar[$i]) != "***$asep***"; $j++) { + if(substr($probdescfile,0,7)!="base64:") $probdescfilepath .= $ar[$i]; + else $probdescfilepath .= trim($ar[$i]); + $i++; + } + if(substr($probdescfile,0,7)=="base64:") { + $probdescfile = substr($probdescfile,7); + $probdescfilepath = base64_decode($probdescfilepath); + } + if(trim($probdescfilehash) != "" && myshorthash($probdescfilepath) != trim($probdescfilehash)) + echo "ERROR: Hash of $probdescfile does not match<br>\n"; + break; + } + $i++; + if ($i>=count($ar)) break; + $x = trim($ar[$i]); + } + if (isset($probnumber) && is_numeric($probnumber) && isset($probname) && + isset($probfullname) && isset($probbasename) && + isset($probtimelimit) && isset($probcolorname) && isset($probcolor)) { + DBNewProblem ($nc, + $probnumber, $probname, $probfullname, $probbasename, $probinputfile, + $probinputfilepath, $probsolfile, $probsolfilepath, 'f', $probdescfile, $probdescfilepath, + $probtimelimit, $probcolorname, $probcolor, 1, 1, 1); + echo "Problem $probnumber created<br>"; + } + } + } + } + echo "</body></html>"; + exit; +} +?> +<br> +<br> +<center><b> +To import a pre-defined contest, just fill in the import file field.</b></center> +<br> +<form name="form1" enctype="multipart/form-data" method="post" action="import.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="0"> + <tr> + <td width="25%" align=right>Import file:</td> + <td width="75%"> + <input type="file" name="importfile" size="40"> + </td> + </tr> + </table> + </center> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Import" onClick="conf()"> + <input type="reset" name="Submit2" value="Clear"> + </center> +</form> + +</body> +</html> + diff --git a/boca-1.5.0/old/import.txt b/boca-1.5.0/old/import.txt new file mode 100644 index 0000000..7af6b5b --- /dev/null +++ b/boca-1.5.0/old/import.txt @@ -0,0 +1,1143 @@ +end123 + +[contest] +contestname=Fase Regional da Maratona de Programacao 2007 +scorelevel=4 +sitename=Nome do meu site +startdate=1190480400 + +[site] + +[answer] +answernumber=1 +answername=NO - Compile error +answeryes=f + +answernumber=2 +answername=NO - Runtime error +answeryes=f + +answernumber=3 +answername=NO - Time limit exceeded +answeryes=f + +answernumber=4 +answername=YES +answeryes=t + +answernumber=5 +answername=NO - Presentation error +answeryes=f + +answernumber=6 +answername=NO - Wrong answer +answeryes=f + +answernumber=7 +answername=NO - Contact staff +answeryes=f + +answernumber=8 +answername=NO - Problem/File name mismatch +answeryes=f + +[language] +langnumber=1 +langname=C +langscriptmd5=7da844fdb1408384529484e9010b6b5d +langscript=run.sh +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 21/aug/2007 by cassio@ime.usp.br +# +# parameters are: +# $1 base_filename +# $2 source_file +# $3 input_file +# $4 languagename +# $5 problemname +# $6 timelimit +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened: +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 +chown nobody.nogroup . + +export CLASSPATH=.:$CLASSPATH + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec +gcc=`which gcc` +[ -x "$gcc" ] || gcc=/usr/bin/gcc +gpp=`which g++` +[ -x "$gpp" ] || gpp=/usr/bin/g++ +java=`which java` +[ -x "$java" ] || java=/usr/java/bin/java +javac=`which javac` +[ -x "$javac" ] || javac=/usr/java/bin/javac +pascal=`which fpc` +[ -x "$pascal" ] || pascal=/usr/bin/fpc +grep=`which grep` +[ -x "$grep" ] || grep=/bin/grep + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then + echo "parameter problem" + exit 43 +fi +if [ ! -r "$2" ]; then + echo "$2 not found or it's not readable" + exit 44 +fi +if [ ! -r "$3" ]; then + echo "$3 not found or it's not readable" + exit 45 +fi +if [ ! -x "$sf" ]; then + echo "$sf not found or it's not executable" + exit 46 +fi + +prefix=$1 +name=$2 +input=$3 + +# setting up the timelimit according to the problem +# note that problems should spelling the same as inside BOCA +if [ "$6" == "" ]; then +time=5 +else +time=$6 +fi +let ttime=$time+30 + +# choose the compiler according to the language +# note that languages should spelling the same as inside BOCA +case "$4" in +C) + $gcc -lm -o "$prefix" "$name" + ret=$? + if [ "$ret" != "0" ]; then + echo "Compiling Error: $ret" + exit 1 + else + $sf -F10 -t$time -T$ttime -i$input -n0 -R. "./$prefix" + ret=$? + if [ $ret -gt 3 ]; then + ret=0 + fi + fi + ;; +C++) + $gpp -lm -o "$prefix" "$name" + ret=$? + if [ "$ret" != "0" ]; then + echo "Compiling Error: $ret" + exit 1 + else + $sf -F10 -t$time -T$ttime -i$input -n0 -R. "./$prefix" + ret=$? + if [ $ret -gt 3 ]; then + ret=0 + fi + fi + ;; +Pascal) + $pascal -o"$prefix" "$name" >compiler.out 2>compiler.out + $grep -irq linking compiler.out + ret=$? + $grep -irq "lines compiled" compiler.out + ret2=$? + if [ "$ret" != "0" -o "$ret2" != "0" ]; then + cat compiler.out + echo "Compiling Error: $ret" + exit 1 + else + $sf -F10 -t$time -T$ttime -i$input -opascal.out -n0 -R. "./$prefix" + ret=$? + if [ -f pascal.out ]; then + cat pascal.out + $grep -irq "runtime error" pascal.out + ret2=$? + if [ "$ret2" = "0" ]; then + echo "Strange output - possible runtime error" + if [ $ret -lt 4 ]; then + ret=48 + fi + fi + fi + fi + ;; +Java) + $javac "$name" + ret=$? + if [ "$ret" != "0" ]; then + echo "Compiling Error: $ret" + exit 1 + else + $sf -u10 -F30 -t$time -T$ttime -i$input -n0 -R. $java "$prefix" + ret=$? + if [ $ret -gt 3 ]; then + echo "Nonzero return code - possible runtime error" + ret=47 + fi + fi + ;; +*) + echo "Language not recognized" + exit 42 + ;; +esac +exit $ret +***end123*** +langcompscriptmd5=bde30aa6d558a0b1596ce7bf8daa75f3 +langcompscript=compare.sh +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 21/aug/2007 by cassio@ime.usp.br +# +# This script receives: +# $1 team_output +# $2 sol_output +# $3 languagename +# $4 problemname +# $5 problem_input +# +# BOCA reads the last line of the standard output +# and pass it to judges +# +# Next lines of this script just compares team_output and sol_output, +# although it is possible to change them to more complex evaluations. + +if [ ! -r "$1" -o ! -r "$2" ]; then + echo "Parameter problem" + exit 43 +fi +diff -q "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff \"$1\" \"$2\" # files match" + echo "Files match exactly" + exit 4 +fi +diff -q -b "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b \"$1\" \"$2\" # files match" + echo -e "diff -c \"$1\" \"$2\" # files dont match - see output" + diff -c "$1" "$2" + echo "Files match with differences in the amount of white spaces" + exit 5 +fi +diff -q -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b \"$1\" \"$2\" # files dont match - see output" + diff -c -b "$1" "$2" + echo "Files match with differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -i -b -B "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B "$1" "$2" + echo "Files match if we ignore case and differences in the amount of white spaces and blank lines" + exit 5 +fi +diff -q -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -i -b -B \"$1\" \"$2\" # files dont match - see output" + diff -c -i -b -B "$1" "$2" + echo "Files match if we discard all white spaces" + exit 5 +fi +diff -q -i -b -B -w "$1" "$2" >/dev/null 2>/dev/null +if [ "$?" == "0" ]; then + echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files match" + echo -e "diff -c -b -B -w \"$1\" \"$2\" # files dont match - see output" + diff -c -b -B -w "$1" "$2" + echo "Files match if we ignore case and discard all white spaces" + exit 5 +fi +echo -e "diff -c -i -b -B -w \"$1\" \"$2\" # files dont match - see output" +diff -c -i -b -B -w "$1" "$2" +echo "Differences found" +exit 6 +***end123*** + +[problem] +probnumber=1 +probname=A +probfullname=Bits +probbasename=bits +probtimelimit=2 +probcolorname=Branco +probcolor=ffffff +probinputfilemd5=3d80104620532811bddcb6ee7ae45ff1 +probinputfile=base64:bits.in +MSA3CjQgMSAxMCAyMCAzMAoyIDIwMDAgOTk5CjMgMCAwIDAKMiAxIDEwMDAK +MTAwMCAxMDczNzQxODI0IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwCjEgMAoxIDgKMAo= +==== +***end123*** +probsolfilemd5=01cb6992846e7c6d7e77ca91fd1c401a +probsolfile=bits.sol +Instancia 1 +3 + +Instancia 2 +20 + +Instancia 3 +22 + +Instancia 4 +3 + +Instancia 5 +20 + +Instancia 6 +31000 + +Instancia 7 +1 + +Instancia 8 +4 + +***end123*** +probdescfile=base64:warmup07.pdf +JVBERi0xLjQKMyAwIG9iaiA8PAovTGVuZ3RoIDIwMTYgICAgICAKL0ZpbHRl +ciAvRmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnjajRjZjtzG8V1fMfITCXgY9sHL +yEssbAAFSCRACySA1wZaHO6qlSE54rEQAsPfnrqaw5nhSt6H7WZdXVVdV8/P +96/+8neV75RKqizTu/vHndZ5kqoq2xVpkSidqd394ZfoP2/jvSmy6J9ucFMf +71XUOYYcGl7fDwR+GvC/i1XU0uYhNWmcpWlUx2X0R5xlNnI9c+x5+XdcAYzY +2tioaD7Fv97/g9WyibE5qbWvdALKqN3e6KSyWUlq3Y0TndLS2SMKtNHYdAc6 +Io98hxKf49xE7uCR5tCPIr7aVUmV6xylp7u9Vkmp2di/DV9m/9z/5LtnN7o+ ++aX+vT6dfv/snt2vzFxe8aaJzSpmfhfvdYWm6CKawQ3dAf71CNRRM6IK00Oq +DfnEMe3YkENj1I4hoLcuQe8sJ70R8fr163hvTRrdwee9mIu0xDxOg0MBn2Kl +VEQHmLLCTTrSoT7cSD+yLnXf8qb9g3UJCNS34a29gCjaBDJXu4+uvWFxUzMM +fhzxQhftWvQaOorjjB31OASxYGwVTRhHZYoq6+AcU1TRGzdyRNHXz2BmLXth +aL76p6blvWB82xy8m+RraOgOPIWitTaqg8VJvM9KjVeGdO+BaGBv+sNKt5J1 +w9Pn8RPvDmCinP9lZlrco3NIj7YZfO06Draz5Zosfw7nA7Gx0XGe0Fu4dRMe +R9dnC01STRYJ3UOqbPsjg1r0Cm4cL2Tg6Yj3w3lXe8dclApAAZ4b/ZFhn9cR +iABysZzmSJZjw/uZCQS3EcCInVbX6ELAB7XYtoySoeXt58ZPnsJVTIMisuGn +gY/r0axnVIeOIXEFn1BGp6H/COhj04YoAeBI8WCqCFGDf3IYanDZUDaiNySy +FfbRd+7IAqmQAci1IV/+RyIDnO4W1o8ojIPSH0OY+EFSA0+lyIC1fwzoJdTr +5dOJiidykSjOBtdDszZ3I3dmZM6AmY59GlzrGPBlbngD9eAwsw0ml8AEcAdZ +KQGWwWYOVaEZiAIow+0BMds4TmffAjDUAKS9uxexJ7YAdsIKkT/2GKt5Dhbu +oRb2XpjQsyR5FNrLaMyqUNHcuQaeVQvhtREudd89zkH4KsULVUXvAGh1xhrj +Zh7xAqzOUWMEjGgoFSvHgJ5cVU8YH/j9kGapwxzEwHVHMM5ayBBU8jfO1lYY +/SQyDw20G+BTosXdsRn50MM6MoImchthe5x864Iot11KoNAEKb6mW+rkflT0 +E2poogdl7AeKSMNZJIatFA/N0+ioW9cmKOcfxeGdW2K4ZVlC8Z4ilavF+SKf ++i5UARM1wqE0r58QNXAFA+xXTIEja0XNbmiWToUE00wN8AdMYKje77HMcP6N +7uDGrfxQKfbKEuoLHWMNBaaleoHs6wrLbc0L/rH3vCHMV8CcgmpIRb7Aq88z +DPqY0gLFjzN+nKBkCUDyyEqKv9BYwheJtJy+yIJxBji6UqzBpBGkxDA0dShP +B1GZiVpmdGKGw9IEKbQRM1TQrtqMIlUkhDAL83OiZwXcEdST/bTEmlTmaYmJ +EVupMpRnyOygrC6JPjmBXvSJgSogCacAgH45CHPPK3rTH5pzC0aclCvqrgyS +ZenDKHJwAbfhgNGzWg1VTaVZo5lGNnGKia7yCg9RalUUsLipTDpny3LGmes7 +j1xYe6zJow+zY+bpnEOPHDm6tJfdXi2R0h+5BwzLwXgChZJ0PC5WokfDeJAJ +Vn8G/Lz0XsVXivq5I9fTtdCbWTU5z9/nZwFOuUVSlqXlwZsGaxq+odG4zalY +lQnMoEz/4VxWrIWBkYYMSk3I6OdYRlYiGTzDTUQjAl/Vb4zrQk74FXsnWQgc +EisDi8eqCzf5hr++LxNJVHYRAiifuA+ONQ8VEGUt3VNwR999WunCi2SnNEHJ +B6Y/UTD1L3Z4qxU17GLVsM/1vmeCVG5LrZyf20SlVoFMFPVXJDQoyWoLXzd3 +ZYDcWCPkKoU/lh3GET+dz+tkveqXnBoFmys9M6WeedlzCuo57B2tw2ywFFgB +j7MgBpbDdVFzQcIVaCGe5Z1DpSwF7ifovEJQigW8VKL7EoXo8X1VJtpAQF92 +1JO7mtZa6eAYC++4JV3cSnExRjFBKr0tPOxqxvKcZyJ3gZZGgIn044LAsRg5 +1/3YQO0OkyHin84jxMB4eSvdPAIlH76f2B+AWYccMAUzfz+/aQpY+mEKbyzO +GNhhqnbjkm30MLEpmCL4kLNLlqXXc0pxnlOQYWmhUiDX4yMy+/Y0LM9dPzAw +zFao0FUP9lR+lAWVORevfhwwKk9UZTPJj7dgjJiRgaf+e+ubXCVZZkqh7zs+ +7zZNtU1sVVZCtyGoSjQ0EMGv+wSaIUFs4S5tlZaX5WMrQDlYev4VIZRE2Pqb +2wGgo6nLHbGGwovtXwLGqeJc5QDA/e9p9ssj3hr18pyJyKv7EyUuLi2mZx7C +Rd1vvFuYoO4HGUqkcnSHm58X8PDupdfD5VBgVmFWwxh+lPx/2/IR+KxsJYvn +wHHhHHo1t7zSMxScK0nsTkvI8owb0gWR32t6LyVxhr+P5fKz2FeeoGl0xd/B +wo904g8Y269a9/WvYUZDSTCc29mWu2CW34IqtdXM0i2dtSqSrKjKXV4mhYU0 ++Kbm4zfq0rXyXJjMVraqLa0XA7VJKpVuMm6bm/4JTrPFWZjbbN8XCWQJtKU0 +MabK+AQke3V3/+r/9sdL7GVuZHN0cmVhbQplbmRvYmoKMiAwIG9iaiA8PAov +VHlwZSAvUGFnZQovQ29udGVudHMgMyAwIFIKL1Jlc291cmNlcyAxIDAgUgov +TWVkaWFCb3ggWzAgMCA1OTUuMjc1NiA4NDEuODg5OF0KL1BhcmVudCAxNiAw +IFIKPj4gZW5kb2JqCjEgMCBvYmogPDwKL0ZvbnQgPDwgL0YxNiA2IDAgUiAv +RjE5IDkgMCBSIC9GOCAxMiAwIFIgL0YxMSAxNSAwIFIgPj4KL1Byb2NTZXQg +WyAvUERGIC9UZXh0IF0KPj4gZW5kb2JqCjE0IDAgb2JqIDw8Ci9MZW5ndGgx +IDc4MQovTGVuZ3RoMiAxNTQ3Ci9MZW5ndGgzIDUzMgovTGVuZ3RoIDIxMTcg +ICAgICAKL0ZpbHRlciAvRmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnja7VJrOJTr +Gq6wqlELITOl+iymHMc3wxhDDkNkYiyFcoxp5hummflmmoM9Isqpg6KD1FA5 +RpgiSpSSqU2rcoiKKZLSioWEaiO0hlZX12793PvXvvb3/nnv57nf+7m/+33R +el7eZiQ6dwfkyoWFZlgM1gZwplDIWBBQ7EEQgUY78yGqkMmFN1CFkA2AJRKt +gE0iNoCzAECCDd7CBk9AoAFnLi+SzwwLFwKGzkazJAJA4kB8Jo0KAxSqMBzi +KDRoVDbgzaUxIWEkBiCx2cCW2RMCYAskgPgREB2DwGIBOpMmBHZAYUwYYT7r +iQwzuADha5ku4n1rRUB8gcIUYDhn0whQmKRzYXYkQIcYCHNPrmIapPDy37D1 +o7iriM32pHJm5eeS+lufymGyI/9icDk8kRDiAxQuHeLDP1K3QV/NUSA6U8T5 +sUsWUtlMGgkOY0OAGdYSA1p+rTMFrkwxRPdiCmnhAIPKFkBzdQim/+hEkd+c +D3MntwCXzWSTv652rulFZcJCn0geBIDf2XMY+x0rQuIzxUAgiAFBrIKoWN92 +wT8Mc4FpXDoTDgNweCuAyudTIxGKR6RAeCAKCzBhOiQGILHCsTkG5goVRwBF +MnsABpePmL1XKxAwZ0MCwWx1roAFCYA56ztU+DaH5+Dff9LJiSuOMrPAAWY4 +vGIoaGkNEPDgnn8j0kR8PgQL5x6SIqpvmMFUpAtBYoiGkD/l0mwTdp6qTCqK +cclrKVYxEuhKChMe3kq8IrHFDLywXfaYf63ZB1o9qpGosZNZop4+5H7RnM7A +v0RVkqIborzNEzs0GpZqGeVkeC8cpg0EbV9wL6tepsY5e/CtfE0v75rJ8DP9 +j90Rt1RKPfqxhFzU0CHlovan02MxrNjGl3LV03T9N+mI4KwbHiehrX3dRx9M +Dm7k5nHl5+/pBGV81JyRo2RdrazOpRJichZF6YnEbmoxaCRm9DQisJmsNXK/ +c8RN3jaLdK0eb82WAPNW2OlJ/Oyrq9wp7xa9fmREfK0nWdJKjtuT7raN7Ptp +ZXHOMlrRSrbdxvOo+VCZLKCWYw/X7e8t2xy3jFXWgrNLw/KunURvCZ2YRo8a +HFH+EPz584t/fUlG1Q7TovTmIS8t2GZinekQYWgyYPQQRKm0HWjQ86eGn3gr +JDm4vVB1TK7nNDn0RFePUwA/4pO9Wk8vHNCX4xD9NhOcU9mmlACT8qqG40Eu +4nlE/7vw+p7c93/crU3OxG13dQ58EVrj025yT3r1dt4GTel+5eCGKlfXPIOq +RdyO1046evaaurba6qSgXh8gPEVe1yo+Ohh+M3oZfnJiVYmN1dnWKds3zem+ +DdeGCq1Wxai8iV/JSsEM+hhHWb9TuuUuDY1ssZZWNPy2fN0puk+02eZTrJIi +96IkTuQIcfHJYmLZe6xSdvTND6SqfzKy+EeBUkP32I/GRvXokPvSEaH6Ua/P +uaEYvr9DTa0M5sO9lyaiInA1v4bgbYPCZlrtC7fkn49KjR0eabdcdTAEYaPa +0/GaiOK57E6P+ZLwqWOjSFXDpephoBx+Wyzp+u0lk/g6/ma+hkjfzu/iWvta +VOntV+OOm81wGgyfKJDtb3Jofs8kml6dy5FqoelavfecqGGGcmQDRfMO+QMS +bqjmJSe5CtEF0xV56VvNY3o7HK9Y6Qk9xnNtYO+15Eq28bwFXcrjY+nI3o/8 +fWfb3AhXs1PoDp05XgGfcibtuh9NivZq3h861Pj8hgWFQfkS6H0yVIfBS2s8 +ItMqYLQ/Mi23vw1ik53aUfmWmanbH5smW4f1ZhQhy2Rnzqr1rcDXRFtKfqrO +xwgdHqpcaL5eXyjoqkwoLeg8F0YMe/DLO6/sT7tOmyay2sFliCPjZ8ZNaaEI +raTAIVXOuyWOrZkGlV7q9dLJ52F8C86TYG3x7ncf5u8/X7c+LMLx2W38rnMG +g2NVwaGeR5YHZ1iZld/BLEy7UfqUMKIPdvhlxFp2+dh/tCUbhzp4WOmkrlpa +0RM6z/uu/3Q+raRvNdZkgOeYkus1YbV7PaNyn0TOOS4t+P0Mmdnu2LQ6v968 +cdQi3nrhg4TGZJ8Cgwwl57G9RW7UY+9Vdqj/vLAurT8ge43NVGRFkiESakg8 +fGKie6ZptCLvZVG7byRQ7Tc5sOVO2pMNwVc3zEy1g7qbqJJRtV34+8/EbjML +fCt0e2mfr5NYDXJZf9ov958uvg5jrwwwWqY9ZTkX2dFY1T055a3S9XrpU+3N +hSGZruPXfyLj2vY4tSBry9YERBUuGIohli7ERdWd+BLkecBxbMTGtA8Tu2m6 +0viACzngWL+/54oVzlE9XWVBD8XT8uaxQe1Rv/5jgahXam1El7F4nZT4ff5M +8uoEVZnPziP9yNj08yk3lIe33dN9G7jyCt24Rqlj7NKiCGmrwFrtHyzkzti4 +aelamDgCbmsbPp5dVkQM0Xoev6ldmeXiZVshSppEeOnUTqbgrHWnKi43FjYp +FT7W3kV/U00brNFsQpabBmTRRLEkKjmGvvqVq9qX7vyWOIME0lEN33G9cfQ6 +lgfveSrmjp1l0KmsmRMyafHpcu01Tpdj2+rW1d39lVdQ5E6+MRTSstmzoqxp +g+0fnmkth4uFdp6Ld3dq09U3pg7piy2fsQ/2qpNjesK5O2TLr/Sftiz5eSiZ +LOBdRh9GLallm5anrovz7pNsbVnBQjEPEnyzKJkY6jVnwz7272WqzfffLLHr +XPrc99jiuBlCYkm4V0JbRp4nL2/AadX0T8fOdKtzkafvXsjxT9w100YYCZmP +tAzIWZ4psvLozN+9lAX+hx/i/wL/EwI0NkTlC7kcKp+F+BNxl1mpZW5kc3Ry +ZWFtCmVuZG9iagoxNSAwIG9iaiA8PAovVHlwZSAvRm9udAovU3VidHlwZSAv +VHlwZTEKL0VuY29kaW5nIDE3IDAgUgovRmlyc3RDaGFyIDYwCi9MYXN0Q2hh +ciAxMTAKL1dpZHRocyAxOCAwIFIKL0Jhc2VGb250IC9CSFpFUUkrQ01NSTEw +Ci9Gb250RGVzY3JpcHRvciAxMyAwIFIKPj4gZW5kb2JqCjEzIDAgb2JqIDw8 +Ci9Bc2NlbnQgNjk0Ci9DYXBIZWlnaHQgNjgzCi9EZXNjZW50IC0xOTQKL0Zv +bnROYW1lIC9CSFpFUUkrQ01NSTEwCi9JdGFsaWNBbmdsZSAtMTQuMDQKL1N0 +ZW1WIDcyCi9YSGVpZ2h0IDQzMQovRm9udEJCb3ggWy0zMiAtMjUwIDEwNDgg +NzUwXQovRmxhZ3MgNAovQ2hhclNldCAoL2xlc3Mvay9uKQovRm9udEZpbGUg +MTQgMCBSCj4+IGVuZG9iagoxOCAwIG9iagpbNzc4IDAgMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgNTIxIDAgMCA2MDAg +XQplbmRvYmoKMTcgMCBvYmogPDwKL1R5cGUgL0VuY29kaW5nCi9EaWZmZXJl +bmNlcyBbIDAgLy5ub3RkZWYgNjAvbGVzcyA2MS8ubm90ZGVmIDEwNy9rIDEw +OC8ubm90ZGVmIDExMC9uIDExMS8ubm90ZGVmXQo+PiBlbmRvYmoKMTEgMCBv +YmogPDwKL0xlbmd0aDEgMTYxOQovTGVuZ3RoMiA5NzMzCi9MZW5ndGgzIDUz +MgovTGVuZ3RoIDEwNjkwICAgICAKL0ZpbHRlciAvRmxhdGVEZWNvZGUKPj4K +c3RyZWFtCnja7ZZlVJvftu6B4sW9aKA4FHd3dytaNDgECW7F3V2LO8WhUNyt +SItbcdeiLRBuuvc5//bs+/HeT3fcJCPjfeaaa87f+6z1roSGUk3zjbgFyAwo +A3IEv2FnYRcASCprsLMB2FnY2CRQaWgkXYCmYBuQo5QpGCgAYOfn5wDIAM2g +F9CPADeXADcHKg1AEuTk5WJjZQ0G0Esy/E7iBYg7AF1szE0dAcqmYGugA7SG +uak9QBNkbgMEe7EAxO3tARq/Z7gCNICuQBd3oAULKjs7wMLGHAwwA1rZOKKy +/kaSd7QEAXj/HbZwc/rvIXegiysUCkD/L0wGABTSAuRo7wWwAFqisqqAoN2A +UJb/G1j/WVzGzd5exdThd/nfRv1vw6YONvZe/5UAcnByAwNdAMogC6CL43+m +vgX+m00ZaGHj5vCfo/JgU3sbc3FHK3sggO3fIRtXGRtPoIWaDdjcGmBpau8K +/Fcc6GjxnxBQ5/6FwCopLi+jJ8P07zX915iaqY0jWMvL6Z+qv5P/pdn/aKg7 +LjaeAAM2qL3s0ETo+7+vjP6jl7SjOcjCxtEKwMHNAzB1cTH1QoXuHqjiBviw +A2wcLYCeAKAnFJiVxREEhk4BQD3xA1iCXFB/Lyg7B4DV0uZ37N+SB8BqAQLb +A11d/wryAVitXEzdgX8i/ABWU3Oot/9EOLgArOZQI+3tTf+JcXICWKGt7U0d +/oSgac5uIDDQwsz+31vjv0e42ACsTqYuQEd7oOVfUfb/iv5H8u9uIAeHP724 +uAGs1l5O1kDHPyHovThBtxvI4k8IeifeQBfQnwD0RkCOf26DG0oB9vgzzv3b +HpCby58AtCjwf7Bw8wJYHW3+rsH3G84e9IeEBzpJ4o+CTpD8o6AE0v8oXqhl +8n8UtJLKHwXNVP1H8UFJ1f4o6DzNPwpqj9Y/Cnpk/OP5/zCX/7eLNi7mbg6W +9tBd8k8YyvfHWH4og9kfBWUw/7MN2KAQFn9J6Gr9tUnYfpv3l4QyWv0lod2t +/5LQBfxry7FBLbP9S0Ip7P+SUIw/m4od+myxOv4loRigvyQUw+kvCcVw/ktC +MVz+klAM178kFAP8l4Ra4/aXhFK5/5EcUAzPvyS0r/df8ncpG3uLfxv0vx8Y +EhIgT583HNzsAOgX229v+QH8PPx+/yPT3M0F+jCA/3UeQ8+d/9aWNtBTCgj0 +BJqjLs2DzAVDbNNbwir8pYumKxEYYSWsWhNUGnu+db4MXkyEtS8dU3RmXG/Q +/VWVhYuxh7BH4fFI4hrV4av+ReY80DkhYw6y526yl+XdRqL7I0vZa9eJ6i74 +GPNzy+z1CTes6tf18YoUveLB3Iuh4wI1eimtfaRVSpheA/em3uwQHl5dmSx7 +7fDQBlpOSg2sDOeKCK7wNQ+slCT4talgf9tw5E9MK5egDjecX0XI+ckQwzv8 +eGzzDgpOjS1GPI190ZPy4nAszPrngZFasWyAlaYLYA9hGVljTD44DzesNteb +WNp45oJwUjpC2f2cua1Dl/KJhsdovXTHmJPJ2LpYYbGE7SKpCFQdS/cT2Rty +BEi75y/sUEwOoN54f+6LmQwuiNUxZNBHoERvs31NqD+YlT2N582OcZ2jTSzu +j0rlJJry7OMmlmUk7lfqimqzjfXLVoLh0V/V7CXmwJCQ2mEeYV4zuZLigAah +Cyt5nNjlpkScF0vthqG+2rcYDWzlx6/KWnC+3TQ4a9ggePN1MY2yGs0W8UL/ +wJ3AFM+QSW5LEnl80YI8VMYwNB9T7TBnNuG9j4jlGCrSGISI7u57n5sYs6ir +O0Tqxny8BSHlqqf8Ew8OWgYNHQN57wjSLZCqclO07WcvkKnP32Zbw7SsCtSG +vBQdCqJ34YkTlACvIY7x1Maby/SSSA67TFCzClIyKy7AxjoXlCllpZzCJJc8 +AN9eb7hhydYuADJOimA/fbTGxszgTdsNvETEk1f/buAGz1HI9lTU7KbP17yf +zljV+xoxnzjz8Z4o1/nTynWqWvtRzmWbb/fwRJp83ERyNDEhVosT0O/wdane +SvhbPB88VDlEV/r97Z/9fkQRDSEJkrDSaBsd+GdHMDsxX8wjrh4FzxeXBmBg +DYCYrJoOL3Ro659RbRY4hguCHcwN2XrsTiXpXJ0Ydtt12doOosSo+zlsv16p +yjbL8jdF0NRYZt7NEB4pKZxIiXU7VMJkrj9xmHGnGZpbeFEGRf+wORnxZiKN +qbH3bNk1rUNK72IaHuNo0hRzu5UnOdSbueWWEXG2ytMIUJUGeSgy3kOuFocE +WaMzIZiu7VKNU/iluLLkRcMFXzyFRZooFCZ3AW7ZtkpSlluLGHfDYXY1iFsF +8Ji1bzafbJ+Ml/wrW/BSrdPLOjxVMoB1GAdN2YlxESbyl9fJKS+Olj8JKMdw +slBR1saDFOS11EhbSmmjRkFOidTGLxTntSW+y3b4tM9bke/VJoZvZYx7V5XE +iTY3DR9YEvSWsxVX8PYBJ+jLRU7jhdLJHG5KUE0NnEU1OTamEIa1ntwTQSc7 +K/RInEpcm1vi8c8kUgwlFlWhAeSvOX3d9hks9E81mknZP9AFYC5EjszdOO4b +0alSmv340GQV1YIQaSXwMTDu4gd23D7SBmNPPGMZa9Tcyt2ifcTUMSwENxfI +B3gQOcoMsnpQn5I4q/FpHAUK18Nv6b9Lse/kfp8jMH1PbLdy5Xxg6v88RfRR +kfas9hDNaybw3fe4mcP7m4l7Yr0asdlwyCn3W9JSd5duVnvLcP3pX6/oc3nu +cTIL7DoF8S7lk+NMZTUwixD9i4b9kh7hOtAMnoGVsnPZ6xnf75itLNiqskx+ +xKPPaIbC6k4JeR7obivGPK9640SfoEgh1kctRMC07vg0wp1SRPE3fJe5TS/A +HAQMBA5YNnEWQlD0wyewBZNRsNmbZF/qv1Bqh/Ei3016UK7SjKFH+XYYwEIo +uIYqw/F5UWVVVCVvLe34iQEHhkb+pCkkGgR6tWZnI8Rs77H7Gs9l00TBvO6n +HOSOquRgX9Goe9KSinJzM+JtVuZK3Rw7uvYDSrf1z4v7IMt9LvEA97qMDlVb +xmUMDoFevaeiCw3GwoQBcs6C5HI8s0r3ku0+tSCPM/TixDxVeBYVnLz3+lN6 +QosgdcSaZEsFsNZcgK7dar1/PqLmdowF16v96OdPDq/rJvXEgP5JS3HZnJsF +82I/XbSsL62whQHKH2qHrqmOWoFuQL0yf/uiew84wPi+PV0vxNQ5j4w99YZt +7P2eudzbgPeb4V9jhzqFkUaZMKbTwBy8YeTKR2iha0Qnc9nvtSJwcq3cNGZr +MuFHR+b2hkXkggPhcDR0KWTwEDM6LdWVthth7AKpy1920/YTjHxVlXjPPD/U +B//4WYHqTvi27kRNL3ZfR2wNkuEeHuc7XO5z+emMjoTO+RtEuYWsigjfhWDN +67kiaeez8iTvIBNxwbP3HvQnwyFup8XQIuLb14lXd6MLbQI4KvvckgNRNoho +8vfnkpqLiJP7oyp2+Bo90So239f0KAKZJeQhcojsj+0qBGcTWzD9xrbjOU/R +WtuzH8g2Nj+9/VEM42kV+p7mKFyxCCnsTTDySfGBRcmHFs7ml4QZJlTAYTJJ +Ri/8xvuJDTmgmHBs1bTP5ykn32aeX14+L6TVcBaDxIQVRthxv4TRC3i9txqZ +8MusvGWP/L4y9uZSKo31yzM5+cM6Wtxpy/ZYnXtBaU3mbSQx2xMLivYH4j7P +Db3FAO2inMi5JYYlC/Gv3QoFSZFuZzxLtqxayEMinM/2HgUX/q0vBbPkm12l +E2R0wDRpwxzOwbrlC1kFCk9j53C6cbnl350nlI2Zqx7f1bPmt3bWptw3nZyq +hjrnRQrV7ndQSE9ErVyBRNTPr8Z+tldwPO/irH+OkK/Vi+/AsLPvYaEBKp/8 +Quf4+YPYVVbs2P0HvYcEmRK3x1MQAH0wAG5LHigZv5yqYfnjtfijdFP4lAoo +K1Qh0a8hSB3r89pxs9fPD86jaQ2dXIugV7Bp6SvXYRVxDkTATt/WSq6uKiYR +EAb8i5p1Xp4L1BxX/9uudOZek43AEwdfEphA8AKoFPsDEizrqj1FylYoynmc +W2bTsdZdmoYVEk1Ir1h0bTi5CHKp52nW9Cq5XWZ+M4dnq7T3Z7v8M//vIhgk +JK9zOgm600Nojd1Omx+PN0Z4iVqGIwrX9BhotlzC1ism2NgSkeMvSo+DUedl +V4aR+EU5C49ZXBqiqR0JjbGw1rny9XTRC78/PCaKo7iP4u/kX8lNxDP65Oi+ +4ArARPNlxduT+dT+nihHGz2FvB3HYmo8tz7DwOvckiWPVoE6SoZTCk7REjih +HpGuM8M33YH1c44C4cb6SsQufvfQZrKK6PtDLUftPXyo2iyQ5SFQ7Z0NCtGv +3RQRhi51y2OEB3mioUDlGTV5nY/Has+UTXbTF5Y/qgfs8/ySs96XUI2Rl41r +xpW/FYKbaOZiWm4tbonxCh7wK4RNmt7lOqqtoY6OkTOgGCM4X5jEqFWcGJHg +F4IJEheJ+pZzxlvUyvsqDoJtllOBpI1rg+M3cVooqC0y/vFBjTGhiEr0bn7S +srLKdEvr9oRXDNjHRq/5VIxpkEvx3GaI4ZbmWKZHuTqIlpcbZ4Cf5Fj+NFP8 +nCqGIVWRNTHYj+8oiLGqRe2GFrYXWXKi/kL462t427RI47S2WqG000Vy208v +IAuChbg4V3PnZYx+5rx+mFKW/sJBFRJDuoFsNeuQ+DzvRCGDNvfNVtxqUoU+ +eK8EAEbm7Pyrlz8qYN4TPYFPp4n2tJTG86uCt3XHAVHO30U8uMXGyQfbfAuY +1vIlhpNOL9XYtI58Tx683naPnEoiJrq5+NMfZ/f3v+PouG4T4fVuRNfJwkOo +QOa6nViSjQp3TatbUmTS2qsYRSr2Ee8PqgiF7bks9jyvkG4fRc4VoF2qmIgb +9Y+KHTebu40V7yqx8bVlVkCpob3FwCduojD6kaUKs1+mlGhP9fApLw3GLZhp +bnicd1XavxMieRKdrFnFkzOyq/81eUatovNBn9MitZzZJ9xS8unnNsamC9Vt +TydOuvIv6slLqUN5Mb6ONS2W2JBBiKN8SWTRSy5U6rtOru/P/QnXOc/wzgUj +QY/DdOLerT8ON2mbvFJ5vrxPF/4p5Y0lQY78mBEqH9oh1PrJjfNze0c7aACO +3eJu1/OaA+eDxrpfgGqN7rY3AFvinmm6SNzgPn+KnA7zPp5xEh4WHOm1cOKB +KOrwknJ01xjO9ULvegz2/cXLTBr9lbW+aKfPiJrcvrA6qAwe1Y+wt86eG9Tf +TyY/W576IIe8iZZq0ddxypk0kZ3apSpkCoX0gU7yJlcsUuBFQdWDLBNrIqi8 +STwGc7x5cJY+o88iQsqqeBHVVdbLoppT0+YXu24Noelwu2sz2AbyvfiZVw31 +54GYtcltGWLFaSkD8cGkJj7f4KvoG19E0G2MrD9a627AqNL36mc4Ena7Gr9b +4nDkNGcxC8GNrX4g0fSTW19SGcwb9enaQkD+lhVeGex54lNHhMcbyh9uEePW +lf09cT2NDamBh+OAkuxlq0zgJRfJazhEksE15lJgF4wqTtqsSS7ley/QUBRX +xkWNtZ/cR0S3UJaP20ufx6MoJs+052rQSJdV0KIsD59jGzORg4sw5tFyaMM/ +FglB5Oy1rio+eEsLjYgBYPKHf1IZtHZz0pjXhi+4CD4a5lM5fEhxhnX1JvtR +9UMvxeiwNaKdYGrh9EfjSaoUipt5RbFRlxs/Bf54YL85GyoLKw8zcOFttW0+ +VVeL6A8C8qmMm88Twqsiq8KhvSg51As2ToNRrKSz9OmoIfhhh15qXY+VQbQq +CqP1UnXxP1YxKW8qdQwfjF9bzFIQ2nroWxnHFSCCdhlKwSerrr1cCT+SFwS2 +5VqX6R7OTssaKRT0V8qkkZKI3bKGl3qrO2fNCO3BhoYtXb3EIdwcSD8xUHHW +T2jz+l8M1AyS6JHtXB4WSgS+DxwLub8+5T5A8OJ1J7oqF335qEKJDYuKvQaZ +Ya8YVDtmlyUywZQJZn30EfWsImp+m6h6GP2RBhKGQtDJpI9mVSuTg1+NV565 +NwA0GIgdp2pNx6p+Ke8wExmyRYwEOF/kBAa2SXl5UymB9SiZo7o96hOqJjdQ +TKGOX2Saw9f9yN1M4SzOGz8lsUUNu3kdQt7G3KiSahBvxlcYpcPrJUr3yZ3t +9lrtdAbZ7Jybc3ZRDoMu/56dofTVGmUJYJs3CnW1pbylkP/iel2vbiuJ8DZu +r5lJ2yglNPelrmNZW2hzRACWZkBmEUvkcPHGT2LQ5hUO9V19QeZN9gA9jqWP +a8cMpPt7GYyuM1WcuXI/TTORZYc0LZw8TsvN4NfXoZTXmDeVH1AKwQlLIfXp +yjTJvCCfzHRXQewNhQg74DTxnDZ28re4D1TsJ7ahUl/9D0WPldj4Ssc/Ch++ +8QYez+3o4k3OmukMBUusDj4zDzlXjf4cdQjntq7Tac0aCInNbLlKoFH/tFV0 +MB2aLZh7tmVOuAEzWjb3mlZskQbhM6tk4Vi4kz4MuE89bJW5f7cfEhjcf7dn +iQSpGGq2CLrEdzpo217Gxld+9wb2cir4bqIRj+vmEncrcTKWjIxZX1LTfbYA +wauYatkwGRU/EVKyeWF7I62+Z4/2bqj7fBWdFl15bz3pcFPEUhASIBTK451S +8HkzsEJW3VYExsjfUjz2nFRw7RRMIZJoCN7zflc8TYAZO9A7WFNpwz4ZpFK/ +36MaR54KcrNhLGahmYRtemMPlGnONwwr5rK5EckqoKhbsi18wz15E2Lf+NF2 +kFjOtLfDJB6WtCFugeIbb78de9crgGPxmLHPoKY3gYEffzgGLCLvwK7dOhWB +6KT7QKrmY0BH0MCw8kcJwNkBP0PTHq0LxwuIrEnGgiLq5go3teaw+FalSFxI +RMdqflE312uDLIESsq4sp+ZTl063qdN2bhKlowNEBbBI5s0tVmOO2rGHYVHX +lCQE3vsxHEfk65tRM0nst6u4LR0W/XwKL+grhUvowjRa04PcLm77FN21K5F3 +emPc2Z7ivgFEUO5kzK1K9NOpLmDed6HXDKEB0YhsTQhKpPtqfqrVyj3mLoZi +XKpNuYZX4j3zDozI4MsP+aZrCMJ2Oex6bte8jD5alZDGrSPo0zbM8tfVOuyp +tr3BI1V7APd/msdPVK12hZ9fcxw+vzPiOq3FyBIOKC9PNqhzWEbA66yhjEsc +NUUn/baNg0GrtSsmVQn/6q37WESwTXEakc+pqKQDdRy1vm/fxX12n3eyy+EK +EhxQTN5309VKqLTVv4u+XpcKO+Cbg68vvLJub59pfbakglSy6YDji9wt7wmg +K35WaL2d4a/LOckPvcUiUjdKp5AabIOyurtjjHZJk0D5CGXfqoAR31bkMX/9 +CF7fl3wFRtWdy0in9w03Du0ET6IzS1/Ou5DRNI4rv0l057rcW4YNosD1EM0p +sKZn6ricw3ArPDzB+yat39ZTkbOaPNSfcNY5PSGHgMLegTcC0dutdk0AMvWy +T+hDXF/ln8sXByxAQLMltSa5hN3kCHvhXjRX3c319y9pg3F0XVJpGd66V++c +fB5ivl8kZli20PSfvXqPvviZS3VP75X6GEFFvv0kOm5UyByFHNmli2RbVt12 +EeNMX+ZcLNpHEogFLKdYfvvg16pXw6fSOX2m2Ps4Jc7X8Vlrk6q6J2JV245G +xKIOX849jNfqb+B/cXFtELWeW+GwJW6dhrYv66IdDB+NvjFvMWe/GXFukNXk +s6ffn6VkccgffkGRqBmypsuRhFZc4BhdobijLRHuVUrB6KuOOMlj5b8D7Ium +wy+HjWFtHjOC/j9jxdff6aRFWJzZu3APPsdFMm2ybdyusSNzZ6kRHOnz23x3 +UZNjNcvvTcxt/mBHk9xLeUdBfMPEItnjrRHA++adWwp2kaZxujGbC1/tWMJu +JAL81k4cAYEAT8FY0Vb/JzBtz4bfRGGTTg+CTdXZTKPk+wAHFLiVdoEnkZfu +K1jI2Dvm3LHUM/7Kd3KfRsxpT78T7gOnOoT1L5Ur1wfJWcxrzGORyHaDg7LX +HN27Tb/AsjFcWqQ3ZjamUqZW0YSXYehEqBQOq7xRB/JXoiExvekuDtNYw49D +FhtS8DlWq5feEYdktf7gUyZnXmtg8KTXFR427M9+QFcVv0YGXBy3CvNF1y1e +SbzLpTyDezuGNOXbRlj0guSo3Kgs+sAYBY2rcCN2/kmI6aWl4p1Zc6RyaqS4 +hX50ReuZcF40u+Et6c+D9TK6SeIv+wn8ODYsjGT8HU2qQ+Oav6AwlY3eQ5PW +QIdAJiLZ4DZUR3Avy4VkIosjZv3iYR2MWU3GUq1zsRPPq/zoDK8CQgpRlZTY +q/gc82p33Q11/Ee+Ut6pJ67e19ifVJx7QzzSZHuuIS2+VefvKvPR8zcf/TB7 +8+F09EeOafjR5AfpycnWuWB37LPwSNkevMDM31XK0mZbso44HLMbcIFqDcfU +zHejOPT5ynR2ZNGSOc4TtOqtmCu8hEGN1G8aCHrU2FHo35pRQvLWW2AWL+6G +e4rVPRj7nfxUU/AJXYx7Wr4VdiR52HYpCm4xahmhkBEjrMrZIjwUYaZADvMJ +qCtCxunQsR4TwUubCZWaXwni05RMTg7Te6TC8lxkQN6cXipG7uMIVD5B4Ov6 +GRx7frpPkRToD+KLAjiaMmayM5f260zjg/0X15doCOx9VsewPxt7CV4aoT1w +30Vz6a2gJwajTCN0CA5QDjAHnpeURcGfL3Q8+BasngEhtTNJBpGuwM7Q+bNx +6rMFmavboVcmzWJ1Wg9ub6j6SuRUS2QxW2GIzQkcinxDKNQa9uPX6U7UHRgB +p0VIH5LjJqRQ1KOzk3bxZ1n3RVqYTM5YELAGRw2DfBxl5zji4OF4dGgFzlSl +f0nMiauS5HGsHSajzegYmCiMyboMViOHOm/qjrmUBAwYn/qrcaG0mIDP69CQ +RLPZG+uYG++McUtyM7Z9V9gmvZQ7ItxFmZ4BWiXc1FT3OrwCL8ikgHfte7AP +mcNhtB/YIPOKTuO62prlkU6+p3f3VXFDLa4VXO+xWohpKh8rP6Y1LWeGirAE +87cTFD02czN9+VCJwDl8xQBuFF4p4PgsaEBCZuWQxzcYqgGzRkQ7yHusRMLJ +fOZhR7XMZq1oYJdBgeVKyIvTpd7QWINSFb9p7Cf8SYYFLuaXqHS/sJF6+0q9 +GgnbfS5MY/V7mZqpoIClsLSyJZQXq0ta+fiiePG2Fm1CLkjV6wmjQV720bGi +pPgHLlLzyoGELS+jleXHPBXgcpyHVfVr1ifuIzFkQsj7MRqDhhACoxe/q1Jw ++FWzivIJLqpxFdZ+kzN3bsi0IdrS944pFR3eB1Ij48LMpxU7lnKPrvwYvtk3 +7Y8DqWIkhUtxRyTXkduSvtK6jxk588K7BlWyUT0EJ99cT/80GvoCRrIaCXsY +bPYPLzIR4XIz9b2Ljx4ORgGPa6aU27J0whMw8Awpe3eYl6i431aUxDRqacRL +Svz85Bi5UQOrSEaFJCNkeHee7MxIlsAGKUe3IDsZhB1B8Y3t2k3yx3oON4/i +5OkFuX7dvauN2FczlQJvLh+EnesNsghcVrkoSxvKFB6pfgu0ZPYdKtkq3viK +1tG+GtymxVfy5suSSdNBBWku1VYy6JKJ0pHh0JRgjJX00uwLi3T73kdDcQ13 +8XFy8ss71CQgIaMTo2p52O5oJ13hPBfpcD9kYn4/gEJSDv9Ny20/p+5i3M5Z +Y9HgtlWR/q/FLzl9geaWwMt20SZ+cvdQMVV/UgGm/AFU9wrkgpAd6z0MBVzS +1BKihLHRzqThyh73A45U6laRtbqfqRMc+rNFMQKzfBcPC0uvLrzjmhVe0OWS +imoahbc+38myxqhec8nBigmLCBuv1978GmPeV9i4SXAPsCPdXuaKB7NXJ9sw +HI/kSe9SMo1jcwx8h3XE3Ve4MQprXmBFlv1qLKZp7VSnu//tk5OwqU7VUekx +atGsfmECamDr11dM1iMxFu1E+I7U9u1rjFdKuOYjLIw4BxpjO0hWRAxXyuyS +RzwK2RsMQJmI2puoXEsna8Fh5TrPPOFjAnTLxI14wVxWyfaqWRS5a0zcDuGk +Po2iMjQ6W9Yj9kMVMQb0qex9jmSffOuaczsLiuZ2YeCBAuRCJ5i8Scm7tJnS +FcH6l5pkT3r3h5zesDCmsR4M+JcqkD4xVIfsIw1MMT0O6w3n1mBnuz7FJ7mU +L9xSHfhfgK6d4RCKstP9wna2i9R7x6PnguH31xEXF7wfDFQRZ4lL72dbw/0q +xHfQLxeRzWXjp9yHpYNZLlqpEAHDFbN2tXKdLnt+cVVpzQClFOEFj2YDJzXA +ZfNyf4veReAO2YtFRZD5dyw0RJq328GTXWlGwxkxwsCGLDfLYOAOxLqN6p4y +nExfAJlYhhyRUrWfTD1M+3AnYxJlFd2nvj320uiLHpVhqrUrCpi9O5ZLUOmb +DK96UvCPDWBZxuBiNRYJ9RN1+0GwQ3PpCv20sTzpVZEki0VkwjxXe4qWx1BP +DvLWCtcW4EOtgxZcCX93djeH71hFHuFu4tsf+wzJRMlP79dxjY3SERZKbZRv +k8JpSV22rtZXWX2wnX26vZyj23LFi5YF1RWMRTP6jPKDKV/EiUxdfDFm/bqz +8RSxdQums7rCzRr9lN4dpmPPGIygBnYkKJbWMqgl0IGYEh3OkbThkIP30c4C +4yGcutRSY8GIWypVmHmNce59lUQPr4zFHuisXr3IvH1RmIbzYnR9l+jHtbtL +O3FYSjeb+yt3XSvHz6zi2pHHk6dpVCQUPLfsT18AcSBNBVJC6Y6qfKmBSRVe +s0aXV8/Z2DEnbJ+QQIDtk1gdv4Q2xi0SRlvKhp2nOFL6b7mMX7Rs0HlpuvxN +u5yRctzw6iRyfV7yXPO6tiMwyWKUY2y9uJC7RUj3nIvrTI03Gpp2Atcu4hTC +EsHV/wSPkn+FobKO8eoLmPiAfzbaSRASIH9kBMM3HmnwGm3W78bv2e7O5/sa +Nv476zFFLwVJXPyrdyas28s0S2uJP7uwSrvWrMg0Z27eNNVvLLrlNUSA9/0q +iu1sfXHj9fJcHCKtj1q4FEl37mUKSE61vy8gky2sYKbEIzunYyWSqNBx7u+C +eOC79uL2584iOBdfpVxV12pdMlwNgeu9HQdTLQ+E2TUjiHpU2fX3mnsZdm9w +OzNL9G+W9gxzkJbGuKuWZ8Z/divyRPM1TnjaGUfuLEjKHOFUsuLkp9N+rkft +c3yiWdZECgjzpyq4Tk907XGwv3jOwSkf/s61LGP1VubxY8iXM6JIfXpqcXqS +IoUjieuXwWAl/pKOqaXwtdv+HJ/nN3l3kjvPr12ZEUx1kBq6we9zh1v4z6Pg +KBYNOjDcbpG5MsXl4cSOYZpur3RbESdU9qx8dTYEv+FfYHk6ddwWhle9mKtv +5yhoEZAw6hSzMcT5lCV3JbLQlnQ3HVGRDmPx7l6xDRUoLOSlqfI2peU0H1tT +3i6AgmESrvSuPuGVDd1AFZM79fLiiT2GkgyJWzkNmG+BCyHMokC4hmWhWist +/957/oivpDC0lo6udMTVBknI9Ha4Su3y7YlGnORrLlkMb7llo+935NnGSlLr +i9p0GPGEh/jnGwwfsmlTbyGjj3fWEtmLH96iTvF5j4mx0SW3BVE4i5/mQnxb +Y97Ns88IbKrQUeC7qtB87AvrPfapewXzJWSwgOD6XIRCxGoJ/h2sM3ep5phz +UL+oHDN9ytz7upnQj3iHTDrVZmpSesEeQYj4MieGwjtV54kQsExTq3ksnhl7 +9NiEnyltFqcMq26EeqNworfp9rprVrDP8izw8MqX7Y6PaGP9kBrSkeCcTi4a +8EXIcEYlbAVX9tErrLvY7GrPRKGeGpsATfdwevSBGyL1K9rhJk1YpboAQtS2 +DxnCJRZMx0n8tVqa5CfsdyGxjmBT6K3tP0ZcRJthaJ8N7+z0ZoG+KuHUk68P +TY3UvCfmQOFXBT9TyvXXeg9a/5jqfK6JXHRlsIpVKgV2Tj8jp2FYf74fJ7qP +5ZQ1v1ToLIb48/UQbzeCw4myFo15mEet1kttz8EWkYnLjMmm6fSRHNy7ahg4 +Av/Y3uW6bxbf7Aw8832FcN4gi3y2WY4EB2+VD0vvUw6oL6VDkN5dClnLK3Xc +N3FIfARoIlcR2xjNd27yyhW6uInjnTHBohddj5zEraF01UzM+aXYrAyfkY/X +NiT69bJ/KbJMm7MkegoIugzMMKI99kNp7easUHst7ihFcDAPEzrxI84dBf0S +glZjSqeswqO1u+cnDcEZnXjewLBs9FJyEGDxLcta//UhFS0fng+rZG+vcfjQ +CcGcpUPoq2KmuCv2F4DhJzLRrybrD5WvBQlrC9UcQYSt6nFqCy1X89Q7eSpT +undFBzJkIgIFFwakpg8acyAWnjc/4qkx/UGPKzBHFkLIeT2ZH3FSPFWpMHp3 +i3OrU6SMM3R4Y+0fpvMN8sW8xeLJS/YW4+sMV2TxhDgSJMRF1YFZ34a5Bw42 +3/n/ehNHxUO5825xT5lFzIWgnW1QRFPGG5n45SRvrMg5bA9zevRiwotyjQ0a +GrGAqs2rvJxXGJf3wgwa9DGnTZ5Om+H0ip6EDh6c1jyiCtu4W524Oza7eVFq +y6YyEq0niZFTRQa1mhpPLv1fgi9iNJ7pgwuY7zOitztRFd5ZTCe+XQ+4R6Xb +zl8b0A6pTLz7uKo/wlmJwMctL/mOGbV2FAZex7BgxAmjYQ44v1srX94mQI+n +2M4l+vljvssUCC0j/ueba3WF/gtM4710euy3ryF6WXCP6a4xaLirZZ+pa6Nl +XlYEa3js24YEK0dK+gVOfE3d55pu284cjN/nF3nlCBOP8sNQnsFk9Zc7IyVh +ndBGi8NCnl6Sg2piOWoxABAhFBxIBTcW71RIxIWsaeiiovs5AU0S5kFdPl+d +OLXXyfShL+hTPND0c2SvUzkcYHemBC83Sj1QsK8FtiD92RKmzK4rungxMm81 +AaGT2cCjY34BkOJEIas47gcQwN0VIgstZWGJdUTBQvdezpb/VF7jNt/tNphO +uCJrmbqU7+/p546mvZj1aju7WItYPamDMpOxXrHQ+WgY/SNp16cXzaKfYRcH +NrTJthglNixyhEcOlG8dxQo8prD84/XNtZRwgp+HLn1qJHeSnzYl3grMVoKH +Xj+uV8KtE5n34+Ovlzko+Q4N4FiK9BglDBHx2Ocy4sZtHGdmKupQFvf6TcpV +zFwDv6R2sOUYHQUC+ZKf1S8dwy/eI5uBZrFa0JfWj8ScdOk+48E01oZHCxYc +eLmeMkaRvMsfwEsU4gyreEWQGvaOintzQk2CdIZu3buotkki/GTJq+9y+ypN +HkPsDPdAH1N9ITh8IVU6s8gB3bF9froif5RBbuBIceJWIgAUVfLTK8gEEMOW +kTlR+TJGe4UDkkyLpeFQt43T/vHOXoUi+6fgpluiKC/yg2EKptHDvp97OpyV +ILQlodgQjYJfkD0i2y6KWN8Dc8nXIIK340qZSsvNl45LibZ8T+wHJMXXYgpy +gteZostKdKyRZk0z0aK+D5X2BVcaPQ8ffH7Bo02iRvJukm+VHry2mB2dSZAc +Wew/sTvX0OeuAqhpzj6Efqc4N8+r/VKoWkymfe7jua5VgTP/BSKGZDB7nm58 +KEbbcNaaRyjEhCWCeF384SAKUTEDXoat+rJZxnoQVqsXRKl9OGPkncFwswaw +UZGRMKkq9OCApNirn/r0BKWM/BRokcEO4DdzX53C1e63dunQ9S639tF+5Qns +ixPoeUlSqxiK6ODOliGkeYE1XevzsUlA6fqBo8jeiGYauJJgfBsgu5c43mD8 +wD0vbprbYi9xdF3dKtTB2Zdsk820NV5OXvONYF5zIe9dGcf+TABQMpcvkHEL +kyXbbp0xhs9sWg7pzqzJ465tYqye7HsEtdN+M7gwJYPtw+HJLptZgbYIsX5R +D0Bnk7h1tIMbCUtk4+ydTSd1A7tugc2maPT0phrXtHDw6wGicxPRstDW4jUL +T36dt5bSQLISVV16ExvCDKZZsrfoBsVZ5KwiM3LWDnz56D2fwXhTWN9h5u9R +wyObtm2zyXnszFtsqw/jZEQ26A+RgQTnOCfJFReLzt1xFMbfz164xPlE7RpG +rfbvHXzr1/4ohhNRibu/w/E6I0zox7d+40II73TchyhBjcyZePmjyDmYiCwM +A46JLuf0p7Zlm/Nfr2xivkuk0o/0kMyVdbb4n0QRaqw8ixKlz87NSFXIluod +LJklsf0fvlD/f4H/JwqY2wNNXcAgB1MXO9T/BZZAZIllbmRzdHJlYW0KZW5k +b2JqCjEyIDAgb2JqIDw8Ci9UeXBlIC9Gb250Ci9TdWJ0eXBlIC9UeXBlMQov +RW5jb2RpbmcgMTkgMCBSCi9GaXJzdENoYXIgMTIKL0xhc3RDaGFyIDEyNgov +V2lkdGhzIDIwIDAgUgovQmFzZUZvbnQgL0NBSUZZRitDTVIxMAovRm9udERl +c2NyaXB0b3IgMTAgMCBSCj4+IGVuZG9iagoxMCAwIG9iaiA8PAovQXNjZW50 +IDY5NAovQ2FwSGVpZ2h0IDY4MwovRGVzY2VudCAtMTk0Ci9Gb250TmFtZSAv +Q0FJRllGK0NNUjEwCi9JdGFsaWNBbmdsZSAwCi9TdGVtViA2OQovWEhlaWdo +dCA0MzEKL0ZvbnRCQm94IFstMjUxIC0yNTAgMTAwOSA5NjldCi9GbGFncyA0 +Ci9DaGFyU2V0ICgvZmkvZG90bGVzc2kvZ3JhdmUvYWN1dGUvY2VkaWxsYS9l +eGNsYW0vcXVvdGVkYmxyaWdodC9wYXJlbmxlZnQvcGFyZW5yaWdodC9jb21t +YS9oeXBoZW4vcGVyaW9kL3plcm8vb25lL3R3by9mb3VyL2VpZ2h0L25pbmUv +Y29sb24vQi9DL0UvSS9OL08vUC9TL1QvcXVvdGVkYmxsZWZ0L2NpcmN1bWZs +ZXgvYS9iL2MvZC9lL2YvZy9oL2kvai9sL20vbi9vL3AvcS9yL3MvdC91L3Yv +eC96L3RpbGRlKQovRm9udEZpbGUgMTEgMCBSCj4+IGVuZG9iagoyMCAwIG9i +agpbNTU2IDAgMCAwIDI3OCAwIDUwMCA1MDAgMCAwIDAgMCA0NDQgMCAwIDAg +MCAwIDAgMCAwIDI3OCA1MDAgMCAwIDAgMCAwIDM4OSAzODkgMCAwIDI3OCAz +MzMgMjc4IDAgNTAwIDUwMCA1MDAgMCA1MDAgMCAwIDAgNTAwIDUwMCAyNzgg +MCAwIDAgMCAwIDAgMCA3MDggNzIyIDAgNjgxIDAgMCAwIDM2MSAwIDAgMCAw +IDc1MCA3NzggNjgxIDAgMCA1NTYgNzIyIDAgMCAwIDAgMCAwIDAgNTAwIDAg +NTAwIDAgMCA1MDAgNTU2IDQ0NCA1NTYgNDQ0IDMwNiA1MDAgNTU2IDI3OCAz +MDYgMCAyNzggODMzIDU1NiA1MDAgNTU2IDUyOCAzOTIgMzk0IDM4OSA1NTYg +NTI4IDAgNTI4IDAgNDQ0IDAgMCAwIDUwMCBdCmVuZG9iagoxOSAwIG9iaiA8 +PAovVHlwZSAvRW5jb2RpbmcKL0RpZmZlcmVuY2VzIFsgMCAvLm5vdGRlZiAx +Mi9maSAxMy8ubm90ZGVmIDE2L2RvdGxlc3NpIDE3Ly5ub3RkZWYgMTgvZ3Jh +dmUvYWN1dGUgMjAvLm5vdGRlZiAyNC9jZWRpbGxhIDI1Ly5ub3RkZWYgMzMv +ZXhjbGFtL3F1b3RlZGJscmlnaHQgMzUvLm5vdGRlZiA0MC9wYXJlbmxlZnQv +cGFyZW5yaWdodCA0Mi8ubm90ZGVmIDQ0L2NvbW1hL2h5cGhlbi9wZXJpb2Qg +NDcvLm5vdGRlZiA0OC96ZXJvL29uZS90d28gNTEvLm5vdGRlZiA1Mi9mb3Vy +IDUzLy5ub3RkZWYgNTYvZWlnaHQvbmluZS9jb2xvbiA1OS8ubm90ZGVmIDY2 +L0IvQyA2OC8ubm90ZGVmIDY5L0UgNzAvLm5vdGRlZiA3My9JIDc0Ly5ub3Rk +ZWYgNzgvTi9PL1AgODEvLm5vdGRlZiA4My9TL1QgODUvLm5vdGRlZiA5Mi9x +dW90ZWRibGxlZnQgOTMvLm5vdGRlZiA5NC9jaXJjdW1mbGV4IDk1Ly5ub3Rk +ZWYgOTcvYS9iL2MvZC9lL2YvZy9oL2kvaiAxMDcvLm5vdGRlZiAxMDgvbC9t +L24vby9wL3Evci9zL3QvdS92IDExOS8ubm90ZGVmIDEyMC94IDEyMS8ubm90 +ZGVmIDEyMi96IDEyMy8ubm90ZGVmIDEyNi90aWxkZSAxMjcvLm5vdGRlZl0K +Pj4gZW5kb2JqCjggMCBvYmogPDwKL0xlbmd0aDEgMTE2NwovTGVuZ3RoMiA1 +MDgxCi9MZW5ndGgzIDUzMgovTGVuZ3RoIDU4MzEgICAgICAKL0ZpbHRlciAv +RmxhdGVEZWNvZGUKPj4Kc3RyZWFtCnja7ZNXXJPrssbpRBQE6T006b1Lk947 +ilKEAAmEFgihhKIUQUGk994hgHRBOoj0LqgUCb13AVHqyVpr76Vn7ctzrs7v +5MtF/s/MO/N88044WAyM+RXtYDZgNZgrgl9YQPgeUFnXxERYCCgsICSkRMTB +oQwHgxBQmKsKCAG+BxSWlhYBKrrBgSISQGGhe2IimC8RB1AZ5oaEQ+0dEEAu +Ze4/kiSBii5gONQW5ArUBSEcwC6YGrYgZ6AxzBYKRiAFgIrOzkCjP054AI3A +HmC4F9hOgEhYGGgHtUUAbcD2UFciwT88abpCYEDJv2Q7T7d/h7zAcA+MKSDX +nza5gRiTdjBXZyTQDgwhEtSDYbqBMV7+N2z9s7iap7OzHsjlj/J/Tuo/4iAX +qDPyXxkwFzdPBBgO1IXZgeGu/0w1Bf9lThdsB/V0+WdUEwFyhtoquto7g4FC +f0lQDzWoD9jOAIqwdQAi4J7gP2Wwq90/PWAm96cDQWUlZRUVE95/XeqfQQMQ +1BVhgnT7u+of2X+y8C/GjAcO9QGaC2HmK4xJxDz//mX5j2aqrrYwO6irPVBE +XAIIgsNBSCLM+mBIHOgnDIS62oF9gGAfjGFBAVcYAnMEiJlJABACgxP9caNi +EkBBN8ylwOz+0P+SpICCvmA47JcgDRSEuYL/ZnEhoCDC+1dcXBjDDnDwbxmi +QEEI1Os3QRwo6AH2Arv+UjBdbGHOsF+KBCZH8W+SxJTQ/JukMS1s4CBbJzDC +GQxB/NJF/9b/WrW/A5JAQdAvwryB7d8kLITpBP0NMTNw/A0xR51+IebiBF1/ +Q4wT2G8ogpnfb4jx4/4bigEF4b/hH1P4DTF9Eb8hpq/nb4gZkNcvFMGUsgH9 +Vew/101JCebjxy8G5BcRFceMThgoJSQU8N/SbD3hcLAr4s+/MmZl/80QKGa/ +wWAfsC3R9GeYrcxzx+T6MNRT1fyxUnwebCX7hhi92o6J1pshU7HYzkUD2u48 +6JpHZ2Vp5CRr+GvM3hf0HhEt/obDavtB7jEpn67WvKzX0nwb6R99S9NFrrqx +noZs326unzzeEcfW/4geRCU8LujOPOjZzjXgUjFZJ/zKgtVp7lXXmf5cQvKR +WprzgxehNXdFWYxIU9xRL8VezHmTJsThzY2GPHV8AXjHO3sIa/G8c5YPyIm/ +ssL6aUvwKlhEKWuqYdRR7kUaP63UnIWK/c+5SEs6IFZtUbsgh016RWdqxavJ +Jtfp5tOZ9rFF46bqTiTW5MXSDRueYdr1Xh0uwjFpD9NdwjI1YiO87XuqDeW6 +pE4euG9CNEKFRIpVj6kTFNL1d8G8IWYFyZwldWS+14zaIyFMb0nrQ6mTxtqg +wQ0Q4KDswnu+8jnV+G8qnXo7JGb+Wh/Y4n4wYLcomV7dqRQ9bt+KBVyTjSZT +6H7eccv70LlyxJW7zbEiznHORNXxlGtIPPM7s5JTgOKW463nc7acxomFuKWb +gMU+fqnscR6WDWgqMusZOypBXSCXpML7hv2NNmKy0o9aQtOulIWMcKJzGdKP +C+WvO3OB2hvwJ1hfllGwVJ8WWkk3sWk5wC3l2FVkl/7PCzbkIFk2k3kbim7p +tpisHbCNiXfM1gnvYujmHvH7Ty6QA5cadilVLtbBrQP5za0S6WhO145pnmeN +Pp0++LOCWgHnhbDPlWFu2xL62OjogfNKcIBDV47wnVhTiZGy0leFHeUcXCFQ +S83WcOay/Q1oGtHybmhdxCAraxaljWhqv9z6tLiH1syML4VNJ9mk1if5fHPT +1bG3Fzc1aIArIqyzURefJkgofzYJ6ZcgpQUWWjoWi5gQtbkX9+SocWi+sKsG +9pYS91jSIpgLr2CR7dYcREOcqtrtgOQB7ZiMkEIIPPGF0a72E+RimLWXPuWT +sIOss2yv0G8nOE/7zLyNXtSSAKFoPV3TO+tjohp0xnluvMUmfO4ELB64MUKj +XFONPTIPklB1vKLr06wJWlLuoiETdhFah9b5VX1HkukFkrxL61uapU2eFXvd +c4tT7Q4asnIsnHcCyxoZTYaCkgJFBMrgixxEXjf7vl4jo3naPxwZx8elWOjU +sldhwbmtOq2DXlWJW33Vv7OcnqJxVxXfePmj+4Hc6/fjPHEFE0CxS6oZ8nde +U5GRNzyeq019WWHILUnOTifcEZVcv9W8nO/NZo7Xm948CxlhoFMMn6ny0SX0 +KWDXKUvcF7wQnXjFjlRjku3owOPVQIp5PqRbco9UV8KPXqTpWVc1beE8lQ31 +zWmRe8DZl3+1MY72Ujpq1SH0ISNUaJATuyK72Vq6fFViMSSKJ5etrF8hLfUY +Fd1Ru3XvVgVuDq3VvpAho8WLF85honYj2oC0ZFgG5ycqx07Co1IAFWgwdgFv +ZJ2ViP3DcZKoyvscGsR2J/BdMdcOFln9UqbYUzPafALe6uHEknNp1NallYtV +vw/CeCEZf3kDFjykd6Ysqcf1ul+u2JT1YGnyWe/NuntAnNP7DGJBb7mX14IN +jS71viu3ZXUEjBqkHUvm7XwrMgdShBPML7C+f3/gzM6d73bgVuCv0kaXH3OD +WPk4Z4fPYgs/mkFKezvKSoNwjoe9T2FqXT2JBZWhU3DeTyR871QcLU77Oq5i +hyFtjdKJR6k6m+FCF7rZpwxK0qGJKEL2jcFWdONN0ycHW79xOuoj0LpO744U +z/PIsUIokA8SrIiZADQgfDOd+BNK1L4/AuIQDQL6SFlkqbp/gFQyEBcFrOVH +KXVi6X2cSxueeu3gwPgQ2UelSLyo5vJ2qIowCrc9jX5ETzmUu4mGLR4/avg0 +H2xd7XGmgXtTwzTl/g8zZUqOTwemWnXxL+i0uQxt8Mz70Q5OGU/xDB535NE9 +jZDE3XTfS681iKpmlVzcjYM+2V/e6LD6qpGuuGeC9nXy7BTL5ExMjJ8YzQKv +0yo/U1WPJ41inJaf6o581jiN31e5CtCzc4hkxj+SeDp21u0yWNXTCipm5qia +S3qYX1dmm1uU3HV4SZzZWpbkYJ9IYQo2XNKVOvpgTE60b9GarReMD0J4qOLf +qPy++iWSl0t+wfeL7ISU0YOXl5WZ/abxvAXlKqSZdCMxoyXfLGeJcUmsajLl +Hcc/tM+tvUCiW86jzf111KrvxIZtU8IeCK7yfgMgzwQMBVPKnlRSDN2+HVkY +tAPdbyDAqopLcOTra3HaR6vuX7ily58lbrlkEPcU4UjMKCp4CvEF5th8gE/R +iqmLpXxakX4UrJygNrFsNfPo0FeXlWpcJWbX8fiJCgcclGqOc35vgFp20zJz +U//Iqp5ivCwlxKvi7nuZRLzTYFhbKG5FUT7I1rdAmsoxqiBplyjTh1lQDX7W +1revx0de5NDWjbyYeijHEcSekZhBrVhv8k5ZtbGle/5qmWuYKn7n9Sgb+cPM +CYOAUfnt701iF3Zk6DoSLgGGiMiM1bmXsjt56XqA8xffY+X38/zGDzwd/Prj +4yhiKvtXCd7sXyxSmNw9Dsn4iSO0Uz8SUKBqxuecaZRJoo2YVO6Z8s8l3Ii0 +l3FHQe1fleqEjfaQ1uACFiLw7tRBiZlqRZbJOKjIhSj7q03OBc/yaJjWog45 +NX1ohzpzmvSG/LpHfU28KH+o1pyEJbmsHVuGhVcewHfPNUT56UYgqxKou7a6 +t9VyE7T8e0x3noW+55GB3yZlt0kwv6XvXgkBnroXNpKa+Ofi0TMAWXBtqnT4 +N9vIdyzGoofouVZpv8aRFjpkbD9DLzfhRTiPUHtRCEQJAuXU01vbaMYtgoJI +4hD8+3qqe6/jQ+tILNfxPbYC8b/OORNGXdJtaqP9GHLGyHE/+IRE59il3eek +kwHDmrMJKcsIPAQM68xk09X1nX3j3oaoja/GewU/5mOqN4Mn3TWE0crUWcRn +V7ODOQ0e5hUdejxI4fGM3pj8XFLPKtqbYUpEfspmnY76UuJvItm+/ID0dnts +In4OIwuj0VVwO1NylaOif3cK2KhkEjmpuM04EtFf1tA5b/HNPv7dcwKIWIqj +cF67Rm5O1cMiCzVH5rVbMZfc8+4TmjAFRY3oSPUsPq9wShnfAySfQQfH+FLz +3me24Xm2BCYRJzO14JQ47EgLCe5ww5glCc6OQe+O8tMAMONCwPmi21lHecrN +IRdll+7ZNgIzfi6ie6yPXe+1Xvt9Cy8MmEO8f/Wwokh5F43H2HDZiFcXssUc +YkqM9HEzXH0+W9LTlJw8qd1FeVeEfcGvgmDBHHF1vy4qj6RQPRjp19jQNFHm +BSCLOU7NOe5PKT4Mpk4I/dTRL3mI0z7gXrZLhxVJ3bW8gmRA0iE3rIHv5/os +sQQIniqmnPQAkA+97/jbts8MF5mhGHo2rBn2LO12GkIPpjvrJe+y39gHHEsu +EBV86h7t9/sherdRW0I05Ad1qn8JQecM8rut1rvArjcTli1UVhwC39GnQeRL +a3PzwzUNz2gu+yelS6PsbLhRy0odF+ZPjqYE7FU5U/iz2pXumBb5nKA734tf +UOfk+BZe3xwf5GNmkpddJI8ymVtklzDEiy8uKUNLXN0/nTeGkN142tiJKx50 +n1Jj3BO2PX/XYCB9nrS0hRyv9echpTAtbhce4xPFfY6Hoo8s4yBSKj31RbdB +zcy+RR1x3U2w10rmanSjfGrnBrnyl8dJNrde8HSEBH956EddSDOCRtHkKXQH +Hn+dwq7ULgq6Prh9vyuCpDaEPysiwvnHEU+gegAeDjSvtV3YLNmlIaNZLEly +qV+9l+NSNGT2o/4DNYO3wrV85lmPSbk3l2+EBOCfMsweestkuwRCtPuLQTMp +lP7EHTPmGSgA+6it8FN6HC2osEd/ct+op33qJs7hzAdN0bGVHpZoGZv1LDnz +AZQuhI08XW3ssy6UpyG4wG6/bCa4wppYAjA9q26cTYQuQHkQOk/PdyZWZnX1 +sjH4brvtinE8CaId9/a68YDL+NabPn47DQb9tyacD1/V5sT2PrK3rBXX1j27 +Wm1vkvTkKoenMB5xeXaSyBd9Xx/+eeBg/iB4VsPZbrG2dE/M3nZP94WfLR79 +07UkHfouvFe7zx6QJI00SemWtrUdpSkGzMY5GEX9UEkssfeOyrAk2Od2xaLA ++slJeaTN5jxtNgk7sCzYUFKrx1mvw4sytvRvUyexjM+jtTbRwaaJpBon7x+T +85mzphoRDSUPAjj+kKgGJjx+ZKdz6DGgbjSrCG+78GSp8NVJ1WtmucXQPKhD +feyIjTRbIR+RyrEhSFU0Mgt0JaKjXXAzVorlkrnx6ZVCmssB18b3qC1fyNuZ +rzUJiO9z2PSmYekXHKMF4YYppVd6keDMa2zrmOz2Ay4ZOuP63CsRGgFi/drm +4jp9//jx55xJb8AA0y9x30Fie4UUn05BfcUwPaG+zkaqlV2wAgHd5ht0gMgU +RG0vaV/gQ51KEyE1m+vFcqbVT3mXtsioWVvwgCw/B2o+6NG1XqEekifqPHAW +LAoIZU12hmUUIZ80kyQEOl/Vy+IefTcAPY0yz9saftxSQCb5ZloojjaCDyCK +n65YaTWAW/4mxaKvr8u7Uqy3w1dE8TFnY3umRHFC7YxOXzOocJrzMUDrvuMx +lqb0Hd5TBKiWJLZetHDgW6gRuEObqJBK9t1XnnrL0ofWzIIVcg6bnhAzC+GT +jQQwuzZplcTEqgSBBGnDcPMSLsuKTPWMbG5Lr0HATpAglr0jbM74s/nI0s3I +nCYGRDslqvCwCRCiX5d7dl9eZ/tjTa1I7+c3EH4jYOydlGTXV5duF+7EQ8jA +a3xRl+FCm8MrFBvycU4Kvvuw9MX45edoy4PIFZPAt7UNcgY5gu/NNV6HQlW/ +LMe4jh8FTPwQEA1yApd47VUvtjED6PNuU6Vm51jafHZ+fZKy5RWhmQI1erOi +6Lj6oxAX+kGFpZZ8wgRPh8WQvgHS/2UnlCUK6+VYlU+4O82PkEGyHMNQDzqL +x1JeKI3gt3L1MNsP1HnZOb64lj9wXlAUv937XOENSAaC9lZTu5oLwUP36tE5 +G+1MQyjLGGzG2b6lFQO35MQSm5wj8jpdjxHSDyZ+4Tvn5D/IElppymmVCdMm +UVx1Fk8cr17+UPKMuIejeR92WajQvqARt4/Yna96V3rhuTdHW1hjzG5sWcbB +l0U+06jSsgg7nWsLve+WWsyksbiYNdXDLa/aOKLTRc7RSXcxkrdLk0jyU9Xt +UTciWQW9arFd0gtCxD46/8A3E2TFWdFCDl7+WEyYukI+P8pN+elJyYlRdS4B +WehuWSYZOpYLVV2k1IculVQID1Fbq8JLx6YzL7+sOUlowHqPK9YX7MdzYz2T +N9zCfDF7HPfqGbDP4eGMGw6D4Ah9iWCkOEFeenYcnDWfcevQIxzynt0dtoJn +K0ZBIhLsIxn75fLGq/ucYlItXCf9jA3CNxuZndATGlGppfzWZZYRSV3E0xLX +jyx0dvnLO1RoWrCn9uS0LkxoI0hif+Ac5hznPCEwuqtCAAElCOvllsXeBtsD +St5nv9sShtNWa42p29nfJF4Be/Lyplsv1HJElEbc7Xna5dubUnn30Ba/e9b7 +p84x5J1bs3S+XwUFzwmLt/imBn/veO6cPIMarXfRrJOYCvrVZFdCeqcubrKr +zoQX3UBvJ1gybLO5JGmD4Xmb43M8nCvOGBsDz6clY6Tlq6Qs66E/qa83YiDD +gFvXX7XO1fNkGRUZr2MpHjmWr23ZXiOeTUVSsbi8uxN94rxKOgw6EsSLEaPC +NRSRGoqgpeavmF1l6IM4PMNiQE0Qh8/xDh/CoDJkCs+IIfO18arZhTMCoRUb +7W3pEx9PUK+43RXmQRc6iWJXNg9VLpizrlvkD8duxPmNRmwYf6+rFm9p324T +a+xkASxHKlU1KjK+cCMMRmDJD9ClJIr2oSxo2idlsZ7UtbZQanJrg8QePYpa +ZWZnkRzcJB7I50ZLL/UArr2MadF2fIoKoN1ZigplVjgxSWQ5svQmJ3WynmAx +G/qGX5Y4U9xgGGtYd3nlYI3MZOtuXDTF51pW0weI3K9v+lkY58eUz8wZDGux +HrxGJN5iVs2HG+0xXkYWuZbV+1fhUPoCR3hfWnwzynU63GYT6yR6yZJ5mkhl +wUPyfoCRuHT8eUakcLjRGdk9vfYZ7L6CmpgxLx/yNEt5pS9vclWkvs12dwmF +rGZRkAQJail8eak5wCrwzkjzNgkZ3/w2a7vmmu8eNEMpHD0AERwLROD47YY3 +DOvOdRk1K1gzG80qFbAleYKZhuQBd8HN/o8l+Tf6sw4ogqS60KtGLwG0W0Kf +0ghToqrcknofmBJavarf3NQRX6aPSuRluH82shSnUx3xuKnf64J2pS6MlL4I +3CKS3/S5/k3+2zBvUc8dkiYlk44ZM47bduyo/jXbq5c6ZyzNbKEeohOn5/gE +7b5FuxOBH/PWQxQWXuo6tJqBlLJGDxj8qf0n6g541y4znDS7F9Dlj0hP9mZK +PtJ33WrOlL0JljWW1/DMelsc3tDL2n1V1dY7k5WUXki1OW1lZvcdegb2O689 +c2sWLP0484xvEkkDJuiLX/WGnt/iLnslCNyq8XWjrTGwDLKhP5d5qLr6pNWM +hMt8CYesGqumE9uSL7BhvoixUXQDMsEFh9AiFMRdIqFTyJVFWWet44MhBIF3 +tasI9rpDm9XlCYx494aIYSmx7gv0LfeoD+ypP5N2/Oid371RiQp/MnCXsDhF +FfW6rijTjbgLJV5jIzF4UjgVLLmWwfmyShVIkjavs/v1ijmKqwoZFs/Wcdsd +8g5Pl9VBv4w1KPcLPOszvo80WZiK0P/wQ/T/Bf5PFLB1BoPgCJgLCO5E9F/h +LatfZW5kc3RyZWFtCmVuZG9iago5IDAgb2JqIDw8Ci9UeXBlIC9Gb250Ci9T +dWJ0eXBlIC9UeXBlMQovRW5jb2RpbmcgMjEgMCBSCi9GaXJzdENoYXIgNDYK +L0xhc3RDaGFyIDEyNAovV2lkdGhzIDIyIDAgUgovQmFzZUZvbnQgL0NCQ0RE +VCtDTVRUMTAKL0ZvbnREZXNjcmlwdG9yIDcgMCBSCj4+IGVuZG9iago3IDAg +b2JqIDw8Ci9Bc2NlbnQgNjExCi9DYXBIZWlnaHQgNjExCi9EZXNjZW50IC0y +MjIKL0ZvbnROYW1lIC9DQkNERFQrQ01UVDEwCi9JdGFsaWNBbmdsZSAwCi9T +dGVtViA2OQovWEhlaWdodCA0MzEKL0ZvbnRCQm94IFstNCAtMjM1IDczMSA4 +MDBdCi9GbGFncyA0Ci9DaGFyU2V0ICgvcGVyaW9kL3plcm8vb25lL3R3by90 +aHJlZS9maXZlL3NldmVuL2NvbG9uL0EvSS9icmFja2V0bGVmdC9icmFja2V0 +cmlnaHQvYS9jL2kvai9rL24vby9wL3Evci9zL3QvdS92L2JhcikKL0ZvbnRG +aWxlIDggMCBSCj4+IGVuZG9iagoyMiAwIG9iagpbNTI1IDAgNTI1IDUyNSA1 +MjUgNTI1IDAgNTI1IDAgNTI1IDAgMCA1MjUgMCAwIDAgMCAwIDAgNTI1IDAg +MCAwIDAgMCAwIDAgNTI1IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAw +IDAgMCA1MjUgMCA1MjUgMCAwIDAgNTI1IDAgNTI1IDAgMCAwIDAgMCA1MjUg +NTI1IDUyNSAwIDAgNTI1IDUyNSA1MjUgNTI1IDUyNSA1MjUgNTI1IDUyNSA1 +MjUgMCAwIDAgMCAwIDUyNSBdCmVuZG9iagoyMSAwIG9iaiA8PAovVHlwZSAv +RW5jb2RpbmcKL0RpZmZlcmVuY2VzIFsgMCAvLm5vdGRlZiA0Ni9wZXJpb2Qg +NDcvLm5vdGRlZiA0OC96ZXJvL29uZS90d28vdGhyZWUgNTIvLm5vdGRlZiA1 +My9maXZlIDU0Ly5ub3RkZWYgNTUvc2V2ZW4gNTYvLm5vdGRlZiA1OC9jb2xv +biA1OS8ubm90ZGVmIDY1L0EgNjYvLm5vdGRlZiA3My9JIDc0Ly5ub3RkZWYg +OTEvYnJhY2tldGxlZnQgOTIvLm5vdGRlZiA5My9icmFja2V0cmlnaHQgOTQv +Lm5vdGRlZiA5Ny9hIDk4Ly5ub3RkZWYgOTkvYyAxMDAvLm5vdGRlZiAxMDUv +aS9qL2sgMTA4Ly5ub3RkZWYgMTEwL24vby9wL3Evci9zL3QvdS92IDExOS8u +bm90ZGVmIDEyNC9iYXIgMTI1Ly5ub3RkZWZdCj4+IGVuZG9iago1IDAgb2Jq +IDw8Ci9MZW5ndGgxIDExNzEKL0xlbmd0aDIgNTAwMQovTGVuZ3RoMyA1MzIK +L0xlbmd0aCA1NzU2ICAgICAgCi9GaWx0ZXIgL0ZsYXRlRGVjb2RlCj4+CnN0 +cmVhbQp42u2VZzica7fH1WgJEr2EEV0wMxi9RA+il+gxxmAYM4zRe4uSKBEh +SkTvnWgRUUMSQnTRoxNdBFs5k73fdydnvx/P+XSu88yX57fudf/X/17Puq/h +5tAzFFK0Q9vC1dAorBBYGCwNUNZWMgWLAMDCIHJubmUMHIpFoFEqUCxcGgCW +kgIDFD0cACIgAFhcWlRMGiJGzg1QRrv6YBAOjlgAnzL/zyQJgKILHIOAQVEA +bSjWEe6C04BBkQBDNAwBx/oIAxSRSIDBzx3uAAO4OxzjCbcTJgeDAXYIGBZg +C3dAoMiBPx1poOzRAIm/wnYerv9e8oRj3HGmAHw4k/wAnEU7NArpA7CD25MD +ddC4WnCck/8NU/8UV/NAInWgLj/l/+zSf6xDXRBIn39loF1cPbBwDEAbbQfH +oP6Zeh/+lzklNPI/ymhgoUgETBHlgIQDQH+FEO5qCG+4nR4CC3ME2EOR7vA/ +43CU3T8t4Nr2pwGgooH5PQPN2//6nn8u6kERKKyRj+vfsj+z/2TwL8Z1B4Pw +BliAhEEgMC4R9/v3m9U/iqmiYGg7BAo3EBBxABSDgfqQ4yYDRxCAHxiAQNnB +vQFwb5xjoDAKjcVtAeBaEgCwR2PIf35OsDgAaIfGIuHu7oifK38FpQBAKAzX +ub8jImIAIAxuh0AioX/HxCAAoKOPqyMc9XdIHLdR9W+SEAUANX6RBACo/TdJ +ggBAvV+EyzT8RbjM+79IEgA0/ZtwMwT8ZUEKVw/2yzYIJ2r3G4IBQPhviCvi +8Bvi7P92ZBCuDPI3xCm7/EIwThn1G+KU0b+hCADo+hvimoX5DXGF3H9DXMex +vyHuQB6/Ic6G5y/E3XKg92/4cy8CaffXqf5z6pSU0N5+QhBRgJAIBIwTE5UC +SEBAAf8tEeaBwcBR2D8vNG52/832CNykw+HecBj55BgaJhPulFL/sDhQNXew +hFgAX8mhIUGntm34DUXYxBN8ZMEHLTeB2RrT09I0GsoV4hV2rzMW95gWf/1+ +tZ0Qt4TnoxcrnjYrab5NLKb7ado+y663foRtUr2uHzn8BsHXHZr9WJxkltf9 +YvfdZrYen4rRKsk0B167hWdde3q4uISpWhrSODKihkeUw4D6uVtxlFjkjBd1 +UiLRzEBYoFMkaePtqT10i8eN01zSrKcXDwjt+k1sfmhtJ/tcWzQ/Tej7caM6 +2KooZtEjSzvVLK78zNZimj0DbIHcf5w+wnsgiLVMrWh1/VIxkplnfqJLyiRW +oh6tKXENEdP8Jo/DGK86oZInaKBhJqfF0cZc54itL3eM1VFL/fJVlK/M1nzd +MGVc81vA86ucYB7GTcpKvnR+rktNUa2IyfixCNXz8rqgVDb3hGrKNSe1/Moo ++zbqW3pco8sPhTRmX018+/hsUimsm1xczjEvwU3FhHpXdtGGTPV6jHNbbYnq +U2od3N1991hT/ZhsPPDevp94yFH9QZlGnKo4y8k8e6Ux7/fFPp9roHAHLXke +frQ8oQiLpbEVl+n9mOhVIbB9bvf4ndrSat4Bpatgl5P7kXJZ93anuAsh2LxZ +YV0hK504CuUrRgNBYswsU/I8Xu1Jnjrlpt0Rh5l7pMoXBFQv5ybxYu2vLVOk +j+cUYVJbwJn24yHULE0mi1eUs9Of9iYHMi+5vQRRXJja7459se62ZmDmGm4g +2cnlHglSl7BbT++tpo4NsdwvKz9FqsHWQBFWDrLrMQ3xD0JfBuXwlN7f9ZMP +0PFfpBxu2LwGgnTTxhZNnordFaM9L1qczkSqZ8pvp13PMgp6T/ogD8b8OWNd +fN4sDpwCCCp8jTIeGN3BVLQLpSV7cLH64ZWbnh6p3khJZbHCd2ULvRVLSHPm +b18Da/Epmzkp6YqRfavUhJI0lb9JnGpI4uJIG9tb/97ATxr7KWDHO+a6IbvK +DYo5KigFUH5SZ7N/qWxIUqxDqUSZtmnn+VIrZspzc4ac4PHGi7rOx+xCXI3n +Kw/DgOu2RMaCoZSq9c27naBIpQr+myP5Hv6MOgMeP6jkmKkK7YW0LAOYUz4T +dERcspcwC1GL9G7VI44WNAXW8RJJZF7ifw3xzdc2KHLq7IjhtJFeCuTHOvGb +2qqFy5IoLvMgNvlNuRP4HvlxTbbRHlPo4sXRbWaAb4mw5K3zZ/YRjmaSIxc8 +zt+TSKh9LQN2hY01qceYKWdCU/fPGyvbKP0Z2OmbleD7tnnEdlxTcU81uo0L +N+1KRC43wBSQztZTzCBvfaPwN7DLQzGKQ858V4BfT3Rw5hA7KxihZzuy5MXP +VK5J1zHYw66cy0z13ZNsVfFoKZJsZEMrfa841EzgQop+J4p8rIAmVswtKZIm +ZW+dW8Box/myeSuKiuTJo/cyNVpBIwZk2uKET3UlzhXZPwl5U0kxsEaWPCMJ +khp2WBsZezCnQXKPLTpRP5S35wFfZ7E/nenCW9JK8tfR8mf7F8xNvphaqg1h +WmktB7j0GRmEPBxTq0AC2uvtp7135F3DFUQwaaIumFjU/h3+UcGZS8WYxrZP +seecQQDMyTXZ2vG9him1plmPlGD3mRHndPPFWkxtaZJhGOK9hvzjraoOfS+V +0iwCcZBYq041l4GzT+LD6YPBClCFLnWYTOjGObOGIJSF0jiXgBL5Kf9tXVmd +8c1802r916JKXHQGbLz3ZpPQkBcag3jaGtuy5ASE7XJgapBqqhz7Ee1MuCqN +kuJalATIdnJNE+AtXrdr+DQwvX41z/qb9EtU03JzdJOBWGNU5wFUFdELo6aR +an7O4xPGtXlW/+li7j23v05lQNMPQIWnu0Nrq9FRXXlucw45ZG3BXLYKXJeh +8BkjlvaVroEHdu+i7GWlt6OCxmnga+uJC3F6swtrdgIDb7KqcTn2FNl+R2fQ +TlB7MSTufRM7FcdpCitBTPUCH5WVDrN/isL7JDqT2W3700992iu+wcZa4Y2J +ZR8+bZJoZDyjIvJnSoq9RtPUd+VhCWGK+rXjhWi5sqrx03fpNayvnMCpl5jv +X0JkX51wGtPNmb8D5006RVcYVxBfvzo2sNEXNSUlmFsRnxkcJtVpPskW5hPy +XVWqpZU8ZVGdiDk/Ihh4v9Pp8fbxXOsCqYxezz6jEfjux84GZ+cGpgNo6rxv +AN6lbJrXdPOVWrvyZBcLivtjYXDU+QWx5ER9TJZrPI9wDER7mItD6UJVZko1 +q7alwCYnSvW4rbI8a0d05O6MUWqKOxfFfM0dz3ccU9du8lmICG2EudEv81F9 +OQmjoF/P5RYo3OPZz9sspevcqCSM6geZu74owMpfdAmEXa2GQ5eefjr91EAr +n6WDz/5aQ0rc8dxii3ZMHxqofETd6rbv84CWrhwTPcoR/YD95ufxzq/dOYhO +VayKer5w0FaLOlJoXIJR7yUUv283qKLetTSfTv+RnLP2ti2nVtIqhfXm9SCI +5T5jGQsB8WjRG4UrZPrk/XS0CL3Dq4c8Vwb1zaoJQFm73sP5hmN3/K1Q6S7t +jrs39d8kcDiJj9y+uNLBU5N95e1G3gmStfeEy0Da1ktLwa+H2OEBjNu55Zvo +0xw9yCuM/OoLoaDU1InznanVvVvxZqBCeKSNFsRtNHKjm8s2Autu2r0+mpHR +ClKqluFQlL88O59mJMXnnIizMLzXueZxFhSqUKxuu37djSjWtMsmY6bVOPd8 +8gMNYu7Wk2Avr2RliNUcZ62ivmEHlWk1xVbotn3Vo+G8HVarF1l8I5RyXu1+ +JHQq/mEz16RYdOE2r3R8N0Q01iJ94fR+Isr0jCDddYWqxPNxtu5gHypdaIUp +16YcnT01/lOTwq+Sb/PtqbvxWpzwKx4vcra/27t+3tpZHu071f9a9Q/2PT8i +PG9Td2arq9NqfHgu5XZMcWSPYpUjFdOuvF5Sf03mWU3lW3gc+ODN3aC2LHK+ +HksJ9x30Qf0ZzHgg1CuoyPuRzpetiiGbqM3KiogrsqzB5W9MsZBZNsp8EiTH +YIFHko0ecdIzWeLJlRF86W/7p5PFJm9KUPWMX2QlHtPnuIsemozgtwXdq9f3 +XUEwwmsZTJedGB8CH4VHxhm8MX2zb2hQmMKTWEPda8/v/ujjGlpW+gFeUpXZ +umsIN1FdnovLI6IRDY3VCtF65/G6dAFtvbdRRl3VLN79tUMoKZ1PGI6rpJHA +DEvS/EfDjcqM/aot58TeawsNWuaQXC32O3RMlqDyHWJ1wntGKimSDQ6KF3JC +VbptWdQCUD6dy0Z148G6T6fRrSfo1faKo/OVUKISYHFzu/lSswrZsk8GtdeH +rw4KtbfjxV9pP00lN69wFWSODDe27QZoEnkptTWcuG2xfZ2QKeIgVFxau+CN +RPagG8VDKnpIBf1HEfbzhZFB8XnyZt8MWONTE7FkBFTJNM9t0xWfxZgfl75b +JPeuerPKyrHPApOLaPHnPkmkcjFYs2yK4gMZK1qfBrA542nz+duV143tzF4c +HL5bJ9xIdR5spG/NKKe37XEKpNoehuB/XzCmj8J8yJWbyctTtPRLVyaPem24 +rCCYTEgXn9h6q0V0ceBRZDCFZQYSHpnAEo4HjTlXypqh6QUWzxNiFDiqBhfM +anVEnztbGrMMngfSlTmFv7kxO0v0oSPRCGodNbjXmZ9DqQCPnWDmnVPLulBB +zbCd2144m2RbZ4f724aj3xTAmDooJj+8CB+k7QmDrP+QeEaFGfg2+qj8allL +3Vhyd9aYl9enOJMimElWyLr/8iO4xwDedszActGr28lN7oNpq7V8wdlVx+hM +Ud3gmd1OfsLGwLvsJKLuhl+f9QJfroEGLrf9YAMWewFDqkNYOjkZHR7Cu0qZ +1+rmQGYu5NJx548bN8F3CtWhcE63t5Kjrg+zv3ypnGcYWaSSTHSHdjd8QTzn +Fr4Rp3eIt7IVdP0Pw9OLRY85U29pX/k1vIhnzWYVmlRkc4cCIZnPF7LrikWv +qb7thotVGYbdSN7Idj1J38o5NyIlylDOKQmgYBa1WCW8oS6px7q537MkK8Lz +0oaCRJ++gu/F7S4JMKNbZ9C7p2oNk7yJQZlMDl8Zws7d0NjMF/l7GqchVzQ+ +GKRT4jXXINpJNaSlZEhCOXN7Vs+P9X0pJjVWThlSeVVn1tKHQu1hc6Cesuwr +gMOtXEH+9++n38awMX5UT/wi8XgoUNFgyJNty3EimSfohXUT/LPnd0c4ULWj +Roxuyo1a/byg/VhQSfaFVfy+Vi3yQB5jtPCx+zSBPDwxCGG5mf0Hk+dezEoO +tTM9dkWkvqI88nK/w6GN1CK1cWKK5zP/0Xc/mnd0sWJ6SZ2OYUHWdcPtAuCC +6aGIw9YwBy1S2mCH49G3PWltZ9Gr9Sl0ZUPD5hslax/a4mMP1W3abozaa6d5 +hts5MTJn5/D6A7U1yy4Z1qktE/wrA5jkE4l23tlts/E3yn7N7mP7Yf9dVp/w +VZh+yxRkSZWwq97Zqe6uuYXkWeZxYe+PmEWe/JIlmdBp2wi7J0lBVUFSBZF1 +I9UMmmp45e0iQ1+VnvL4pJnRY5OS7w5YkLgfnRoSM+UdBwpMafqQIySFr46S +sMnSduSXridYbqYa9WVu82PkBTeKW/QBgVYeTz0cJvNdx8yXriUW0hL4sPXN +Fz5vZxals1XTLr0IY1XRJbBJGoAcjihdrb2ha0amdjn+Dn0xKyB4ptq5F43q +V8m+d/VVloYJpxB1Sk2XAv9Nxc0iah3uPLVzVgoXeZgKKF7Awj098wqfm53j +dGUlsPRr8QubEMOkM7/47eplWz8v+4MAY4MFw/DlULM8GWGurdVsyuIscapx +vkMakNfXl06c6++8B8ajzVILp46aLZdV75B/fEHFu85dwSsu/SGUcK6BJlnI +uM/t9iE+tIKffXP0zHo+Tbf3YcCDt/VCnPvCbt2synwzgSfWFeMJaEM5woG5 +Rhdfds/GUfSHLo20z8NFtQIy9jbD9DLP0lNQrBkTRXNhAttfXo54vhKOG5zW +3D4rJVVgzg32qzQykczPsLjhIZg+pUsqffYB2pGe25uhbGaswp8bGr2teBBX +L7TDQWFr2LSawp/osr/9Wq2A9zPXp7qqvK4/2lbvcGmFWX1kexKosyWhtco3 +LElaRiNXN4W38Hq7uvc7jahE7Q8ZAc9+ZY+XyplfLr3I/O8kyRqmVo3Yshxk +pon4O84Gw2r7oJKr9Z0P75YfeLG4xyZ9FLHWx7eb0MjgVzOQ/MGM39465OHy +pDXe4ooKxwX0B0jos03K+b09ubDDdxauKEqzum04vcyGne79aD+Akeyiu2+T +7GMC2gAtxhtEvbUc3MQPOnbJb9YrHg8lYFk3iFTLxAGxIjT1NOvegRNq7Udb +n999PMGXWMjdaFGZKP1aFdXZ0FUaF8usg34i5dJEPF8GiT+LKnqhDDiXuXVe +J3WRKW1DYOZ2EsiWm7sHlZUOQ+88VbwsfH1f3nA25LVFY6nkxM5BcqT9UsJz +Jg0MWeG1bSeI5Dwt/UMILMRB+9XyRjaD9yIBIewjd7Cd5v1+s7sOgnwLz8gy +uhsDWoDcLkrPYHVZw9lYmbBBYqLRWz4JOTXey4rms89fMWEYdC9LjPzW3FWi +tk2/KptloOdCHOcH9XgxLbK38V1JJG+PN317pDEccAJhQ5fxGviyqzPlRMGx +KYL+d4dmVBTbLVGr55T9t+n7gQV0PALDPGKa6ZXzCXvbVnXZ2mtFN9UjkkUG +gQ3Rf+y7Ht2Wycbb+v6xi1a95ujDVumwN/pjTEvet7eQvqg3liYObPk5BPV5 +hcY+8guCZErLY2Naly3XCy8IXS/P7IUgDQhizhUbxhrRRBQB7n+ZeRfYGNRo +HCEO2tRcS2aUl68fXr83zDLqxs44CZ6UCslSS23yAkWa6pektesdmmThuQ9Y +51oXo1LcC6Q6k+/kiKNvX3uOL0bJGDlVQT6H3/2gwrHB+8S+pW7S7H54cRnt +fOlng1XbhJiMwS1E3T4nYZXGrqt1UM4S6dQ6kDxB87RneCj4/MRX3ETv+KX5 +NYOzu29yj8VVCdZnz2rsL9ID8QbWwObNTtCAE+qOg2rqTEvZgm0HIclKbbME +gt1xvmnFu1dt9BgOzWkFeWpn3S8NYQYLBVLcLu3NlIaYFVeFCwZ5umBG4UW6 +uOKQ6U0pixoOUfEHsm+t3sQYa5D0mGOYuux++Nj4M172F1euGL66v3Q7by5i +G68Y7WPvcb9VQNkRFcKw/iYJr/vVZ0sll/cHxLF6i1iCge9TdCJE159aGkV3 +hL0FjyAnXq2usDNF3Dl7u6kndBx7GXhQbgHuKuuhejZ2qKw+H3P/UGZTsMNs +Y7lqojtb5epy4Xe6qGBAm1OBgfmpcKnY2cAhCs14TGB+T+QWh6vancZ+TJe1 +xErnY3Xrlde7mKRu57u3pn2cQtxyQu/lL+zYsj0hkq9eaAl8wom0l79bYk35 +fskk8IrgslR1pL1tyRLYH2KWtCsd9hoTeQQTsKZz8Dz4qN0xtcNn7ehgOlbt +aXnkTfK+6xTsSlrkezvvoQiFv6rtlJjf3Mkw60G489knyISm1ZnzhFS7ZDwQ +K3Nh0FsjQZ2XanI9e37ku63GqcSRFraVlMErJknfHjm4yc/1B0hklzG3INQD +r68hxv3O1Y0vH9Yy6Y1WLz+33SGa1dnyxb+GcniWSBbDEnCnVRmjJGP0h65I +nqlW797LcYcs0TzGlK70ixr4D9D/8CH/f4H/EwIwJByKwaJdoBhn8v8Cv3WB +PGVuZHN0cmVhbQplbmRvYmoKNiAwIG9iaiA8PAovVHlwZSAvRm9udAovU3Vi +dHlwZSAvVHlwZTEKL0VuY29kaW5nIDIzIDAgUgovRmlyc3RDaGFyIDE2Ci9M +YXN0Q2hhciAxMjYKL1dpZHRocyAyNCAwIFIKL0Jhc2VGb250IC9BUlpMUkor +Q01CWDEyCi9Gb250RGVzY3JpcHRvciA0IDAgUgo+PiBlbmRvYmoKNCAwIG9i +aiA8PAovQXNjZW50IDY5NAovQ2FwSGVpZ2h0IDY4NgovRGVzY2VudCAtMTk0 +Ci9Gb250TmFtZSAvQVJaTFJKK0NNQlgxMgovSXRhbGljQW5nbGUgMAovU3Rl +bVYgMTA5Ci9YSGVpZ2h0IDQ0NAovRm9udEJCb3ggWy01MyAtMjUxIDExMzkg +NzUwXQovRmxhZ3MgNAovQ2hhclNldCAoL2RvdGxlc3NpL2FjdXRlL2NlZGls +bGEvaHlwaGVuL0UvSS9NL1AvUy9XL1gvYS9jL2QvZS9nL2kvbC9tL24vby9w +L3Ivcy90L3Uvdi94L3RpbGRlKQovRm9udEZpbGUgNSAwIFIKPj4gZW5kb2Jq +CjI0IDAgb2JqClszMTIgMCAwIDU2MiAwIDAgMCAwIDUwMCAwIDAgMCAwIDAg +MCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMzc1IDAgMCAwIDAgMCAw +IDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCAwIDAgMCA3MzggMCAwIDAg +NDE5IDAgMCAwIDEwNjcgMCAwIDc2OSAwIDAgNjI1IDAgMCAwIDExNjIgODUw +IDAgMCAwIDAgMCAwIDAgMCA1NDcgMCA1MDAgNjI1IDUxMyAwIDU2MiAwIDMx +MiAwIDAgMzEyIDkzNyA2MjUgNTYyIDYyNSAwIDQ1OSA0NDQgNDM3IDYyNSA1 +OTQgMCA1OTQgMCAwIDAgMCAwIDU2MiBdCmVuZG9iagoyMyAwIG9iaiA8PAov +VHlwZSAvRW5jb2RpbmcKL0RpZmZlcmVuY2VzIFsgMCAvLm5vdGRlZiAxNi9k +b3RsZXNzaSAxNy8ubm90ZGVmIDE5L2FjdXRlIDIwLy5ub3RkZWYgMjQvY2Vk +aWxsYSAyNS8ubm90ZGVmIDQ1L2h5cGhlbiA0Ni8ubm90ZGVmIDY5L0UgNzAv +Lm5vdGRlZiA3My9JIDc0Ly5ub3RkZWYgNzcvTSA3OC8ubm90ZGVmIDgwL1Ag +ODEvLm5vdGRlZiA4My9TIDg0Ly5ub3RkZWYgODcvVy9YIDg5Ly5ub3RkZWYg +OTcvYSA5OC8ubm90ZGVmIDk5L2MvZC9lIDEwMi8ubm90ZGVmIDEwMy9nIDEw +NC8ubm90ZGVmIDEwNS9pIDEwNi8ubm90ZGVmIDEwOC9sL20vbi9vL3AgMTEz +Ly5ub3RkZWYgMTE0L3Ivcy90L3UvdiAxMTkvLm5vdGRlZiAxMjAveCAxMjEv +Lm5vdGRlZiAxMjYvdGlsZGUgMTI3Ly5ub3RkZWZdCj4+IGVuZG9iagoxNiAw +IG9iaiA8PAovVHlwZSAvUGFnZXMKL0NvdW50IDEKL0tpZHMgWzIgMCBSXQo+ +PiBlbmRvYmoKMjUgMCBvYmogPDwKL1R5cGUgL0NhdGFsb2cKL1BhZ2VzIDE2 +IDAgUgo+PiBlbmRvYmoKMjYgMCBvYmogPDwKL1Byb2R1Y2VyIChwZGZlVGVY +LTEuMjFhKQovQ3JlYXRvciAoVGVYKQovQ3JlYXRpb25EYXRlIChEOjIwMDcw +ODE4MTU1ODIzLTAzJzAwJykKL1BURVguRnVsbGJhbm5lciAoVGhpcyBpcyBw +ZGZlVGVYLCBWZXJzaW9uIDMuMTQxNTkyLTEuMjFhLTIuMiAoV2ViMkMgNy41 +LjQpIGtwYXRoc2VhIHZlcnNpb24gMy41LjQpCj4+IGVuZG9iagp4cmVmCjAg +MjcKMDAwMDAwMDAwMCA2NTUzNSBmIAowMDAwMDAyMjE4IDAwMDAwIG4gCjAw +MDAwMDIxMDMgMDAwMDAgbiAKMDAwMDAwMDAwOSAwMDAwMCBuIAowMDAwMDMw +NTQ5IDAwMDAwIG4gCjAwMDAwMjQ1MTggMDAwMDAgbiAKMDAwMDAzMDM5MyAw +MDAwMCBuIAowMDAwMDIzNjIxIDAwMDAwIG4gCjAwMDAwMTc1MTUgMDAwMDAg +biAKMDAwMDAyMzQ2NSAwMDAwMCBuIAowMDAwMDE2MTM2IDAwMDAwIG4gCjAw +MDAwMDUxNjkgMDAwMDAgbiAKMDAwMDAxNTk3OSAwMDAwMCBuIAowMDAwMDA0 +NzE0IDAwMDAwIG4gCjAwMDAwMDIzMjAgMDAwMDAgbiAKMDAwMDAwNDU1NiAw +MDAwMCBuIAowMDAwMDMxNTQxIDAwMDAwIG4gCjAwMDAwMDUwNDkgMDAwMDAg +biAKMDAwMDAwNDkyMiAwMDAwMCBuIAowMDAwMDE2OTEwIDAwMDAwIG4gCjAw +MDAwMTY1NTMgMDAwMDAgbiAKMDAwMDAyNDE0NiAwMDAwMCBuIAowMDAwMDIz +OTE1IDAwMDAwIG4gCjAwMDAwMzExMjcgMDAwMDAgbiAKMDAwMDAzMDgyNiAw +MDAwMCBuIAowMDAwMDMxNTk5IDAwMDAwIG4gCjAwMDAwMzE2NTAgMDAwMDAg +biAKdHJhaWxlcgo8PAovU2l6ZSAyNwovUm9vdCAyNSAwIFIKL0luZm8gMjYg +MCBSCi9JRCBbPDk2RUQxNUYwNEE5MDE3QkQxQTVDOEY0NDAxQTFDNDEwPiA8 +OTZFRDE1RjA0QTkwMTdCRDFBNUM4RjQ0MDFBMUM0MTA+XQo+PgpzdGFydHhy +ZWYKMzE4NTMKJSVFT0YK +==== +***end123*** + +probnumber=2 +probname=B +probfullname=CCA A 1 +probbasename=cc +probtimelimit=3 +probcolorname=cccaaa +probcolor=333333 +probinputfilemd5=41545cd5f6a54ab28996d8e0109ba756 +probinputfile=c.in +ac +ac +ac + +ac +ac + +ac +***end123*** +probsolfilemd5=696fd0c1a38fa96d213ae34469540cc6 +probsolfile=c.sol +caa +aca +aac + +caa +aca +aac +***end123*** + +[end] diff --git a/boca-1.5.0/old/run.sh b/boca-1.5.0/old/run.sh new file mode 100755 index 0000000..7f4740e --- /dev/null +++ b/boca-1.5.0/old/run.sh @@ -0,0 +1,164 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +#Last modified: 10/aug/2009 by cassio@ime.usp.br +# +# parameters are: +# $1 base_filename +# $2 source_file +# $3 input_file +# $4 languagename +# $5 problemname +# $6 timelimit +# +# the output of the submission should be directed to the standard output +# +# the return code show what happened: +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# other_codes are unknown to boca: in this case BOCA will present the +# last line of standard output to the judge + +umask 0022 +chown nobody.nogroup . + +export CLASSPATH=.:$CLASSPATH + +# this script makes use of safeexec to execute the code with less privilegies +# make sure that directories below are correct. +sf=`which safeexec` +[ -x "$sf" ] || sf=/usr/bin/safeexec +gcc=`which gcc` +[ -x "$gcc" ] || gcc=/usr/bin/gcc +gpp=`which g++` +[ -x "$gpp" ] || gpp=/usr/bin/g++ +java=`which java` +[ -x "$java" ] || java=/usr/java/bin/java +javac=`which javac` +[ -x "$javac" ] || javac=/usr/java/bin/javac +pascal=`which fpc` +[ -x "$pascal" ] || pascal=/usr/bin/fpc +grep=`which grep` +[ -x "$grep" ] || grep=/bin/grep + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" ]; then + echo "parameter problem" + exit 43 +fi +if [ ! -r "$2" ]; then + echo "$2 not found or it's not readable" + exit 44 +fi +if [ ! -r "$3" ]; then + echo "$3 not found or it's not readable" + exit 45 +fi +if [ ! -x "$sf" ]; then + echo "$sf not found or it's not executable" + exit 46 +fi + +prefix=$1 +name=$2 +input=$3 + +# setting up the timelimit according to the problem +# note that problems should spelling the same as inside BOCA +if [ "$6" == "" ]; then +time=5 +else +time=$6 +fi +let ttime=$time+30 + +# choose the compiler according to the language +# note that languages should spelling the same as inside BOCA +case "$4" in +C) + $gcc -lm -o "$prefix" "$name" + ret=$? + if [ "$ret" != "0" ]; then + echo "Compiling Error: $ret" + exit 1 + else + $sf -F10 -t$time -T$ttime -i$input -n0 -R. "./$prefix" + ret=$? + if [ $ret -gt 3 ]; then + ret=0 + fi + fi + ;; +C++) + $gpp -lm -o "$prefix" "$name" + ret=$? + if [ "$ret" != "0" ]; then + echo "Compiling Error: $ret" + exit 1 + else + $sf -F10 -t$time -T$ttime -i$input -n0 -R. "./$prefix" + ret=$? + if [ $ret -gt 3 ]; then + ret=0 + fi + fi + ;; +Pascal) + $pascal -o"$prefix" "$name" >compiler.out 2>compiler.out + $grep -irq linking compiler.out + ret=$? + $grep -irq "lines compiled" compiler.out + ret2=$? + if [ "$ret" != "0" -o "$ret2" != "0" ]; then + cat compiler.out + echo "Compiling Error: $ret" + exit 1 + else + $sf -F10 -t$time -T$ttime -i$input -opascal.out -n0 -R. "./$prefix" + ret=$? + if [ -f pascal.out ]; then + cat pascal.out + $grep -irq "runtime error" pascal.out + ret2=$? + if [ "$ret2" = "0" ]; then + echo "Strange output - possible runtime error" + if [ $ret -lt 4 ]; then + ret=48 + fi + fi + fi + fi + ;; +Java) + $javac "$name" + ret=$? + if [ "$ret" != "0" ]; then + echo "Compiling Error: $ret" + exit 1 + else + $sf -u10 -F30 -t$time -T$ttime -i$input -n0 -R. $java "$prefix" + ret=$? + if [ $ret -gt 3 ]; then + echo "Nonzero return code - possible runtime error" + ret=47 + fi + fi + ;; +*) + echo "Language not recognized" + exit 42 + ;; +esac +exit $ret diff --git a/boca-1.5.0/old/updatescore.sh b/boca-1.5.0/old/updatescore.sh new file mode 100755 index 0000000..a9c05b7 --- /dev/null +++ b/boca-1.5.0/old/updatescore.sh @@ -0,0 +1,118 @@ +#!/bin/bash +#////////////////////////////////////////////////////////////////////////////////////////// +#//BOCA Online Contest Administrator. Copyright (c) 2003- Cassio Polpo de Campos. +#//It may be distributed under the terms of the Q Public License version 1.0. A copy of the +#//license can be found with this software or at http://www.opensource.org/licenses/qtpl.php +#// +#//THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +#//INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +#//PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER +#//OR HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR +#//CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR +#//PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING +#//OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +#/////////////////////////////////////////////////////////////////////////////////////////// +# last updated 26/oct/2011 by cassio@ime.usp.br +for i in id chown chmod md5sum wget tr cut awk tail head grep cat sed sleep; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done +if [ "`id -u`" != "0" ]; then + echo "Script must run as root" +fi + +privatedir=/var/www/boca/private +if [ ! -d $privatedir ]; then + echo "Could not find directory $privatedir" + exit 1 +fi +httpbocadir=boca +tempdir=/tmp +others=/var/www/boca/private/otherservers +secs=120 +apacheuser= +[ -r /etc/icpc/apacheuser ] && apacheuser=`cat /etc/icpc/apacheuser | sed 's/ \t\n//g'` +[ "$apacheuser" == "" ] && apacheuser=www-data +id -u $apacheuser > /dev/null 2>/dev/null +[ $? != 0 ] && echo "User $apacheuser not found -- error to set permissions with chown/chmod" + +#hash="shasum -a 256 -" +hash="md5sum -" + +#rm -f $privatedir/score_*.dat +#rm -f $privatedir/thissitescore.dat +chown $apacheuser.root $privatedir/score_*.dat +chown $apacheuser.root $privatedir/thissitescore.dat + +BOCASERVER= +[ -x /etc/icpc/bocaserver.sh ] && . /etc/icpc/bocaserver.sh +LOCALSERVER=$BOCASERVER +if [ "$LOCALSERVER" == "" -o "$LOCALSERVER" == "0/0" ]; then + LOCALSERVER=http://127.0.0.1/$httpbocadir +else + LOCALSERVER=http://$LOCALSERVER/$httpbocadir +fi + +if [ ! -r $others ]; then + echo "External server list in $others not found" + exit 1 +fi +echo "Starting loop to get scores from servers defined in $others" +while /bin/true; do +echo "Getting scores..." + +qtd=1 +for BOCASERVER in `grep -v "^[ \t]*\#" $others | awk '{ print $1; }'`; do +if [ "$BOCASERVER" == "" ]; then + continue +fi +echo $BOCASERVER | grep -q "http" +[ $? == 0 ] || BOCASERVER=http://$BOCASERVER/boca + +user=`grep -v "^[ \t]*\#" $others | head -n$qtd | tail -n1 | awk '{ print $2; }'` +[ "$user" == "" ] && user=score +pass=`grep -v "^[ \t]*\#" $others | head -n$qtd | tail -n1 | awk '{ print $2; }'` +[ "$pass" == "" ] && pass=score +let "qtd = $qtd + 1" + +wget -t3 -T3 "$LOCALSERVER/scoretable.php?clock=1" -O $tempdir/.temp.txt 2>/dev/null >/dev/null +if [ $? != 0 ]; then + echo "Error getting contest clock from $LOCALSERVER" +else + tempo=`cat $tempdir/.temp.txt` + echo -n "Asking server $BOCASERVER at time $tempo. Authenticating with user '$user'..." + md=`wget -t3 -T3 -S $BOCASERVER/index.php -O /dev/null --save-cookies $tempdir/.cookie.txt --keep-session-cookies 2>&1 | grep PHPSESS | tail -n1 | cut -f2 -d'=' | cut -f1 -d';'` + res=`echo -n $pass | $hash | cut -f1 -d' '` + res=`echo -n "${res}${md}" | $hash | cut -f1 -d' '` + echo -n "sending password..." + wget -t3 -T3 "$BOCASERVER/index.php?name=${user}&password=${res}" --load-cookies $tempdir/.cookie.txt --keep-session-cookies --save-cookies $tempdir/.cookie.txt -O $tempdir/.temp.txt 2>/dev/null >/dev/null + grep -qi incorrect $tempdir/.temp.txt + if [ $? != 0 ]; then + fname=`echo $BOCASERVER | tr './:' '_'` + echo "downloading scoretable..." + wget -t3 -T3 "$BOCASERVER/scoretable.php?remote=$tempo" --load-cookies $tempdir/.cookie.txt --keep-session-cookies --save-cookies $tempdir/.cookie.txt -O $privatedir/score_${fname}.tmp 2>$tempdir/.bocascore.tmp >$tempdir/.bocascore.tmp + if [ $? == 0 ]; then + chown $apacheuser.root $privatedir/score_$fname.tmp + chmod 660 $privatedir/score_$fname.tmp + mv $privatedir/score_$fname.tmp $privatedir/score_$fname.dat + echo "Score downloaded successfully into $privatedir/score_$fname.dat" + else + echo "Error getting scoretable from $BOCASERVER: `cat $tempdir/.bocascore.tmp`" + fi + else + echo "Error authenticating to server $BOCASERVER" + fi +fi +rm -f $tempdir/.temp.txt +rm -f $tempdir/.cookie.txt +done + +echo -n "Waiting $secs secs..." +sleep $secs +echo "" +done diff --git a/boca-1.5.0/src/.htaccess b/boca-1.5.0/src/.htaccess new file mode 100644 index 0000000..dbafa30 --- /dev/null +++ b/boca-1.5.0/src/.htaccess @@ -0,0 +1,5 @@ +php_flag output_buffering on +php_value memory_limit 256M +php_value post_max_size 128M +php_flag magic_quotes_gpc off +php_value upload_max_filesize 128M diff --git a/boca-1.5.0/src/Css.php b/boca-1.5.0/src/Css.php new file mode 100644 index 0000000..50680b3 --- /dev/null +++ b/boca-1.5.0/src/Css.php @@ -0,0 +1,71 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +$corfundo = "#e0e0d0"; +$corfrente = "#000000"; +$corfundo2 = "#dfdfdf"; +$cormenu = "#dfdfdf"; +?> +DIV.menu {background-color:<?php echo $corfundo?>; layer-background-color:<?php echo $corfundo?>} +DIV.menudown {background-color:<?php echo $cormenu?>; border-bottom:1px solid white; border-right:1px solid white;border-top:2px solid #555555;border-left:1px solid #555555} +DIV.fname {background-color:<?php echo $corfundo2?>; layer-background-color:<?php echo $corfundo2?>; position:absolute; visibility:hidden; border:0; left:0px; top:0px; height:19px; z-index:100;} +DIV.dir {background-color:<?php echo $corfundo?>; layer-background-color:<?php echo $corfundo?>; position:absolute; visibility:hidden; border:0; left:0px; top:0px; height:19px;z-index:100; } +A {font-family:"Courier New", Courier, mono; font-size:12pt; color:<?php echo $corfrente?>} +A.header {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12pt} +A.menu {font-family:Verdana, Arial, Helvetica, sans-serif; text-decoration:none; font-size:12pt; border: 1px solid <?php echo $corfundo?>} +A.menu:hover {background-color:<?php echo $cormenu?>; border-bottom:1px solid #555555; border-right:1px solid #555555;border-top:1px solid white;border-left:1px solid white} +A.user {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12pt} +A.user:hover {font-weight: bolder} +A.disabled {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12pt; text-decoration:none; color:#BFBFBF} +A.form {font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12pt; background-color:<?php echo $cormenu?>} +BODY {background-color:<?php echo $corfundo?>; font-family:"Courier new", monospace; font-size:12pt; color:<?php echo $corfrente?>} +BODY.cline {background-color:#000000; color:#FFFFFF} +TABLE { font-family:"Courier New", Courier, mono; font-size:12pt } +TABLE.form { font-family:Verdana, Arial, Helvetica, sans-serif; font-size:12pt } +FORM { font-size:12pt;} +FORM.alt { font-size:12pt; margin-top: 5px } +FORM.fname { font-size:12pt; margin: 0px} +INPUT.fname { font-family:"Courier New", Courier, mono;font-size:12pt; border:0; background-color:<?php echo $corfundo2?> } +FORM.dir { font-size:12pt; margin: 0px} +INPUT.dir { font-family:"Courier New", Courier, mono;font-size:12pt; border:0; background-color:<?php echo $corfundo?> } +<?php if( strstr(getenv("HTTP_USER_AGENT"), "MSIE")) { ?> +input.checkbox { border:none } +<?php } else { ?> +input.checkbox { } +<?php } ?> +INPUT { font-size:12pt; border:1px solid #555555} +INPUT.cline { background-color:#000000; font-family:"Courier new", monospace; font-size:12pt; color:#FFFFFF; border:0} +TEXTAREA { border:1px solid #555555 } +TEXTAREA.edit { font-family:"Courier New", Courier, mono;font-size:10pt; background-color:#EFEFEF } +SELECT { font-size:12pt;} +p.link a:hover {background-color: #2B2E21;;color:#fff;} +p.link a:link span{display: none;} +p.link a:visited span{display: none;} +p.link a:hover span { + position: absolute; + margin:15px 0px 0px 20px; + background-color: beige; + max-width:220; + padding: 2px 10px 2px 10px; + border: 1px solid #C0C0C0; + font: normal 10px/12px verdana; + color: #000; + text-align:left; + display: block; +} +<?php for($i=1;$i<999;$i++) echo "table.sitehide$i .sitegroup$i { display: none; }\n"; ?> diff --git a/boca-1.5.0/src/Md5.js b/boca-1.5.0/src/Md5.js new file mode 100644 index 0000000..65c8c44 --- /dev/null +++ b/boca-1.5.0/src/Md5.js @@ -0,0 +1,226 @@ +/* + * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message + * Digest Algorithm, as defined in RFC 1321. + * Copyright (C) Paul Johnston 1999 - 2000. + * Updated by Greg Holt 2000 - 2001. + * See http://pajhome.org.uk/site/legal.html for details. + +The BSD License +--------------- +Copyright (c) 1998 - 2002, Paul Johnston & Contributors +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list +of conditions and the following disclaimer. Redistributions in binary form must +reproduce the above copyright notice, this list of conditions and the following +disclaimer in the documentation and/or other materials provided with the distribution. + +Neither the name of Paul Johnston nor pajhome.org.uk nor the names of its contributors +may be used to endorse or promote products derived from this software without specific +prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN +ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + +JavaScript MD5 +-------------- +The JavaScript code implementing the algorithm is derived from the C code in RFC 1321 +and is covered by the following copyright: + +Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All rights reserved. +License to copy and use this software is granted provided that it is identified as +the "RSA Data Security, Inc. MD5 Message-Digest Algorithm" in all material mentioning +or referencing this software or this function. + +License is also granted to make and use derivative works provided that such works are +identified as "derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm" +in all material mentioning or referencing the derived work. + +RSA Data Security, Inc. makes no representations concerning either the merchantability +of this software or the suitability of this software for any particular purpose. It is +provided "as is" without express or implied warranty of any kind. + +These notices must be retained in any copies of any part of this documentation and/or +software. + +This copyright does not prohibit distribution of the JavaScript MD5 code under the +BSD license. + */ + +/* + * Convert a 32-bit number to a hex string with ls-byte first + */ +var hex_chr = "0123456789abcdef"; +function rhex(num) +{ + str = ""; + for(j = 0; j <= 3; j++) + str += hex_chr.charAt((num >> (j * 8 + 4)) & 0x0F) + + hex_chr.charAt((num >> (j * 8)) & 0x0F); + return str; +} + +/* + * Convert a string to a sequence of 16-word blocks, stored as an array. + * Append padding bits and the length, as described in the MD5 standard. + */ +function str2blks_MD5(str) +{ + nblk = ((str.length + 8) >> 6) + 1; + blks = new Array(nblk * 16); + for(i = 0; i < nblk * 16; i++) blks[i] = 0; + for(i = 0; i < str.length; i++) + blks[i >> 2] |= str.charCodeAt(i) << ((i % 4) * 8); + blks[i >> 2] |= 0x80 << ((i % 4) * 8); + blks[nblk * 16 - 2] = str.length * 8; + return blks; +} + +/* + * Add integers, wrapping at 2^32. This uses 16-bit operations internally + * to work around bugs in some JS interpreters. + */ +function add(x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} + +/* + * Bitwise rotate a 32-bit number to the left + */ +function rol(num, cnt) +{ + return (num << cnt) | (num >>> (32 - cnt)); +} + +/* + * These functions implement the basic operation for each round of the + * algorithm. + */ +function cmn(q, a, b, x, s, t) +{ + return add(rol(add(add(a, q), add(x, t)), s), b); +} +function ff(a, b, c, d, x, s, t) +{ + return cmn((b & c) | ((~b) & d), a, b, x, s, t); +} +function gg(a, b, c, d, x, s, t) +{ + return cmn((b & d) | (c & (~d)), a, b, x, s, t); +} +function hh(a, b, c, d, x, s, t) +{ + return cmn(b ^ c ^ d, a, b, x, s, t); +} +function ii(a, b, c, d, x, s, t) +{ + return cmn(c ^ (b | (~d)), a, b, x, s, t); +} + +/* + * Take a string and return the hex representation of its MD5. + */ +function calcMD5(str) +{ + x = str2blks_MD5(str); + a = 1732584193; + b = -271733879; + c = -1732584194; + d = 271733878; + + for(i = 0; i < x.length; i += 16) + { + olda = a; + oldb = b; + oldc = c; + oldd = d; + + a = ff(a, b, c, d, x[i+ 0], 7 , -680876936); + d = ff(d, a, b, c, x[i+ 1], 12, -389564586); + c = ff(c, d, a, b, x[i+ 2], 17, 606105819); + b = ff(b, c, d, a, x[i+ 3], 22, -1044525330); + a = ff(a, b, c, d, x[i+ 4], 7 , -176418897); + d = ff(d, a, b, c, x[i+ 5], 12, 1200080426); + c = ff(c, d, a, b, x[i+ 6], 17, -1473231341); + b = ff(b, c, d, a, x[i+ 7], 22, -45705983); + a = ff(a, b, c, d, x[i+ 8], 7 , 1770035416); + d = ff(d, a, b, c, x[i+ 9], 12, -1958414417); + c = ff(c, d, a, b, x[i+10], 17, -42063); + b = ff(b, c, d, a, x[i+11], 22, -1990404162); + a = ff(a, b, c, d, x[i+12], 7 , 1804603682); + d = ff(d, a, b, c, x[i+13], 12, -40341101); + c = ff(c, d, a, b, x[i+14], 17, -1502002290); + b = ff(b, c, d, a, x[i+15], 22, 1236535329); + + a = gg(a, b, c, d, x[i+ 1], 5 , -165796510); + d = gg(d, a, b, c, x[i+ 6], 9 , -1069501632); + c = gg(c, d, a, b, x[i+11], 14, 643717713); + b = gg(b, c, d, a, x[i+ 0], 20, -373897302); + a = gg(a, b, c, d, x[i+ 5], 5 , -701558691); + d = gg(d, a, b, c, x[i+10], 9 , 38016083); + c = gg(c, d, a, b, x[i+15], 14, -660478335); + b = gg(b, c, d, a, x[i+ 4], 20, -405537848); + a = gg(a, b, c, d, x[i+ 9], 5 , 568446438); + d = gg(d, a, b, c, x[i+14], 9 , -1019803690); + c = gg(c, d, a, b, x[i+ 3], 14, -187363961); + b = gg(b, c, d, a, x[i+ 8], 20, 1163531501); + a = gg(a, b, c, d, x[i+13], 5 , -1444681467); + d = gg(d, a, b, c, x[i+ 2], 9 , -51403784); + c = gg(c, d, a, b, x[i+ 7], 14, 1735328473); + b = gg(b, c, d, a, x[i+12], 20, -1926607734); + + a = hh(a, b, c, d, x[i+ 5], 4 , -378558); + d = hh(d, a, b, c, x[i+ 8], 11, -2022574463); + c = hh(c, d, a, b, x[i+11], 16, 1839030562); + b = hh(b, c, d, a, x[i+14], 23, -35309556); + a = hh(a, b, c, d, x[i+ 1], 4 , -1530992060); + d = hh(d, a, b, c, x[i+ 4], 11, 1272893353); + c = hh(c, d, a, b, x[i+ 7], 16, -155497632); + b = hh(b, c, d, a, x[i+10], 23, -1094730640); + a = hh(a, b, c, d, x[i+13], 4 , 681279174); + d = hh(d, a, b, c, x[i+ 0], 11, -358537222); + c = hh(c, d, a, b, x[i+ 3], 16, -722521979); + b = hh(b, c, d, a, x[i+ 6], 23, 76029189); + a = hh(a, b, c, d, x[i+ 9], 4 , -640364487); + d = hh(d, a, b, c, x[i+12], 11, -421815835); + c = hh(c, d, a, b, x[i+15], 16, 530742520); + b = hh(b, c, d, a, x[i+ 2], 23, -995338651); + + a = ii(a, b, c, d, x[i+ 0], 6 , -198630844); + d = ii(d, a, b, c, x[i+ 7], 10, 1126891415); + c = ii(c, d, a, b, x[i+14], 15, -1416354905); + b = ii(b, c, d, a, x[i+ 5], 21, -57434055); + a = ii(a, b, c, d, x[i+12], 6 , 1700485571); + d = ii(d, a, b, c, x[i+ 3], 10, -1894986606); + c = ii(c, d, a, b, x[i+10], 15, -1051523); + b = ii(b, c, d, a, x[i+ 1], 21, -2054922799); + a = ii(a, b, c, d, x[i+ 8], 6 , 1873313359); + d = ii(d, a, b, c, x[i+15], 10, -30611744); + c = ii(c, d, a, b, x[i+ 6], 15, -1560198380); + b = ii(b, c, d, a, x[i+13], 21, 1309151649); + a = ii(a, b, c, d, x[i+ 4], 6 , -145523070); + d = ii(d, a, b, c, x[i+11], 10, -1120210379); + c = ii(c, d, a, b, x[i+ 2], 15, 718787259); + b = ii(b, c, d, a, x[i+ 9], 21, -343485551); + + a = add(a, olda); + b = add(b, oldb); + c = add(c, oldc); + d = add(d, oldd); + } + return rhex(a) + rhex(b) + rhex(c) + rhex(d); +} diff --git a/boca-1.5.0/src/admin/answer.php b/boca-1.5.0/src/admin/answer.php new file mode 100644 index 0000000..c2d1fdc --- /dev/null +++ b/boca-1.5.0/src/admin/answer.php @@ -0,0 +1,134 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +require('header.php'); + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("$loc/index.php"); + +if (isset($_GET["delete"]) && is_numeric($_GET["delete"])) { + $param["number"] = $_GET["delete"]; + if(!DBDeleteAnswer($_SESSION["usertable"]["contestnumber"], $param)) { + MSGError('Error deleting answer'); + LogError('Error deleting answer'); + } + ForceLoad("answer.php"); +} + +if (isset($_POST["Submit3"]) && isset($_POST["answernumber"]) && is_numeric($_POST["answernumber"]) && isset($_POST["answername"]) && + $_POST["answername"] != "" && isset($_POST["answeryes"])) { + if ($_POST["confirmation"] == "confirm") { + $param["number"] = $_POST["answernumber"]; + $param["name"] = $_POST["answername"]; + $param["yes"] = $_POST["answeryes"]; + DBNewAnswer ($_SESSION["usertable"]["contestnumber"],$param); + } + ForceLoad("answer.php"); +} +?> +<br> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + function conf2(url) { + if (confirm("Confirm the DELETION of the ANSWER and ALL data associated to it (including the SUBMISSIONS)?")) { + if (confirm("Are you REALLY sure about what you are doing? DATA CANNOT BE RECOVERED!")) { + document.location=url; + } else { + document.location='answer.php'; + } + } else { + document.location='answer.php'; + } + } + </script> +<table width="100%" border=1> + <tr> + <td><b>Answer #</b></td> + <td><b>Description</b></td> + <td><b>Yes/No</b></td> + </tr> +<?php +$ans = DBGetAnswers($_SESSION["usertable"]["contestnumber"]); +$n=0; +for ($i=0; $i<count($ans); $i++) { + echo " <tr>\n"; + if($ans[$i]["fake"]!="t") { + if($ans[$i]["number"]>7) { + echo " <td nowrap><a href=\"javascript:conf2('answer.php?delete=" . $ans[$i]["number"] . + "')\">" . $ans[$i]["number"] . "</a></td>\n"; + } else + echo " <td nowrap>".$ans[$i]["number"]."</td>\n"; + } else { + echo " <td nowrap>".$ans[$i]["number"]." (fake)</td>\n"; + } + echo " <td nowrap>" . $ans[$i]["desc"] . "</td>\n"; + if($ans[$i]["yes"]=="t") echo " <td nowrap>Yes</td>\n"; + else echo " <td nowrap>No</td>\n"; + echo " </tr>\n"; + $n++; +} +echo "</table>"; +if ($n == 0) echo "<br><center><b><font color=\"#ff0000\">NO ANSWERS DEFINED</font></b></center>"; +?> + +<br><br><center><b>When allowed, clicking on the answer number will delete it.<br> + Inputting with the same number of an existing one will update its description.<br> + TAKE CARE: deleting an answer will remove EVERYTHING related to it (ALSO IN OTHER TABLES!!).<br> + It is NOT recommended to change anything while the contest is running.<br> + To insert a new answer, enter the data below.<br> + Note that any changes will overwrite the already defined data.<br><br> +</b> +<form name="form1" enctype="multipart/form-data" method="post" action="answer.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <table border="0"> + <tr> + <td width="35%" align=right>Number:</td> + <td width="65%"> + <input type="text" name="answernumber" value="" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Description:</td> + <td width="65%"> + <input type="text" name="answername" value="" size="50" maxlength="50" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Type:</td> + <td width="65%"> + <select name="answeryes"> + <option selected value="f">No</option> + <option value="t">Yes</option> + </select> + </td> + </tr> + </table> + </center> + <center> + <input type="submit" name="Submit3" value="Send" onClick="conf()"> + <input type="reset" name="Submit4" value="Clear"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/admin/clar.php b/boca-1.5.0/src/admin/clar.php new file mode 100644 index 0000000..66a7b0d --- /dev/null +++ b/boca-1.5.0/src/admin/clar.php @@ -0,0 +1,112 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +require 'header.php'; +if (isset($_POST["message"]) && isset($_POST["problem"]) && isset($_POST["Submit"])) { + if ($_POST["confirmation"] == "confirm") { + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + $param['site']=$_SESSION["usertable"]["usersitenumber"]; + $param['user']= $_SESSION["usertable"]["usernumber"]; + $param['problem'] = htmlspecialchars($_POST["problem"]); + $param['question'] = htmlspecialchars($_POST["message"]); + DBNewClar($param); + } + ForceLoad("clar.php"); +} +if(isset($_GET["order"]) && $_GET["order"] != "") { + $order = htmlspecialchars($_GET["order"]); + $_SESSION["clarline"] = $order; +} else { + if(isset($_SESSION["clarline"])) + $order = $_SESSION["clarline"]; + else + $order=''; +} +?> +<br> +<table width="100%" border=1> + <tr> + <td><b><a href="clar.php?order=clar">Clar #</a></b></td> + <td><b><a href="clar.php?order=site">Site</a></b></td> + <td><b><a href="clar.php?order=user">User</a></b></td> + <td><b>Time</b></td> + <td><b><a href="clar.php?order=problem">Problem</a></b></td> + <td><b><a href="clar.php?order=status">Status</a></b></td> + <td><b><a href="clar.php?order=judge">Judge (Site)</a></b></td> + <td><b>Question</b></td> + <td><b>Answer</b></td> + </tr> +<?php + +if(($s = DBSiteInfo($_SESSION["usertable"]["contestnumber"], $_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("$loc/index.php"); + +// forca aparecer as clars do proprio site +if (trim($s["sitejudging"])!="") $s["sitejudging"].=",".$_SESSION["usertable"]["usersitenumber"]; +else $s["sitejudging"]=$_SESSION["usertable"]["usersitenumber"]; + +$clar = DBAllClarsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"], $order); + +for ($i=0; $i<count($clar); $i++) { + echo " <tr>\n"; + echo " <td nowrap><a href=\"claredit.php?clarnumber=".$clar[$i]["number"]."&clarsitenumber=".$clar[$i]["site"] . + "\">" . $clar[$i]["number"] . "</a></td>\n"; + echo " <td nowrap>" . $clar[$i]["site"] . "</td>\n"; + echo " <td nowrap>" . $clar[$i]["user"] . "</td>\n"; + echo " <td nowrap>" . dateconvminutes($clar[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $clar[$i]["problem"] . "</td>\n"; + if ($clar[$i]["judge"] == $_SESSION["usertable"]["usernumber"] && + $clar[$i]["judgesite"] == $_SESSION["usertable"]["usersitenumber"] && $clar[$i]["status"] == "answering") + $color="ff7777"; + else if (strpos($clar[$i]["status"], "answered") !== false) $color="bbbbff"; + else if ($clar[$i]["status"] == "answering") $color="77ff77"; + else if ($clar[$i]["status"] == "openclar") $color="ffff88"; + else $color="ffffff"; + + echo " <td nowrap bgcolor=\"#$color\">" . $clar[$i]["status"] . "</td>\n"; + if ($clar[$i]["judge"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $clar[$i]["judgesite"], $clar[$i]["judge"]); + echo " <td nowrap>" . $u["username"] . " (" . $clar[$i]["judgesite"] . ")</td>\n"; + } + else + echo " <td> </td>\n"; + + if ($clar[$i]["question"] == "") $clar[$i]["question"] = " "; + + echo " <td>"; +// echo "<pre>" . $clar[$i]["question"] . "</pre>"; +// echo $clar[$i]["question"]; + echo " <textarea name=\"m$i\" cols=\"60\" rows=\"8\" readonly>".$clar[$i]["question"]."</textarea>\n"; + echo "</td>\n"; + if (trim($clar[$i]["answer"]) == "") $clar[$i]["answer"] = "Not answered yet"; + echo " <td>"; +// echo " <pre>" . $clar[$i]["answer"] . "</pre>"; +// echo $clar[$i]["answer"]; + echo " <textarea name=\"a$i\" cols=\"60\" rows=\"8\" readonly>".$clar[$i]["answer"]."</textarea>\n"; + echo "</td>\n"; + + echo " </tr>\n"; +} + +echo "</table>"; +if (count($clar) == 0) echo "<br><center><b><font color=\"#ff0000\">NO CLARIFICATIONS AVAILABLE</font></b></center>"; + +?> +</body> +</html> diff --git a/boca-1.5.0/src/admin/claredit.php b/boca-1.5.0/src/admin/claredit.php new file mode 100644 index 0000000..91fae39 --- /dev/null +++ b/boca-1.5.0/src/admin/claredit.php @@ -0,0 +1,171 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require 'header.php'; + +if (isset($_POST["cancel"]) && $_POST["cancel"]=="Cancel") + ForceLoad("clar.php"); + +if (isset($_POST["delete"]) && $_POST["delete"]=="Delete" && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["number"]) && + is_numeric($_POST["sitenumber"])) { + if ($_POST["confirmation"]=="confirm") { + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + + if (DBClarDelete($number, $sitenumber, $_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"])) + MSGError("Clarification deleted."); + } + ForceLoad("clar.php"); +} + +if (isset($_POST["answer"]) && isset($_POST["open"]) && $_POST["open"]=="Open the Clar" && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["number"]) && + is_numeric($_POST["sitenumber"])) { + if ($_POST["confirmation"]=="confirm") { + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + + if (DBChiefClarGiveUp($number, $sitenumber, $_SESSION["usertable"]["contestnumber"])) + MSGError("Clarification returned."); + ForceLoad("clar.php"); + } +} + +if (isset($_POST["answer"]) && isset($_POST["Submit"]) && $_POST["Submit"]=="Answer" && is_numeric($_POST["number"]) && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["sitenumber"])) { + if ($_POST["confirmation"]=="confirm") { + + $ans = myhtmlspecialchars($_POST["answer"]); + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + + if (isset($_POST["answerall"])) $type='all'; + else if (isset($_POST["answersite"])) $type='site'; + else $type = 'none'; + + if (trim($ans)=="") { + DBClarGiveUp($number, $sitenumber, $_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"]); + MSGError("Clarification returned."); + } else { + DBChiefUpdateClar($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], + $sitenumber, $number, $ans, $type); + } + } + ForceLoad("clar.php"); +} + +if (!isset($_GET["clarnumber"]) || !isset($_GET["clarsitenumber"]) || + !is_numeric($_GET["clarnumber"]) || !is_numeric($_GET["clarsitenumber"])) { + IntrusionNotify("tried to open the admin/claredit.php with wrong parameters."); + ForceLoad("clar.php"); +} + +$clarsitenumber = myhtmlspecialchars($_GET["clarsitenumber"]); +$clarnumber = myhtmlspecialchars($_GET["clarnumber"]); + +if (($a = DBChiefGetClarToAnswer($clarnumber, $clarsitenumber, + $_SESSION["usertable"]["contestnumber"])) === false) { + MSGError("Another judge got it first."); + ForceLoad("clar.php"); +} + +?> +<br><br><center><b>Use the following fields to answer the clarification: +</b></center> +<form name="form1" method="post" action="claredit.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="0"> + <tr> + <td width="20%" align=right><b>Clarification Site:</b></td> + <td width="80%"> + <input type=hidden name="sitenumber" value="<?php echo $a["sitenumber"]; ?>" /> + <?php echo $a["sitenumber"]; ?> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Clarification Number:</b></td> + <td width="80%"> + <input type=hidden name="number" value="<?php echo $a["number"]; ?>" /> + <?php echo $a["number"]; ?> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Clarification Time:</b></td> + <td width="80%"> + <?php echo dateconvminutes($a["timestamp"]); ?> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Problem:</b></td> + <td width="80%"> + <?php echo $a["problemname"]; ?> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Clarification:</b></td> + <td width="80%"> + <textarea name="message" readonly cols="60" rows="8"><?php echo $a["question"]; ?> + </textarea> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Answer:</b></td> + <td width="80%"> + <textarea name="answer" cols="60" rows="8"><?php echo $a["answer"]; ?></textarea> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Answer to all users in the site</b></td> + <td width="80%"> + <input class=checkbox type=checkbox <?php if ($a["status"] == "answeredsite") echo "checked"; ?> name="answersite" value="yes"> + </td> + </tr> +<!-- + <tr> + <td width="20%" align=right><b>Answer to all users in all sites</b></td> + <td width="80%"> + <input class=checkbox type=checkbox <?php if ($a["status"] == "answeredall") echo "checked"; ?> name="answerall" value="yes"> + </td> + </tr> +--> + </table> + </center> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Answer" onClick="conf()"> + <input type="submit" name="open" value="Open the Clar" onClick="conf()"> + <input type="submit" name="cancel" value="Cancel"> + <input type="submit" name="delete" value="Delete" onClick="conf()"> + <input type="reset" name="Submit2" value="Clear"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/admin/contest.php b/boca-1.5.0/src/admin/contest.php new file mode 100644 index 0000000..361b55b --- /dev/null +++ b/boca-1.5.0/src/admin/contest.php @@ -0,0 +1,252 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +require 'header.php'; + +$contest=$_SESSION["usertable"]["contestnumber"]; + +if(($ct = DBContestInfo($contest)) == null) + ForceLoad("$loc/index.php"); +if ($ct["contestlocalsite"]==$ct["contestmainsite"]) $main=true; else $main=false; + +if (isset($_POST["Submit3"]) && isset($_POST["penalty"]) && is_numeric($_POST["penalty"]) && + isset($_POST["maxfilesize"]) && isset($_POST["mainsite"]) && isset($_POST["name"]) && + $_POST["name"] != "" && isset($_POST["lastmileanswer"]) && is_numeric($_POST["lastmileanswer"]) && + is_numeric($_POST["mainsite"]) && isset($_POST["lastmilescore"]) && is_numeric($_POST["lastmilescore"]) && + isset($_POST["duration"]) && is_numeric($_POST["duration"]) && isset($_POST['localsite']) && + isset($_POST["startdateh"]) && $_POST["startdateh"] >= 0 && $_POST["startdateh"] <= 23 && + isset($_POST["startdatemin"]) && $_POST["startdatemin"] >= 0 && $_POST["startdatemin"] <= 59 && + isset($_POST["startdated"]) && isset($_POST["startdatem"]) && isset($_POST["startdatey"]) && + checkdate($_POST["startdatem"], $_POST["startdated"], $_POST["startdatey"])) { + if ($_POST["confirmation"] == "confirm") { + $param['number']=$contest; + if($_POST["Submit3"] == "Become Main Site") { + $param['mainsite']=$ct["contestlocalsite"]; + } else { + $at = false; + if(!is_numeric($_POST['localsite']) || $_POST['localsite']<=0) $_POST['localsite']=-1; + if($_POST["Submit3"] == "Update Contest and All Sites") $at = true; + $t = mktime ($_POST["startdateh"], $_POST["startdatemin"], 0, + $_POST["startdatem"], $_POST["startdated"], $_POST["startdatey"]); + $param['localsite']=$_POST['localsite']; + $param['name']=$_POST["name"]; + $param['startdate']=$t; + $param['duration']=$_POST["duration"]*60; + $param['lastmileanswer']=$_POST["lastmileanswer"]*60; + $param['lastmilescore']= $_POST["lastmilescore"]*60; + $param['penalty']=$_POST["penalty"]*60; + $param['maxfilesize']=$_POST["maxfilesize"]*1000; + $param['active']=0; + $param['mainsite']=$_POST["mainsite"]; + $param['mainsiteurl']=$_POST["mainsiteurl"]; + $param['unlockkey']=$_POST["unlockkey"]; + + if (isset($_FILES["keyfile"]) && $_FILES["keyfile"]["name"]!="") { + $type=myhtmlspecialchars($_FILES["keyfile"]["type"]); + $size=myhtmlspecialchars($_FILES["keyfile"]["size"]); + $name=myhtmlspecialchars($_FILES["keyfile"]["name"]); + $temp=myhtmlspecialchars($_FILES["keyfile"]["tmp_name"]); + if (!is_uploaded_file($temp)) { + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + if (($ar = file($temp)) === false) { + IntrusionNotify("Unable to open the uploaded file."); + ForceLoad("user.php"); + } + $dd=0; + foreach($ar as $val => $key) { + $key=trim($key); + if($key=='') { + unset($ar[$val]); + continue; + } + if(substr($key,10,5) != '#####') { + MSGError('Invalid key in the file -- not importing any keys'); + $dd=0; + break; + } + if(isset($param['unlockkey']) && $param['unlockkey'] != '') { + $pass=decryptData(substr($key,15),$param['unlockkey'],'includekeys'); + if(substr($pass,0,5) != '#####') { + MSGError('Invalid key in the file -- not importing any keys'); + $dd=0; + break; + } + } + $ar[$val]=$key; + $dd++; + } + if($dd > 0) { + $param['keys']=implode(',',$ar); + MSGError(count($ar) . ' keys are being imported from the file'); + } + } + $param['atualizasites']=$at; + } + DBUpdateContest ($param); + if(strlen($param['unlockkey'])>1) DBGetFullProblemData($_SESSION["usertable"]["contestnumber"],true); + } + ForceLoad("contest.php"); +} +?> +<br> + +<form name="form1" enctype="multipart/form-data" method="post" action="contest.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + function conf2() { + if (confirm("This will restart all start/stop related information in all the sites.\n\ +If you have a contest running, the result is unpredictable. Are you really sure?")) { + document.form1.confirmation.value='confirm'; + } + } + function conf3() { + if (confirm("This will make your site become the main site, that is, this site will\n\ +play an active position in the contest regarding the information\n\ +flow. ARE YOU SURE?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <br><br> + <center> + <table border="0"> + <tr> + <td width="35%" align=right>Contest number:</td> + <td width="65%"> +<?php +echo $contest; +?> + </td> + </tr> + <tr> + <td width="35%" align=right>Name:</td> + <td width="65%"> + <input type="text" <?php if(!$main) echo "readonly"; ?> name="name" value="<?php echo $ct["contestname"]; ?>" size="50" maxlength="50" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Start date:</td> + <td width="65%"> hh:mm + <input type="text" <?php if(!$main) echo "readonly"; ?> name="startdateh" value="<?php echo date("H", $ct["conteststartdate"]); ?>" size="2" maxlength="2" /> + : + <input type="text" <?php if(!$main) echo "readonly"; ?> name="startdatemin" value="<?php echo date("i", $ct["conteststartdate"]); ?>" size="2" maxlength="2" /> + dd/mm/yyyy + <input type="text" <?php if(!$main) echo "readonly"; ?> name="startdated" value="<?php echo date("d", $ct["conteststartdate"]); ?>" size="2" maxlength="2" /> + / + <input type="text" <?php if(!$main) echo "readonly"; ?> name="startdatem" value="<?php echo date("m", $ct["conteststartdate"]); ?>" size="2" maxlength="2" /> + / + <input type="text" <?php if(!$main) echo "readonly"; ?> name="startdatey" value="<?php echo date("Y", $ct["conteststartdate"]); ?>" size="4" maxlength="4" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Duration (in minutes):</td> + <td width="65%"> + <input type="text" name="duration" <?php if(!$main) echo "readonly"; ?> value="<?php echo $ct["contestduration"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Stop answering (in minutes):</td> + <td width="65%"> + <input type="text" name="lastmileanswer" <?php if(!$main) echo "readonly"; ?> value="<?php echo $ct["contestlastmileanswer"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Stop scoreboard (in minutes):</td> + <td width="65%"> + <input type="text" name="lastmilescore" <?php if(!$main) echo "readonly"; ?> value="<?php echo $ct["contestlastmilescore"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Penalty (in minutes):</td> + <td width="65%"> + <input type="text" name="penalty" <?php if(!$main) echo "readonly"; ?> value="<?php echo $ct["contestpenalty"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Max file size allowed for teams (in KB):</td> + <td width="65%"> + <input type="text" name="maxfilesize" <?php if(!$main) echo "readonly"; ?> + value="<?php echo $ct["contestmaxfilesize"]/1000; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr><td width="35%" align=right> + Your PHP config. allows at most:</td> + <td width="65%"> + <?php echo ini_get('post_max_size').'B(max. post) and '.ini_get('upload_max_filesize').'B(max. filesize)'; ?> + </td></tr> + <tr><td width="35%" align=right></td> + <td width="65%"> +<?php echo ini_get('session.gc_maxlifetime').'s of session expiration and ' . ini_get('session.cookie_lifetime') . ' as cookie lifetime (0 means unlimited)'; ?> + </td></tr> + <tr> + <td width="35%" align=right>Main site URL (IP/bocafolder):</td> + <td width="65%"> + <input type="text" name="mainsiteurl" value="<?php echo $ct["contestmainsiteurl"]; ?>" size="40" maxlength="200" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Unlock password (only use it within a <b>secure network</b>):</td> + <td width="65%"> + <input type="password" name="unlockkey" value="" size="40" maxlength="200" /> + <?php if(strlen($ct["contestunlockkey"]) > 1) echo "<b><= has been set</b>"; ?> + </td> + </tr> +<?php if($main) { ?> + <tr> + <td width="35%" align=right>Keys (only use it within a <b>secure network</b>):</td> + <td width="65%"> + <input type="file" name="keyfile" size="40"> + <?php if(strlen($ct["contestkeys"]) > 32) echo "<b><= has been set</b>"; ?> + </td> + </tr> + <?php } ?> + <tr> + <td width="35%" align=right>Contest main site number:</td> + <td width="65%"> + <input type="text" name="mainsite" <?php if(!$main) echo "readonly"; ?> value="<?php echo $ct["contestmainsite"]; ?>" size="4" maxlength="4" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Contest local site number:</td> + <td width="65%"> + <input type="text" name="localsite" <?php if(!$main) echo "readonly"; ?> value="<?php echo $ct["contestlocalsite"]; ?>" size="4" maxlength="4" /> + </td> + </tr> + </table> + </center> + <center> +<?php if($main) { ?> + <input type="submit" name="Submit3" value="Update" onClick="conf()"> + <input type="submit" name="Submit3" value="Update Contest and All Sites" onClick="conf2()"> + <input type="reset" name="Submit4" value="Clear"> +<?php } else { ?> + <input type="submit" name="Submit3" value="Update" onClick="conf()"> + <input type="submit" name="Submit3" value="Become Main Site" onClick="conf3()"> +<?php } ?> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/admin/export.php b/boca-1.5.0/src/admin/export.php new file mode 100644 index 0000000..2682c94 --- /dev/null +++ b/boca-1.5.0/src/admin/export.php @@ -0,0 +1,121 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +//Change list +// 15/June/2011 by cassio@ime.usp.br: created based on import.php +require('header.php'); + +if(isset($_POST["Submit"]) || isset($_POST['Submit1'])) { + if ($_POST["confirmation"] == "confirm" && isset($_POST['localsite']) && is_numeric($_POST['localsite']) && + isset($_POST['challenge']) && isset($_POST['password'])) { + $localsite=$_POST['localsite']; + + header ("Content-transfer-encoding: binary\n"); + header ("Content-type: application/force-download"); +//header ("Content-type: application/octet-stream"); +//if (strstr($_SERVER["HTTP_USER_AGENT"], "MSIE")) +// header("Content-Disposition: filename=" .$_GET["filename"]); // For IE +//else + header ("Content-Disposition: attachment; filename=export.dat"); + ob_end_flush(); + $reduced = false; + if(isset($_POST["Submit"]) && $_POST['Submit']=="Reduced Export") { + $reduced = true; + } + + $fromsite = $localsite; + $siteinfo = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$fromsite); + $scores = explode(",", $siteinfo['siteglobalscore']); + if(count($scores)==0 || (count($scores)==1 && !is_numeric($scores[0]))) $scores=array($fromsite); + $judges = explode(",", $siteinfo['sitejudging']); + if(count($judges)==0 || (count($judges)==1 && !is_numeric($judges[0]))) $judges=array($fromsite); + $scores = array_unique(array_merge($scores,$judges)); + if(in_array(0,$scores)) $scores=null; + + $xml = generateXML($_SESSION["usertable"]["contestnumber"],$localsite,$scores,$reduced); + if(isset($_POST['nopassword']) && $_POST['nopassword']=='true') + echo $xml; + else + echo rawurlencode($_POST['challenge']) . " " . encryptData($xml,($_POST['password'])); + exit; + } +} +ob_end_flush(); +?> +<br> +<body onload="document.form1.name.focus()"> +<script language="JavaScript" src="../sha256.js"></script> +<script language="JavaScript"> +function computeHASH() +{ + var passHASH; + if(document.form1.password.value == '') { + document.form1.nopassword.value = 'true'; + } else { + passHASH = js_myhash(js_myhash(document.form1.password.value)+document.form1.challenge.value); + document.form1.password.value = passHASH; + } +} +</script> + +<form name="form1" enctype="multipart/form-data" method="post" action="export.php"> + <input type="hidden" name="confirmation" value="noconfirm" /> + <input type="hidden" name="noflush" value="noflush" /> + <input type="hidden" name="nopassword" value="false" /> + <center> + <table border="0"> + <tr> + <td width="50%" align=right>Local site number:</td> + <td width="50%"> + <input type="text" name="localsite" size="10"> + </td> + </tr> + <tr><td width="50%" align=right>Challenge string:</td><td width="50%"><input type="text" name="challenge" size="20"></td></tr> +<!-- + <tr> + <td width="50%" align=right>Import file:</td> + <td width="50%"> + <input type="file" name="importfile" size="40"> + </td> + </tr> +--> + <tr> + <td width="50%" align=right>Encryption key:</td> + <td width="50%"> + <input type="password" name="password"> + </td> + </tr> + </table> + </center> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + computeHASH(); + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Reduced Export" onClick="conf()"> + <input type="submit" name="Submit1" value="Full Export" onClick="conf()"> + <input type="reset" name="Submit2" value="Clear"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/admin/files.php b/boca-1.5.0/src/admin/files.php new file mode 100644 index 0000000..16f0f2d --- /dev/null +++ b/boca-1.5.0/src/admin/files.php @@ -0,0 +1,78 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("$loc/index.php"); +if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("$loc/index.php"); + +if (isset($_GET["delete"]) && is_numeric($_GET["delete"])) { + DBBkpDelete($_GET["delete"],$_GET["usersitenumber"],$_SESSION["usertable"]["contestnumber"], $_GET["usernumber"],$_SESSION["usertable"]["username"]); + ForceLoad("files.php"); +} +?> +<br> + <script language="javascript"> + function conf2(url) { + if (confirm("Confirm DELETION of file?")) { + document.location=url; + } else { + document.location='files.php'; + } + } + </script> +<table width="100%" border=1> + <tr> + <td><b>Bkp #</b></td> + <td><b>Time</b></td> + <td><b>User(Site)</b></td> + <td><b>File</b></td> + <td><b>Status</b></td> + </tr> +<?php +$run = DBUserBkps($_SESSION["usertable"]["contestnumber"], -1, -1); + +for ($i=0; $i<count($run); $i++) { + echo " <tr>\n"; + if(strpos($run[$i]["status"],"deleted")!==false) + echo " <td nowrap>" . $run[$i]["number"] . "</td>\n"; + else + echo " <td nowrap><a href=\"javascript:conf2('files.php?delete=" . $run[$i]["number"] . + "&usernumber=" .$run[$i]["usernumber"]. "&usersitenumber=" .$run[$i]["usersitenumber"]. "')\">" . $run[$i]["number"] . "</a></td>\n"; + + echo " <td nowrap>" . dateconvsimple($run[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $run[$i]["usernumber"] . " (" . $run[$i]["usersitenumber"] . ")</td>\n"; + $if = rawurlencode($run[$i]["filename"]); + if($run[$i]["status"]=="active") { + echo "<td nowrap><a href=\"../filedownload.php?". filedownload($run[$i]["oid"],$run[$i]["filename"]) . "\">"; + echo $run[$i]["filename"] . "</a>"; + } else echo "<td>" . $run[$i]["filename"]; + echo " (" . $run[$i]["size"] . " bytes)"; + echo "</td>\n"; + echo "<td>" . $run[$i]["status"] . "</td>\n"; + echo " </tr>\n"; + +} +echo "</table>"; +if (count($run) == 0) echo "<br><center><b><font color=\"#ff0000\">NO BACKUPS AVAILABLE</font></b></center>"; + +?> +</body> +</html> diff --git a/boca-1.5.0/src/admin/header.php b/boca-1.5.0/src/admin/header.php new file mode 100644 index 0000000..c308059 --- /dev/null +++ b/boca-1.5.0/src/admin/header.php @@ -0,0 +1,88 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br + +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +header ("Content-Type: text/html; charset=utf-8"); +session_start(); +if(!isset($_POST['noflush'])) + ob_end_flush(); +//$loc = $_SESSION['loc']; +//$locr = $_SESSION['locr']; +$loc = $locr = ".."; +$runphp = "run.php"; +$runeditphp = "runedit.php"; + +require_once("$locr/globals.php"); +require_once("$locr/db.php"); + +if(!isset($_POST['noflush'])) { + require_once("$locr/version.php"); + echo "<html><head><title>Admin's Page</title>\n"; + echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"; + echo "<link rel=stylesheet href=\"$loc/Css.php\" type=\"text/css\">\n"; +} + +//echo "<meta http-equiv=\"refresh\" content=\"60\" />"; +if(!ValidSession()) { + InvalidSession("admin/index.php"); + ForceLoad("$loc/index.php"); +} +if($_SESSION["usertable"]["usertype"] != "admin") { + IntrusionNotify("admin/index.php"); + ForceLoad("$loc/index.php"); +} + +if(!isset($_POST['noflush'])) { + echo "</head><body><table border=1 width=\"100%\">\n"; + echo "<tr><td nowrap bgcolor=\"eeee00\" align=center>"; + echo "<img src=\"../images/smallballoontransp.png\" alt=\"\">"; + echo "<font color=\"#000000\">BOCA</font>"; + echo "</td><td bgcolor=\"#eeee00\" width=\"99%\">\n"; + echo "Username: " . $_SESSION["usertable"]["userfullname"] . " (site=".$_SESSION["usertable"]["usersitenumber"].")<br>\n"; + list($clockstr,$clocktype)=siteclock(); + echo "</td><td bgcolor=\"#eeee00\" align=center nowrap> ".$clockstr." </td></tr>\n"; + echo "</table>\n"; + echo "<table border=0 width=\"100%\" align=center>\n"; + echo " <tr>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=run.php>Runs</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=score.php>Score</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=clar.php>Clarifications</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=user.php>Users</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=problem.php>Problems</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=language.php>Languages</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=answer.php>Answers</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=export.php>Export</a></td>\n"; +//echo " </tr></table><hr><table border=0 width=\"100%\" align=center><tr>\n"; + echo " </tr><tr>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=task.php>Tasks</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=site.php>Site</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=contest.php>Contest</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=log.php>Logs</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=report.php>Reports</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=files.php>Backups</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=option.php>Options</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=$loc/index.php>Logout</a></td>\n"; + echo " </tr>\n"; + echo "</table>\n"; +} +?> diff --git a/boca-1.5.0/src/admin/index.php b/boca-1.5.0/src/admin/index.php new file mode 100644 index 0000000..1b35a4c --- /dev/null +++ b/boca-1.5.0/src/admin/index.php @@ -0,0 +1,22 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require_once('header.php'); +?> +</body> +</html> diff --git a/boca-1.5.0/src/admin/language.php b/boca-1.5.0/src/admin/language.php new file mode 100644 index 0000000..b2a7481 --- /dev/null +++ b/boca-1.5.0/src/admin/language.php @@ -0,0 +1,124 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); + +if (isset($_GET["delete"]) && is_numeric($_GET["delete"])) { + $param["number"] = $_GET["delete"]; + DBDeleteLanguage ($_SESSION["usertable"]["contestnumber"],$param); + ForceLoad("language.php"); +} + +if (isset($_POST["Submit3"]) && isset($_POST["langnumber"]) && is_numeric($_POST["langnumber"]) && + isset($_POST["langname"]) && $_POST["langname"] != "") { + if ($_POST["confirmation"] == "confirm") { + $param = array(); + $param['number'] = $_POST['langnumber']; + $param['name'] = $_POST['langname']; + $param['extension'] = $_POST['langextension']; + DBNewLanguage ($_SESSION["usertable"]["contestnumber"], $param); + } + ForceLoad("language.php"); +} +?> +<br> + <script language="javascript"> + function conf2(url) { + if (confirm("Confirm the DELETION of the LANGUAGE and ALL data associated to it (including the SUBMISSIONS)?")) { + if (confirm("Are you REALLY sure about what you are doing? DATA CANNOT BE RECOVERED!")) { + document.location=url; + } else { + document.location='language.php'; + } + } else { + document.location='language.php'; + } + } + </script> +<table width="100%" border=1> + <tr> + <td><b>Language #</b></td> + <td><b>Name</b></td> + <td><b>Extension</b></td> + </tr> +<?php +$lang = DBGetLanguages($_SESSION["usertable"]["contestnumber"]); +$cf = globalconf(); +for ($i=0; $i<count($lang); $i++) { + echo " <tr>\n"; + echo " <td nowrap><a href=\"javascript: conf2('language.php?delete=" . $lang[$i]["number"] . "')\">" . + $lang[$i]["number"] . "</a></td>\n"; + echo " <td nowrap>" . $lang[$i]["name"] . "</td>\n"; + echo " <td nowrap>" . $lang[$i]["extension"] . "</td>\n"; + echo " </tr>\n"; +} +echo "</table>"; +if (count($lang) == 0) echo "<br><center><b><font color=\"#ff0000\">NO LANGUAGES DEFINED</font></b></center>"; + +?> + +<br><br><center><b>Clicking on a language number will DELETE it.<br> +WARNING: deleting a language will remove EVERYTHING related to it.<br> +It is NOT recommended to change anything while the contest is running.<br> +</b></center> + +<form name="form1" enctype="multipart/form-data" method="post" action="language.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> +<b>To insert/edit a language, enter the data below.<br> +Note that any changes will overwrite the already defined data.<br><br> +</b> + <table border="0"> + <tr> + <td width="35%" align=right>Number:</td> + <td width="65%"> + <input type="text" name="langnumber" value="" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Name:</td> + <td width="65%"> + <input type="text" name="langname" value="" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Extension:</td> + <td width="65%"> + <input type="text" name="langextension" value="" size="20" maxlength="20" /> + </td> + </tr> + </table> + </center> + <center> + <input type="submit" name="Submit3" value="Send" onClick="conf()"> + <input type="reset" name="Submit4" value="Clear"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/admin/log.php b/boca-1.5.0/src/admin/log.php new file mode 100644 index 0000000..ff915ea --- /dev/null +++ b/boca-1.5.0/src/admin/log.php @@ -0,0 +1,76 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +if(isset($_GET["order"])) +$order = myhtmlspecialchars($_GET["order"]); +else $order=''; +if(isset($_GET["user"])) +$user = myhtmlspecialchars($_GET["user"]); +else $user=''; +if(isset($_GET["site"])) +$site = myhtmlspecialchars($_GET["site"]); +else $site=''; +if(isset($_GET["type"])) +$type = myhtmlspecialchars($_GET["type"]); +else $type=''; +if(isset($_GET["ip"])) +$ip = myhtmlspecialchars($_GET["ip"]); +else $ip=''; +$get="&order=${order}&user=${user}&site=${site}&type=${type}&ip=${ip}"; +if (isset($_GET["limit"]) && $_GET["limit"]>0) + $limit = myhtmlspecialchars($_GET["limit"]); +else $limit = 50; +$log = DBGetLogs($order, $_SESSION["usertable"]["contestnumber"], + $site, $user, $type, $ip, $limit); +?> +<br> +<table width="100%" border=1> + <tr> + <td><b><a href="log.php?order=site&limit=<?php echo $limit; ?>">Site</a></b></td> + <td nowrap><b><a href="log.php?order=user&limit=<?php echo $limit; ?>">User #</a></b></td> + <td><b><a href="log.php?order=ip&limit=<?php echo $limit; ?>">IP</a></b></td> + <td><b><a href="log.php?order=type&limit=<?php echo $limit; ?>">Type</a></b></td> + <td><b>Date</b></td> + <td><b>Description</b></td> + <td><b>Status</b></td> + </tr> +<?php +for ($i=0; $i<count($log); $i++) { + echo " <tr>\n"; + echo " <td nowrap><a href=\"log.php?site=" . $log[$i]["site"] . "&limit=$limit\">" . $log[$i]["site"] . "</a></td>\n"; + echo " <td nowrap><a href=\"log.php?user=" . $log[$i]["user"] . "&limit=$limit\">" . $log[$i]["user"] . "</a></td>\n"; + echo " <td nowrap><a href=\"log.php?ip=" . $log[$i]["ip"] . "&limit=$limit\">" . $log[$i]["ip"] . "</a></td>\n"; + echo " <td nowrap><a href=\"log.php?type=" . $log[$i]["type"] . "&limit=$limit\">" . $log[$i]["type"] . "</a></td>\n"; + echo " <td nowrap>" . dateconv($log[$i]["date"]) . "</td>\n"; + echo " <td nowrap>" . $log[$i]["data"] . "</td>\n"; + echo " <td nowrap>" . $log[$i]["status"] . "</td>\n"; + echo "</tr>\n"; +} +echo "</table>\n"; + +?> +<br> +<center> +<a href="log.php?limit=50<?php echo $get; ?>">50</a> +<a href="log.php?limit=200<?php echo $get; ?>">200</a> +<a href="log.php?limit=1000<?php echo $get; ?>">1000</a> +<a href="log.php?limit=1000000<?php echo $get; ?>">no limit</a> +</body> +</html> diff --git a/boca-1.5.0/src/admin/option.php b/boca-1.5.0/src/admin/option.php new file mode 100644 index 0000000..81e5879 --- /dev/null +++ b/boca-1.5.0/src/admin/option.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +require('../optionlower.php'); +?> diff --git a/boca-1.5.0/src/admin/problem.php b/boca-1.5.0/src/admin/problem.php new file mode 100644 index 0000000..d55ff63 --- /dev/null +++ b/boca-1.5.0/src/admin/problem.php @@ -0,0 +1,262 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +require('header.php'); +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); + +if (isset($_GET["delete"]) && is_numeric($_GET["delete"]) && isset($_GET["input"])) { + $param = array(); + $param['number']=$_GET["delete"]; + $param['inputfilename']=$_GET["input"]; + if(!DBDeleteProblem ($_SESSION["usertable"]["contestnumber"], $param)) { + MSGError('Error deleting problem'); + LogError('Error deleting problem'); + } + ForceLoad("problem.php"); +} + +if (isset($_POST["Submit3"]) && isset($_POST["problemnumber"]) && is_numeric($_POST["problemnumber"]) && + isset($_POST["problemname"]) && $_POST["problemname"] != "") { + if ($_POST["confirmation"] == "confirm") { + if ($_FILES["probleminput"]["name"] != "") { + $type=myhtmlspecialchars($_FILES["probleminput"]["type"]); + $size=myhtmlspecialchars($_FILES["probleminput"]["size"]); + $name=myhtmlspecialchars($_FILES["probleminput"]["name"]); + $temp=myhtmlspecialchars($_FILES["probleminput"]["tmp_name"]); + if (!is_uploaded_file($temp)) { + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + } else $name = ""; + + $param = array(); + $param['number'] = $_POST["problemnumber"]; + $param['name'] = $_POST["problemname"]; + $param['inputfilename'] = $name; + $param['inputfilepath'] = $temp; + $param['fake'] = 'f'; + $param['colorname'] = $_POST["colorname"]; + $param['color'] = $_POST["color"]; + if($param['color']=='') $param['color']=-1; + DBNewProblem ($_SESSION["usertable"]["contestnumber"], $param); + } + ForceLoad("problem.php"); +} +?> +<br> + <script language="javascript"> + function conf2(url) { + if (confirm("Confirm the DELETION of the PROBLEM and ALL data associated to it (including the SUBMISSIONS)?")) { + if (confirm("Are you REALLY sure about what you are doing? DATA CANNOT BE RECOVERED!")) { + document.location=url; + } else { + document.location='problem.php'; + } + } else { + document.location='problem.php'; + } + } + </script> +<table width="100%" border=1> + <tr> + <td><b>Problem #</b></td> + <td><b>Short Name</b></td> + <td><b>Fullname</b></td> + <td><b>Basename</b></td> + <td><b>Descfile</b></td> + <td><b>Package file</b></td> +<!-- <td><b>Compare file</b></td> + <td><b>Timelimit</b></td>--> + <td><b>Color</b></td> + </tr> +<?php + $prob = DBGetFullProblemData($_SESSION["usertable"]["contestnumber"],true); +for ($i=0; $i<count($prob); $i++) { + echo " <tr>\n"; + if($prob[$i]["fake"]!='t') { + echo " <td nowrap><a href=\"javascript: conf2('problem.php?delete=" . $prob[$i]["number"] . "&input=" . rawurlencode($prob[$i]["inputfilename"]) . + "')\">" . $prob[$i]["number"] . "</a></td>\n"; + } else { + echo " <td nowrap>" . $prob[$i]["number"] . " (fake)</td>\n"; + } + echo " <td nowrap>" . $prob[$i]["name"] . "</td>\n"; + echo " <td nowrap>" . $prob[$i]["fullname"] . " </td>\n"; + echo " <td nowrap>" . $prob[$i]["basefilename"] . " </td>\n"; + if (isset($prob[$i]["descoid"]) && $prob[$i]["descoid"] != null) { + echo " <td nowrap><a href=\"../filedownload.php?" . filedownload($prob[$i]["descoid"], $prob[$i]["descfilename"]) . "\">" . + basename($prob[$i]["descfilename"]) . "</td>\n"; + } + else + echo " <td> </td>\n"; + if ($prob[$i]["inputoid"] != null) { + $tx = $prob[$i]["inputhash"]; + echo " <td nowrap><a href=\"../filedownload.php?" . filedownload($prob[$i]["inputoid"] ,$prob[$i]["inputfilename"]) ."\">" . + $prob[$i]["inputfilename"] . "</a> " . + "<img title=\"hash: $tx\" alt=\"$tx\" width=\"25\" src=\"../images/bigballoontransp-hash.png\" />" . + "</td>\n"; + } + else + echo " <td nowrap> </td>\n"; +/* + if ($prob[$i]["soloid"] != null) { + $tx = $prob[$i]["solhash"]; + echo " <td nowrap><a href=\"../filedownload.php?" . filedownload($prob[$i]["soloid"],$prob[$i]["solfilename"]) ."\">" . + $prob[$i]["solfilename"] . "</a> ". + "<img title=\"hash: $tx\" alt=\"$tx\" width=\"25\" src=\"../images/bigballoontransp-hash.png\" />" . + "</td>\n"; + } + else + echo " <td nowrap> </td>\n"; + if ($prob[$i]["timelimit"]!="") + echo " <td nowrap>" . $prob[$i]["timelimit"] . "</td>\n"; + else + echo " <td nowrap> </td>\n"; +*/ + if ($prob[$i]["color"]!="") { + echo " <td nowrap>" . $prob[$i]["colorname"] . + "<img title=\"".$prob[$i]["color"]."\" alt=\"".$prob[$i]["colorname"]."\" width=\"25\" src=\"" . + balloonurl($prob[$i]["color"]) . "\" /></td>\n"; + } else + echo " <td nowrap> </td>\n"; + echo " </tr>\n"; +} +echo "</table>"; +if (count($prob) == 0) echo "<br><center><b><font color=\"#ff0000\">NO PROBLEMS DEFINED</font></b></center>"; + +?> + +<br><br><center><b>Clicking on a problem number will delete it.<br> +WARNING: deleting a problem will remove EVERYTHING related to it.<br> +It is NOT recommended to change anything while the contest is running.<br> +To import a problem, fill in the following fields.<br> +To replace the data of a problem, proceed as if it did not exist (data will be replaced without removing it).</b></center> + +<form name="form1" enctype="multipart/form-data" method="post" action="problem.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <script language="javascript"> + function conf() { + if(document.form1.problemname.value=="") { + alert('Sorry, mandatory fields are empty'); + } else { +/* + var s1 = String(document.form1.problemdesc.value); + var l = s1.length; + if(l >= 3 && (s1.substr(l-3,3).toUpperCase()==".IN" || + s1.substr(l-4,4).toUpperCase()==".OUT" || + s1.substr(l-4,4).toUpperCase()==".SOL" || + s1.substr(l-2,2).toUpperCase()==".C" || + s1.substr(l-2,2).toUpperCase()==".H" || + s1.substr(l-3,3).toUpperCase()==".CC" || + s1.substr(l-3,3).toUpperCase()==".GZ" || + s1.substr(l-4,4).toUpperCase()==".CPP" || + s1.substr(l-4,4).toUpperCase()==".HPP" || + s1.substr(l-4,4).toUpperCase()==".ZIP" || + s1.substr(l-4,4).toUpperCase()==".TGZ" || + s1.substr(l-5,5).toUpperCase()==".JAVA")) { + alert('Description file has invalid extension: ...'+s1.substr(l-3,3)); + } else { +*/ + var s2 = String(document.form1.probleminput.value); + if(s2.length > 4) { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } else { + alert('File package must be given'); + } + } + } + </script> + <center> + <table border="0"> + <tr> + <td width="35%" align=right>Number:</td> + <td width="65%"> + <input type="text" name="problemnumber" value="" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Short Name (usually a letter):</td> + <td width="65%"> + <input type="text" name="problemname" value="" size="20" maxlength="20" /> + </td> + </tr> +<!-- + <tr> + <td width="35%" align=right>Problem Fullname:</td> + <td width="65%"> + <input type="text" name="fullname" value="" size="50" maxlength="100" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Problem Basename (a.k.a. name of class expected to have the main):</td> + <td width="65%"> + <input type="text" name="basename" value="" size="50" maxlength="100" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Description file (PDF, txt, ...):</td> + <td width="65%"> + <input type="file" name="problemdesc" value="" size="40" /> + </td> + </tr> +--> + <tr> + <td width="35%" align=right>Problem package (ZIP):</td> + <td width="65%"> + <input type="file" name="probleminput" value="" size="40" /> + </td> + </tr> +<!-- + <tr> + <td width="35%" align=right>Compare file archive (ZIP):</td> + <td width="65%"> + <input type="file" name="problemsol" value="" size="40" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Timelimit (in sec):</td> + <td width="65%"> + <input type="text" name="timelimit" value="" size="10" /> +(optional: use a , followed by the number of repetitions to run) + </td> + </tr> +--> + <tr> + <td width="35%" align=right>Color name:</td> + <td width="65%"> + <input type="text" name="colorname" value="" size="40" maxlength="100" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Color (RGB HTML format):</td> + <td width="65%"> + <input type="text" name="color" value="" size="6" maxlength="6" /> + </td> + </tr> + </table> + </center> + <center> + <input type="submit" name="Submit3" value="Send" onClick="conf()"> + <input type="reset" name="Submit4" value="Clear"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/admin/report.php b/boca-1.5.0/src/admin/report.php new file mode 100644 index 0000000..bb1fc34 --- /dev/null +++ b/boca-1.5.0/src/admin/report.php @@ -0,0 +1,89 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +require 'header.php'; + +if (isset($_GET)) { +} +?> +<br><br> + <center> +<?php +// echo "<b>Logs</b><br /><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/score.php?p=2', ". + "'Complete Scoreboard','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Scoreboard</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/score.php?p=0', ". + "'Complete Scoreboard','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Detailed Scoreboard</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/score.php?p=0&hor=0', ". + "'Complete Scoreboard','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Interactive Scoreboard</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/score.php?p=1', ". + "'Public Scoreboard','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Delayed Scoreboard</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/run.php', ". + "'Run List','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Run List</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/clar.php', ". + "'Clarification List','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Clarification List</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/task.php', ". + "'Task List','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Task List</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/site.php', ". + "'Start/Stop Logs','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Site Start/Stop Logs</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/icpc.php', ". + "'ICPC File','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">ICPC File</a><br />\n"; + + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/stat.php', ". + "'Problem Statistics','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Statistics</a><br />\n"; + +/* + echo "<br /><br />\n"; + echo "<b>Statistics</b><br /><br />\n"; + + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/statproblem.php', ". + "'Problem Statistics','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Problems</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/statanswer.php', ". + "'Answer Statistics','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Answers</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/statuser.php', ". + "'User Statistics','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Users</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/statlanguage.php', ". + "'Language Statistics','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Languages</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/statrun.php', ". + "'Run Statistics','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Runs</a><br />\n"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('report/statclar.php', ". + "'Clarification Statistics','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Clarifications</a><br />\n"; +*/ +?> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/admin/report/clar.php b/boca-1.5.0/src/admin/report/clar.php new file mode 100644 index 0000000..66bd4cd --- /dev/null +++ b/boca-1.5.0/src/admin/report/clar.php @@ -0,0 +1,82 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +require('header.php'); +?> +<br> +<center><h2>Clarification List</h2></center> +<table width="100%" border=1> + <tr> + <td><b>#</b></td> + <td><b>Site</b></td> + <td><b>User</b></td> + <td><b>Time</b></td> + <td><b>Problem</b></td> + <td><b>Status</b></td> + <td><b>Judge (Site)</b></td> + <td><b>Question</b></td> + <td><b>Answer</b></td> + </tr> +<?php +$s = $st; + +// forca aparecer as clars do proprio site +if (trim($s["sitejudging"])!="") $s["sitejudging"].=",".$_SESSION["usertable"]["usersitenumber"]; +else $s["sitejudging"]=$_SESSION["usertable"]["usersitenumber"]; + +$clar = DBAllClarsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"], 'normal'); + +for ($i=0; $i<count($clar); $i++) { + echo " <tr>\n"; + echo " <td nowrap>" . $clar[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . $clar[$i]["site"] . "</td>\n"; + echo " <td nowrap>" . $clar[$i]["user"] . "</td>\n"; + echo " <td nowrap>" . dateconvminutes($clar[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $clar[$i]["problem"] . "</td>\n"; + + echo " <td nowrap>" . $clar[$i]["status"] . "</td>\n"; + if ($clar[$i]["judge"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $clar[$i]["judgesite"], $clar[$i]["judge"]); + echo " <td nowrap>" . $u["username"] . " (" . $clar[$i]["judgesite"] . ")</td>\n"; + } + else + echo " <td> </td>\n"; + + if ($clar[$i]["question"] == "") $clar[$i]["question"] = " "; + + echo " <td>"; +// echo "<pre>" . $clar[$i]["question"] . "</pre>"; +// echo $clar[$i]["question"]; + echo " <textarea name=\"m$i\" cols=\"60\" rows=\"8\" readonly>".$clar[$i]["question"]."</textarea>\n"; + echo "</td>\n"; + if (trim($clar[$i]["answer"]) == "") $clar[$i]["answer"] = "Not answered yet"; + echo " <td>"; +// echo " <pre>" . $clar[$i]["answer"] . "</pre>"; +// echo $clar[$i]["answer"]; + echo " <textarea name=\"a$i\" cols=\"60\" rows=\"8\" readonly>".$clar[$i]["answer"]."</textarea>\n"; + echo "</td>\n"; + + echo " </tr>\n"; +} + +echo "</table>"; +if (count($clar) == 0) echo "<br><center><b><font color=\"#ff0000\">NO CLARIFICATIONS AVAILABLE</font></b></center>"; + +include("$locr/footnote.php"); +?> diff --git a/boca-1.5.0/src/admin/report/header.php b/boca-1.5.0/src/admin/report/header.php new file mode 100644 index 0000000..1d191de --- /dev/null +++ b/boca-1.5.0/src/admin/report/header.php @@ -0,0 +1,65 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +header ("Content-Type: text/html; charset=utf-8"); +session_start(); +ob_end_flush(); +//$locr = $_SESSION['locr']; +//$loc = $_SESSION['loc']; +$loc = $locr = "../.."; + +require $locr.'/version.php'; +require_once($locr . "/globals.php"); +if(!ValidSession()) { + InvalidSession($_SERVER['PHP_SELF']); + ForceLoad($loc."/index.php"); +} +if($_SESSION["usertable"]["usertype"] != "admin") { + IntrusionNotify($_SERVER['PHP_SELF']); + ForceLoad($loc."/index.php"); +} + +require_once($locr."/db.php"); +require_once($locr."/freport.php"); + +echo "<html><head><title>Report Page</title>\n"; +echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"; + +echo "<link rel=stylesheet href=\"$loc/Css.php\" type=\"text/css\">\n"; + +$contest=$_SESSION["usertable"]["contestnumber"]; +if(($ct = DBContestInfo($contest)) == null) + ForceLoad($loc."/index.php"); +$site=$_SESSION["usertable"]["usersitenumber"]; +if(($st = DBSiteInfo($contest,$site)) == null) + ForceLoad($loc."/index.php"); + +echo "</head><body><table border=1 width=\"100%\">\n"; +echo "<tr><td bgcolor=\"eeee00\" nowrap align=center>"; +echo "<img src=\"$loc/images/smallballoontransp.png\" alt=\"\">"; +echo "<font color=\"#ffffff\"><a href=\"http://www.ime.usp.br/~cassio/boca/\">BOCA</a></font>"; +echo "</td><td bgcolor=\"#eeee00\" width=\"99%\">\n"; +echo $ct["contestname"] . " - " . $st["sitename"] . "</td>\n"; +echo "</tr></table>\n"; +?> diff --git a/boca-1.5.0/src/admin/report/icpc.php b/boca-1.5.0/src/admin/report/icpc.php new file mode 100644 index 0000000..1bf2b86 --- /dev/null +++ b/boca-1.5.0/src/admin/report/icpc.php @@ -0,0 +1,46 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA System (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +//Last updated 10/jul/2012 by cassio@ime.usp.br + +require('header.php'); + +$score = DBScore($_SESSION["usertable"]["contestnumber"], false, -1, $st["siteglobalscore"]); + +echo "<h2>ICPC Output</h2>"; +echo "<pre>"; +$n=0; +$class=1; +while(list($e, $c) = each($score)) { + if(isset($score[$e]["site"]) && isset($score[$e]["user"])) { + $r = DBUserInfo($_SESSION["usertable"]["contestnumber"], + $score[$e]["site"], $score[$e]["user"]); + echo $r["usericpcid"] . ","; + echo $class++ . ","; + echo $score[$e]["totalcount"] . ","; + echo $score[$e]["totaltime"] . ","; + + if($score[$e]["first"]) + echo $score[$e]["first"] . "\n"; + else echo "0\n"; + $n++; + } +} +echo "</pre>"; +?> +<?php include("$locr/footnote.php"); ?> + diff --git a/boca-1.5.0/src/admin/report/linechart.php b/boca-1.5.0/src/admin/report/linechart.php new file mode 100644 index 0000000..fa47b17 --- /dev/null +++ b/boca-1.5.0/src/admin/report/linechart.php @@ -0,0 +1,45 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +session_start(); +$locr = $_SESSION['locr']; +$loc = $_SESSION['loc']; + +require_once($locr . "/libchart/libchart.php"); +header ("Content-type: image/png"); +ob_end_flush(); + +$v = explode(chr(1),rawurldecode($_GET['dados']),100); + +$chart = new VerticalChart(1000, 300); + +$chart->setUpperBound($v[1]); + +for($i=2;$i<count($v); $i+=2) + $chart->addPoint(new Point($v[$i], $v[$i+1])); + +$chart->setTitle($v[0]); +$chart->setLogo($locr. "/images/poweredbyboca.png"); +$chart->render(); +?> diff --git a/boca-1.5.0/src/admin/report/piechart.php b/boca-1.5.0/src/admin/report/piechart.php new file mode 100644 index 0000000..18d8d04 --- /dev/null +++ b/boca-1.5.0/src/admin/report/piechart.php @@ -0,0 +1,60 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +session_start(); +$locr = $_SESSION['locr']; +$loc = $_SESSION['loc']; + +require_once($locr . "/libchart/libchart.php"); +header("Content-type: image/png"); +ob_end_flush(); + +$v = explode(chr(1),rawurldecode($_GET['dados']),100); +$cor = null; +if(isset($_GET['color'])) + $cor = explode("-",rawurldecode($_GET['color']),100); + +if(count($v)/2 > 8) + $chart = new PieChart(450, 300); +else + $chart = new PieChart(400, 250); + +if(isset($_GET['order'])) $chart->order=true; + +for($i=1;$i<count($v); $i+=2) { + $color = null; + if($cor != null) { + $r = hexdec( substr($cor[($i-1)/2], 0, 2) ); + $g = hexdec( substr($cor[($i-1)/2], 2, 2) ); + $b = hexdec( substr($cor[($i-1)/2], 4, 2) ); + $color = array($r, $g, $b); + } + $chart->addPoint(new Point($v[$i], $v[$i+1], $color)); +} + +$chart->setTitle($v[0]); +$chart->setLogo($locr. "/images/poweredbyboca.png"); +$chart->render(); + +?> diff --git a/boca-1.5.0/src/admin/report/run.php b/boca-1.5.0/src/admin/report/run.php new file mode 100644 index 0000000..422200d --- /dev/null +++ b/boca-1.5.0/src/admin/report/run.php @@ -0,0 +1,93 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +require('header.php'); +?> +<br> +<center><h2>Run List</h2></center> +<table width="100%" border=1> + <tr> + <td><b>#</b></td> + <td><b>Site</b></td> + <td><b>User</b></td> + <td><b>Time</b></td> + <td><b>Problem</b></td> + <td><b>Language</b></td> + <td><b>Filename</b></td> + <td><b>Status</b></td> + <td><b>Judge (Site)</b></td> + <td><b>Answer</b></td> + </tr> +<?php +$s = $st; +// forca aparecer as runs do proprio site +if (trim($s["sitejudging"])!="") $s["sitejudging"].=",".$_SESSION["usertable"]["usersitenumber"]; +else $s["sitejudging"]=$_SESSION["usertable"]["usersitenumber"]; + +$run = DBAllRunsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"], 'normal'); + +for ($i=0; $i<count($run); $i++) { + echo " <tr>\n"; + echo " <td nowrap>" . $run[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . $run[$i]["site"] . "</td>\n"; + if ($run[$i]["user"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["site"], $run[$i]["user"]); + echo " <td nowrap>" . $u["userfullname"] . "</td>\n"; + } + echo " <td nowrap>" . dateconvminutes($run[$i]["timestamp"]) . "</td>\n"; + + if($run[$i]["status"] == "deleted") { + echo "<td> </td>\n"; + echo "<td> </td>\n"; + echo "<td> </td>\n"; + echo " <td nowrap>" . $run[$i]["status"] . "</td>\n"; + if ($run[$i]["judge"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["judgesite"], $run[$i]["judge"]); + echo " <td nowrap>" . $u["username"] . " (" . $run[$i]["judgesite"] . ")</td>\n"; + } else + echo " <td> </td>\n"; + echo "<td> </td>\n"; + echo "</tr>"; + continue; + } + + echo " <td nowrap>" . $run[$i]["problem"]; + if($run[$i]["colorname"] != "") + echo "(".$run[$i]["colorname"].")"; + echo "</td>\n"; + echo " <td nowrap>" . $run[$i]["language"] . "</td>\n"; + echo " <td nowrap>" . $run[$i]["filename"] . "</td>\n"; + + echo " <td nowrap>" . $run[$i]["status"] . "</td>\n"; + if ($run[$i]["judge"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["judgesite"], $run[$i]["judge"]); + echo " <td nowrap>" . $u["username"] . " (" . $run[$i]["judgesite"] . ")</td>\n"; + } else + echo " <td> </td>\n"; + + if ($run[$i]["answer"] == "") $run[$i]["answer"] = " "; + echo " <td>" . $run[$i]["answer"] . "</td>\n"; + echo " </tr>\n"; +} + +echo "</table>"; +if (count($run) == 0) echo "<br><center><b><font color=\"#ff0000\">NO RUNS AVAILABLE</font></b></center>"; + +include("$locr/footnote.php"); +?> diff --git a/boca-1.5.0/src/admin/report/score.php b/boca-1.5.0/src/admin/report/score.php new file mode 100644 index 0000000..0196b3a --- /dev/null +++ b/boca-1.5.0/src/admin/report/score.php @@ -0,0 +1,43 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA System (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +//Last updated 10/jul/2012 by cassio@ime.usp.br + +require('header.php'); + +$final = true; +$s = $st; +$des = true; +$detail=true; +if($_GET["p"] == "0") $ver = false; +else if($_GET["p"] == "2") $detail=false; +else { + $ver = true; + $des = false; +} +if(isset($_GET["hor"])) $hor = $_GET["hor"]; +else $hor = -1; + +if ($s["currenttime"] >= $s["sitelastmilescore"] && $ver) { + $togo = (int) (($s['siteduration'] - $s["sitelastmilescore"])/60); + echo"<br /><center><h2>Scoreboard (as of $togo minutes to go)</h2></center>\n"; +} else + echo"<br /><center><h2>Final Scoreboard</h2></center>\n"; + +require("$locr/scoretable.php"); +include("$locr/footnote.php"); +?> diff --git a/boca-1.5.0/src/admin/report/site.php b/boca-1.5.0/src/admin/report/site.php new file mode 100644 index 0000000..001d48e --- /dev/null +++ b/boca-1.5.0/src/admin/report/site.php @@ -0,0 +1,128 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +require('header.php'); + +$sitetime = DBAllSiteTime($_SESSION["usertable"]["contestnumber"], $site); +?> +<br /> +<center><h2>Site Start/Stop Logs</h2></center> + + <table border="0"> +<?php +echo " <td nowrap width=\"50%\" align=right>Start date (contest=" . dateconv($ct["conteststartdate"]) . "):</td>"; +echo "<td width=\"50%\"><b>" . dateconv($st["sitestartdate"]) . "</b></td>\n"; +echo "<tr>"; +if (!$st["siterunning"]) { + echo " <tr>\n"; + echo " <td nowrap width=\"50%\" align=right><b>Finished at:</b></td>\n"; + echo " <td width=\"50%\"><b>" . dateconv($st["siteendeddate"]); + if($st["siteautoended"]) echo " (auto)"; + echo "</b></td>\n"; + echo " </tr>\n"; + if($st["siteautoended"]) { + $w = (int) ($st["siteduration"]/60); + $ww = $st["siteduration"] % 60; + } + else { + $w = (int) ($st["currenttime"]/60); + $ww = $st["currenttime"] % 60; + } + echo " <tr>\n"; + echo " <td nowrap width=\"50%\" align=right><b>Real duration:</b></td>\n"; + echo " <td width=\"50%\"><b>$w minutes"; + if($ww != 0) echo " plus $ww seconds"; + echo "</b></td>\n"; + echo " </tr>\n"; +} +echo "<tr>\n"; +echo " <td width=\"50%\" align=right>Planned Duration (contest="; +echo $ct["contestduration"]/60; +echo "):</td>"; +?> + <td width="50%"> + <?php echo $st["siteduration"]/60; ?> + </td> + </tr> + <tr> +<?php +echo " <td width=\"50%\" align=right>Stop answering (contest="; +echo $ct["contestlastmileanswer"]/60; +echo "):</td>"; +?> + <td width="50%"> + <?php echo $st["sitelastmileanswer"]/60; ?> + </td> + </tr> + <tr> +<?php +echo " <td width=\"50%\" align=right>Stop scoreboard (contest="; +echo $ct["contestlastmilescore"]/60; +echo "):</td>"; +?> + <td width="50%"> + <?php echo $st["sitelastmilescore"]/60; ?> + </td> + </tr> + <tr> + <td width=\"50%\" align=right>Number of Clars:</td> + <td width="50%"><?php echo $st["sitenextclar"]; ?> + </td> + </tr> + <tr> + <td width=\"50%\" align=right>Number of Runs:</td> + <td width="50%"><?php echo $st["sitenextrun"]; ?> + </td> + </tr> + <tr> + <td width=\"50%\" align=right>Number of Tasks:</td> + <td width="50%"><?php echo $st["sitenexttask"]; ?> + </td> + </tr> + </table> + </center> +<center> +<br /> +<table border=1> +<tr> +<td nowrap width=\"50%\" align=right>Starting at</td><td nowrap width=\"50%\" align=left>Ending at</td> +</tr> +<?php +$n = count($sitetime); +for ($i=0; $i< $n; $i++) { + echo "<tr>"; + echo "<td nowrap align=right>"; + echo dateconv($sitetime[$i]["sitestartdate"]); + echo "</td>"; + echo "<td nowrap align=left>"; + if($sitetime[$i]["siteenddate"] == 0) { + if($st["siterunning"]) + echo "still open"; + else echo "auto-ended"; + } + else + echo dateconv($sitetime[$i]["siteenddate"]); + echo "</td>"; + echo "</tr>"; +} +?> +</table> +</center> + +<?php include("$locr/footnote.php"); ?> diff --git a/boca-1.5.0/src/admin/report/stat.php b/boca-1.5.0/src/admin/report/stat.php new file mode 100644 index 0000000..7d99cb3 --- /dev/null +++ b/boca-1.5.0/src/admin/report/stat.php @@ -0,0 +1,337 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +require('header.php'); + +$d = DBRunReport($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"]); + +echo "<center><h2>Statistics</h2></center>\n"; +//---------------------------------------------------------- +echo "<center><h3>Runs by Problem</h3></center>\n"; +echo "<center><table border=1>\n"; +echo "<tr><td><b><u>Problems</u></b></td>"; + +echo "<td>Total</td><td>Accepted</td>"; +echo "</tr>\n"; + +$str="All Runs by Problem"; +$str2="Accepted Runs by Problem"; +reset($d['problem']); +$cor = ""; +while (list($keya, $val) = each($d['problem'])) { + $val = $d['problemyes'][$keya]; if($val=="") $val=0; + $str2 .= chr(1) . $keya . "(" . $val . ")" . chr(1) . $val; + $cor .= "-" . $d['color'][$keya]; +} +$cor = substr($cor,1); + +reset($d['problem']); +while (list($keya, $val) = each($d['problem'])) { + $str .= chr(1) . $keya . "(" . $val . ")" . chr(1) . $val; + echo "<tr><td>$keya "; + echo "<img alt=\"balloon\" width=\"15\" ". + "src=\"" . balloonurl($d['color'][$keya]) ."\" />\n"; + echo "</td>"; + echo "<td>$val</td>"; + if(isset($d['problemyes'][$keya])) { + echo "<td nowrap>".$d['problemyes'][$keya]; + if($val != 0) { + $p = round(100*$d['problemyes'][$keya] / $val); + echo " (".$p."%)"; + } + echo "</td>"; + } + else + echo "<td nowrap>0 (0%)</td>"; + echo "</tr>"; +} +echo "</table></center>"; + +echo "<center><table><tr>"; +echo "<td><img alt=\"\" src=\"piechart.php?dados=".rawurlencode($str)."&color=".rawurlencode($cor)."\" /></td>\n"; +echo "<td><img alt=\"\" src=\"piechart.php?dados=".rawurlencode($str2)."&color=".rawurlencode($cor)."\" /></td></tr></table></center>\n"; + +//---------------------------------------------------------- +echo "<center><h3>Runs by Problem and Answer</h3></center>\n"; +echo "<center><table border=1>\n"; +echo "<tr><td><b><u>Problems x Answers</u></b></td>"; +reset($d['answer']); +while (list($key, $val) = each($d['answer'])) + echo "<td>$key</td>"; +echo "<td>Total</td></tr>\n"; + +reset($d['problem']); +while (list($keya, $vala) = each($d['problem'])) { + echo "<tr><td>$keya "; + echo "<img alt=\"balloon\" width=\"15\" ". + "src=\"" . balloonurl($d['color'][$keya]) ."\" />\n"; + echo "</td>"; + reset($d['answer']); + while (list($key, $val) = each($d['answer'])) { + if(!isset($d['pa'][$keya][$key])) + echo "<td>0</td>"; + else { + $p = round(100*$d['pa'][$keya][$key] / $vala); + echo "<td nowrap>".$d['pa'][$keya][$key]." (".$p."%)</td>"; + } + } + echo "<td>$vala</td>"; + echo "</tr>"; +} +echo "</table></center>"; + +//---------------------------------------------------------- +echo "<center><h3>Runs by Problem and Language</h3></center>\n"; +echo "<center><table border=1>\n"; +echo "<tr><td><b><u>Problems x Languages</u></b></td>"; +reset($d['language']); +while (list($key, $val) = each($d['language'])) + echo "<td>$key</td>"; +echo "<td>Total</td></tr>\n"; + +reset($d['problem']); +while (list($keya, $vala) = each($d['problem'])) { + echo "<tr><td>$keya "; + echo "<img alt=\"balloon\" width=\"15\" ". + "src=\"" . balloonurl($d['color'][$keya]) ."\" />\n"; + echo "</td>"; + reset($d['language']); + while (list($key, $val) = each($d['language'])) { + if(!isset($d['pl'][$keya][$key])) + echo "<td>0</td>"; + else { + $p = round(100*$d['pl'][$keya][$key] / $vala); + echo "<td nowrap>".$d['pl'][$keya][$key]." (".$p."%)</td>"; + } + } + echo "<td>$vala</td>"; + echo "</tr>"; +} +echo "</table></center>"; + +//---------------------------------------------------------- +echo "<br />"; +echo "<hr />"; +echo "<center><h3>Runs by Language</h3></center>\n"; +echo "<center><table border=1>\n"; +echo "<tr><td><b><u>Languages</u></b></td>"; + +echo "<td>Total</td><td>Accepted</td>"; +echo "</tr>\n"; + +$str="All Runs by Language"; +$str2="Accepted Runs by Language"; +reset($d['language']); +while (list($keya, $val) = each($d['language'])) { + $val = $d['languageyes'][$keya]; if($val=="") $val=0; + $str2 .= chr(1) . $keya . "(" . $val . ")" . chr(1) . $val; +} + +reset($d['language']); +while (list($keya, $val) = each($d['language'])) { + $str .= chr(1) . $keya . "(" . $val . ")" . chr(1) . $val; + echo "<tr><td>$keya</td>"; + echo "<td>$val</td>"; + if(isset($d['languageyes'][$keya])) { + $p = round(100*$d['languageyes'][$keya] / $val); + echo "<td nowrap>".$d['languageyes'][$keya]." (".$p."%)</td>"; + } + else + echo "<td nowrap>0 (0%)</td>"; + echo "</tr>"; +} +echo "</table></center>"; + +echo "<center><table><tr>"; +echo "<td><img alt=\"\" src=\"piechart.php?dados=".rawurlencode($str)."\" /></td>\n"; +echo "<td><img alt=\"\" src=\"piechart.php?dados=".rawurlencode($str2)."\" /></td></tr></table></center>\n"; + +//---------------------------------------------------------- +echo "<center><h3>Runs by Language and Answer</h3></center>\n"; +echo "<center><table border=1>\n"; +echo "<tr><td><b><u>Languages x Answers</u></b></td>"; +reset($d['answer']); +while (list($key, $val) = each($d['answer'])) + echo "<td>$key</td>"; +echo "<td>Total</td></tr>\n"; + +reset($d['language']); +while (list($keya, $vala) = each($d['language'])) { + echo "<tr><td>$keya</td>"; + reset($d['answer']); + while (list($key, $val) = each($d['answer'])) { + if(!isset($d['la'][$keya][$key])) + echo "<td>0</td>"; + else { + $p = round(100*$d['la'][$keya][$key] / $vala); + echo "<td nowrap>".$d['la'][$keya][$key]." (".$p."%)</td>"; + } + } + echo "<td>$vala</td>"; + echo "</tr>"; +} +echo "</table></center>"; + +//---------------------------------------------------------- +echo "<br />"; +echo "<hr />"; +echo "<center><h3>Runs by Answer</h3></center>\n"; + +echo "<center><table><tr>"; +echo "<td>"; + +echo "<center><table border=1>\n"; +echo "<tr><td><b><u>Answers</u></b></td>"; + +echo "<td>Answers</td>"; +echo "</tr>\n"; + +$str="All Runs by Answer"; +reset($d['answer']); +while (list($keya, $val) = each($d['answer'])) { + $str .= chr(1) . $keya . "(" . $val . ")" . chr(1) . $val; + echo "<tr><td>$keya</td>"; + echo "<td>$val</td>"; + echo "</tr>"; +} +echo "</table></center>"; + +echo "</td>"; +echo "<td><img alt=\"\" src=\"piechart.php?order=1&dados=".rawurlencode($str)."\" /></td></tr></table></center>\n"; + +//---------------------------------------------------------- +echo "<br />"; +echo "<hr />"; +echo "<center><h3>Runs by User and Problem</h3></center>\n"; +echo "<center><table border=1>\n"; +echo "<tr><td><b><u>Users x Problems</u></b></td>"; +reset($d['problem']); +while (list($key, $val) = each($d['problem'])) { + echo "<td>$key "; + echo "<img alt=\"balloon\" width=\"15\" ". + "src=\"" . balloonurl($d['color'][$key]) ."\" />\n"; + echo "</td>"; +} +echo "<td>Total</td><td>Accepted</td></tr>\n"; + +reset($d['username']); +while (list($keya, $vala) = each($d['username'])) { + $keya = $d['username'][$keya]; + $vala = $d['user'][$keya]; + echo "<tr><td>".$d['userfull'][$keya]."</td>"; + reset($d['problem']); + while (list($key, $val) = each($d['problem'])) { + if(!isset($d['up'][$keya][$key])) + echo "<td bgcolor=\"ffff88\">0</td>"; + else { + $q = $d['up'][$keya][$key]; + $color = "ff5555"; + if($q < 0) { + $q = - $q; + $color = "22ee22"; + } + echo "<td nowrap bgcolor=\"$color\">".$q; + if($vala != 0) { + $p = round(100*$q / $vala); + echo " (".$p."%)"; + } + echo "</td>"; + } + } + if($vala != "") + echo "<td>$vala</td>"; + else + echo "<td>0</td>"; + if(isset($d['useryes'][$keya])) { + if($vala != 0) { + $p = round(100*$d['useryes'][$keya] / $vala); + echo "<td nowrap>".$d['useryes'][$keya]." (".$p."%)</td>"; + } else + echo "<td>".$d['useryes'][$keya]."</td>"; + } else + echo "<td>0</td>"; + + echo "</tr>"; +} +echo "</table></center>"; + +//---------------------------------------------------------- +echo "<br />"; +echo "<hr />"; +echo "<center><h3>Runs by Time Period</h3></center>\n"; + +$vezes = 30; +$passo = $st['siteduration']/$vezes; +$atual = 0; +$pos = 0; +$res = array(); +$m = 0; +sort($d['timestamp']); +reset($d['timestamp']); +while (list($keya, $val) = each($d['timestamp'])) { + while($atual+$passo < $val) { + $atual += $passo; + $pos++; + } + $res[$pos]++; + if($res[$pos] > $m) $m=$res[$pos]; +} + +$str="Runs by Time Period" . chr(1) . $m; +$atual=0; +for($pos=0; $pos<$vezes; $pos++) { + if($res[$pos]=="") $res[$pos] = 0; + $q = (int) ($atual/60); + $atual += $passo; + $qq = (int) ($atual/60); + $str .= chr(1) . $q . "-" .$qq . chr(1) . $res[$pos]; +} + +echo "<center><img alt=\"\" src=\"linechart.php?dados=".rawurlencode($str)."\" /></center>\n"; + +//------------------------------------------------ +$vezes = 30; +$passo = $st['siteduration']/$vezes; +$atual = 0; +$pos = 0; +$res = array(); +sort($d['timestampyes']); +reset($d['timestampyes']); +while (list($keya, $val) = each($d['timestampyes'])) { + while($atual+$passo < $val) { + $atual += $passo; + $pos++; + } + $res[$pos]++; +} + +$str="Accepted Runs by Time Period" . chr(1) . $m; +$atual=0; +for($pos=0; $pos<$vezes; $pos++) { + if($res[$pos]=="") $res[$pos] = 0; + $q = (int) ($atual/60); + $atual += $passo; + $qq = (int) ($atual/60); + $str .= chr(1) . $q . "-" .$qq . chr(1) . $res[$pos]; +} + +echo "<center><img alt=\"\" src=\"linechart.php?dados=".rawurlencode($str)."\" /></center>\n"; + +include("$locr/footnote.php"); +?> diff --git a/boca-1.5.0/src/admin/report/task.php b/boca-1.5.0/src/admin/report/task.php new file mode 100644 index 0000000..59ca0e2 --- /dev/null +++ b/boca-1.5.0/src/admin/report/task.php @@ -0,0 +1,68 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +?> +<br> +<center><h2>Task List</h2></center> +<table width="100%" border=1> + <tr> + <td><b>#</b></td> + <td><b>Time</b></td> + <td><b>User / Site</b></td> + <td><b>Description</b></td> + <td><b>File</b></td> + <td><b>Staff / Site</b></td> + <td><b>Status</b></td> + </tr> +<?php +$s = $st; +$task = DBAllTasksInSites($_SESSION["usertable"]["contestnumber"], $s["sitetasking"], 'normal'); +$cf = globalconf(); +for ($i=0; $i<count($task); $i++) { + $st = $task[$i]["status"]; + + if($st == "processing" && $task[$i]["staff"]==$_SESSION["usertable"]["usernumber"] && + $task[$i]["staffsite"]==$_SESSION["usertable"]["usersitenumber"]) $mine=1; + else $mine=0; + + echo " <tr>\n"; + echo " <td nowrap>" . $task[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . dateconvminutes($task[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>".$task[$i]["username"]." / ".$task[$i]["site"]."</td>\n"; + echo " <td>" . $task[$i]["description"] . "</td>\n"; + if ($task[$i]["oid"] != null) { + echo " <td nowrap>" . $task[$i]["filename"]; + echo "</td>\n"; + + } + else + echo " <td nowrap> </td>\n"; + if($st != "opentask") + echo " <td nowrap>". $task[$i]["staffname"] . "(" . $task[$i]["staff"] .") / ".$task[$i]["staffsite"]."</td>\n"; + else + echo " <td nowrap> </td>\n"; + + echo " <td nowrap>$st</td>\n"; +} +echo "</table>"; +if (count($task) == 0) echo "<br><center><b><font color=\"#ff0000\">NO TASKS FOUND</font></b></center>"; + +include("$locr/footnote.php"); +?> diff --git a/boca-1.5.0/src/admin/run.php b/boca-1.5.0/src/admin/run.php new file mode 100644 index 0000000..4ec0eca --- /dev/null +++ b/boca-1.5.0/src/admin/run.php @@ -0,0 +1,187 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require 'header.php'; +if(isset($_GET["order"]) && $_GET["order"] != "") { +$order = myhtmlspecialchars($_GET["order"]); + $_SESSION["runline"] = $order; +} else { + if(isset($_SESSION["runline"])) + $order = $_SESSION["runline"]; +else + $order = ''; +} +?> + +<form name="form1" method="post" action="<?php echo $runphp; ?>"> + <input type=hidden name="confirmation" value="noconfirm" /> +<br> +<table width="100%" border=1> + <tr> + <td><b><a href="<?php echo $runphp; ?>?order=run">Run #</a></b></td> + <td><b><a href="<?php echo $runphp; ?>?order=site">Site</a></b></td> +<?php if($runphp == "run.php") { ?> + <td><b><a href="<?php echo $runphp; ?>?order=user">User</a></b></td> +<?php } ?> + <td><b>Time</b></td> + <td><b><a href="<?php echo $runphp; ?>?order=problem">Problem</a></b></td> + <td><b><a href="<?php echo $runphp; ?>?order=language">Language</a></b></td> +<!-- <td><b>Filename</b></td> --> + <td><b><a href="<?php echo $runphp; ?>?order=status">Status</a></b></td> + <td><b><a href="<?php echo $runphp; ?>?order=judge">Judge (Site)</a></b></td> + <td><b>AJ</b></td> + <td><b><a href="<?php echo $runphp; ?>?order=answer">Answer</a></b></td> + </tr> +<?php +if (($s=DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +// forca aparecer as runs do proprio site +if (trim($s["sitejudging"])!="") $s["sitejudging"].=",".$_SESSION["usertable"]["usersitenumber"]; +else $s["sitejudging"]=$_SESSION["usertable"]["usersitenumber"]; + +$run = DBAllRunsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"], $order); + +if(isset($_POST)) { + $nrenew = 0; + $nreopen = 0; + for ($i=0; $i<count($run); $i++) { + if(isset($_POST["cbox_" . $run[$i]["number"] . "_" . $run[$i]["site"]]) && + $_POST["cbox_" . $run[$i]["number"] . "_" . $run[$i]["site"]] != "") { + if(isset($_POST["auto"]) && $_POST["auto"]=="Re-run autojudge for selected runs") { + if (DBGiveUpRunAutojudging($_SESSION["usertable"]["contestnumber"], + $run[$i]["site"], $run[$i]["number"])) + $nrenew++; + } + if(isset($_POST["open"]) && $_POST["open"]=="Open selected runs for rejudging") { + DBGiveUpRunAutojudging($_SESSION["usertable"]["contestnumber"], + $run[$i]["site"], $run[$i]["number"]); + if (DBChiefRunGiveUp($run[$i]["number"], $run[$i]["site"], + $_SESSION["usertable"]["contestnumber"])) + $nreopen++; + } + } + } + if($nrenew > 0) { + MSGError($nrenew . " runs renewed for autojudging."); + ForceLoad($runphp); + } + if($nreopen > 0) { + MSGError($nreopen . " runs reopened."); + ForceLoad($runphp); + } +} + + +for ($i=0; $i<count($run); $i++) { + if($run[$i]["answer1"] != 0 && $run[$i]["answer2"] != 0 && $run[$i]["status"] != "judged") { + if($runphp == "runchief.php") + echo " <tr bgcolor=\"ff0000\">\n"; + else echo "<tr>\n"; + echo " <td nowrap bgcolor=\"ff0000\">"; + } + else { + echo " <tr><td nowrap>"; + } + echo "<input type=\"checkbox\" name=\"cbox_" . $run[$i]["number"] . "_" . $run[$i]["site"] . "\" />"; + echo " <a href=\"" . $runeditphp . "?runnumber=".$run[$i]["number"]."&runsitenumber=".$run[$i]["site"] . + "\">" . $run[$i]["number"] . "</a></td>\n"; + + echo " <td nowrap>" . $run[$i]["site"] . "</td>\n"; + if($runphp == "run.php") { + if ($run[$i]["user"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["site"], $run[$i]["user"]); + echo " <td nowrap>" . $u["username"] . "</td>\n"; + } + } + echo " <td nowrap>" . dateconvminutes($run[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $run[$i]["problem"] . "</td>\n"; + echo " <td nowrap>" . $run[$i]["language"] . "</td>\n"; +// echo " <td nowrap>" . $run[$i]["filename"] . "</td>\n"; + if ($run[$i]["judge"] == $_SESSION["usertable"]["usernumber"] && + $run[$i]["judgesite"] == $_SESSION["usertable"]["usersitenumber"] && $run[$i]["status"] == "judging") + $color="ff7777"; + else if ($run[$i]["status"]== "judged+" && $run[$i]["judge"]=="") $color="ffff00"; + else if ($run[$i]["status"]== "judged") $color="bbbbff"; + else if ($run[$i]["status"] == "judging" || $run[$i]["status"]== "judged+") $color="77ff77"; + else if ($run[$i]["status"] == "openrun") $color="ffff88"; + else $color="ffffff"; + + echo " <td nowrap bgcolor=\"#$color\">" . $run[$i]["status"] . "</td>\n"; + if ($run[$i]["judge"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["judgesite"], $run[$i]["judge"]); + echo " <td nowrap>" . $u["username"] . " (" . $run[$i]["judgesite"] . ")"; + } else + echo " <td> "; + + if ($run[$i]["judge1"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["judgesite1"], $run[$i]["judge1"]); + echo " [" . $u["username"] . " (" . $run[$i]["judgesite1"] . ")]"; + } + if ($run[$i]["judge2"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["judgesite2"], $run[$i]["judge2"]); + echo " [" . $u["username"] . " (" . $run[$i]["judgesite2"] . ")]"; + } + + echo "</td>\n"; + + if ($run[$i]["autoend"] != "") { + $color="bbbbff"; + if ($run[$i]["autoanswer"]=="") $color="ff7777"; + } + else if ($run[$i]["autobegin"]=="") $color="ffff88"; + else $color="77ff77"; + echo "<td bgcolor=\"#$color\"> </td>\n"; + + if ($run[$i]["answer"] == "") { + echo " <td> </td>\n"; + } else { + echo " <td>" . $run[$i]["answer"]; + if($run[$i]['yes']=='t') { + echo " <img alt=\"".$run[$i]["colorname"]."\" width=\"10\" ". + "src=\"" . balloonurl($run[$i]["color"]) ."\" />"; + } + echo "</td>\n"; + } + echo " </tr>\n"; +} + +echo "</table>"; +if (count($run) == 0) echo "<br><center><b><font color=\"#ff0000\">NO RUNS AVAILABLE</font></b></center>"; +else { +?> + <br> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> +<b>Click on the number of a run to edit it or select them with<br />the checkboxes and use the buttons to work on multiple runs:</b><br /><br /> + <input type="submit" name="auto" value="Re-run autojudge for selected runs" onClick="conf()"> + <input type="submit" name="open" value="Open selected runs for rejudging" onClick="conf()"> +<br><br> + </center> + </form> +<?php +} +?> +</body> +</html> diff --git a/boca-1.5.0/src/admin/runedit.php b/boca-1.5.0/src/admin/runedit.php new file mode 100644 index 0000000..c0090f9 --- /dev/null +++ b/boca-1.5.0/src/admin/runedit.php @@ -0,0 +1,331 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require 'header.php'; + +if (isset($_POST["cancel"]) && $_POST["cancel"]=="Cancel editing") + ForceLoad($runphp); + +if (isset($_POST["giveup"]) && $_POST["giveup"]=="Renew" && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["number"]) && + is_numeric($_POST["sitenumber"])) { + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + if (DBGiveUpRunAutojudging($_SESSION["usertable"]["contestnumber"], $sitenumber, $number)) + MSGError("Run renewed."); + ForceLoad($runphp); +} + +if (isset($_POST["delete"]) && $_POST["delete"]=="Delete" && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["number"]) && + is_numeric($_POST["sitenumber"])) { + if ($_POST["confirmation"]=="confirm") { + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + + if (DBRunDelete($number, $sitenumber, $_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"])) + MSGError("Run deleted."); + } + ForceLoad($runphp); +} + +if (isset($_POST["answer"]) && isset($_POST["open"]) && $_POST["open"]=="Open run for rejudging" && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["number"]) && + is_numeric($_POST["sitenumber"])) { + + if ($_POST["confirmation"] == "confirm") { + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + + DBGiveUpRunAutojudging($_SESSION["usertable"]["contestnumber"], $sitenumber, $number); + if (DBChiefRunGiveUp($_POST["number"], $_POST["sitenumber"], $_SESSION["usertable"]["contestnumber"])) + MSGError("Run returned."); + ForceLoad($runphp); + } +} + +if (isset($_POST["answer"]) && isset($_POST["Submit"]) && $_POST["Submit"]=="Judge" && is_numeric($_POST["answer"]) && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["sitenumber"]) && + is_numeric($_POST["number"])) { // && isset($_POST["notifyuser"]) && isset($_POST["updatescore"])) { + + if ($_POST["confirmation"] == "confirm") { + $answer = myhtmlspecialchars($_POST["answer"]); + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); +// $notuser = myhtmlspecialchars($_POST["notifyuser"]); +// $updscore = myhtmlspecialchars($_POST["updatescore"]); + + DBChiefUpdateRun($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], + $sitenumber, $number, $answer); //, $notuser, updscore); + } + ForceLoad($runphp); +} + +if (!isset($_GET["runnumber"]) || !isset($_GET["runsitenumber"]) || + !is_numeric($_GET["runnumber"]) || !is_numeric($_GET["runsitenumber"])) { + IntrusionNotify("tried to open the admin/runedit.php with wrong parameters."); + ForceLoad($runphp); +} + +// ??? +$runsitenumber = myhtmlspecialchars($_GET["runsitenumber"]); +$runnumber = myhtmlspecialchars($_GET["runnumber"]); + +if (($a = DBChiefGetRunToAnswer($runnumber, $runsitenumber, + $_SESSION["usertable"]["contestnumber"])) === false) { + MSGError("Another judge got it first."); + ForceLoad($runphp); +} + +$b = DBGetProblemData($_SESSION["usertable"]["contestnumber"], $a["problemnumber"]); +$c = DBGetLanguageData($_SESSION["usertable"]["contestnumber"], $a["langnumber"], $a["problemnumber"]); +?> +<br><br><center><b>Use the following fields to judge the run: +</b></center> +<form name="form1" method="post" action="<?php echo $runeditphp; ?>"> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="1"> + <tr> + <td width="27%" align=right><b>Site:</b></td> + <td width="83%"> + <input type=hidden name="sitenumber" value="<?php echo $a["sitenumber"]; ?>" /> + <?php echo $a["sitenumber"]; ?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Number:</b></td> + <td width="83%"> + <input type=hidden name="number" value="<?php echo $a["number"]; ?>" /> + <?php echo $a["number"]; ?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Time:</b></td> + <td width="83%"> + <?php echo dateconvminutes($a["timestamp"]); ?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Problem</b><i> <?php echo $a["problemname"]; ?></i>: </td> + <td width="83%"> +<?php +for ($i=0;$i<count($b);$i++) { + echo "<b>Problem package:</b><a href=\"../filedownload.php?". filedownload($b[$i]["inputoid"],$b[$i]["inputfilename"]) . "\">"; + echo $b[$i]["inputfilename"] . "</a>"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($b[$i]["inputoid"],$b[$i]["inputfilename"]) ."', 'View$i - INPUT','width=680,height=600,scrollbars=yes,resizable=yes')\">view</a> "; +/* + echo "<b>Sol:</b><a href=\"../filedownload.php?". filedownload($b[$i]["soloid"], $b[$i]["solfilename"]) . "\">"; + echo $b[$i]["solfilename"] . "</a>"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($b[$i]["soloid"], $b[$i]["solfilename"]) ."', 'View$i - CORRECT OUTPUT','width=680,height=600,scrollbars=yes,resizable=yes')\">view</a>"; +*/ +} +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Language</b><i> <?php echo $a["language"]; ?></i>:</td> + <td width="83%"> +<?php + if (isset($c["compilation"]) && $c["compilation"]!="") echo "<b>Compilation Line:</b> ".$c["compilation"]. "<br>"; + if (isset($c["execution"]) && $c["execution"]!="") echo "<b>Execution Line:</b> ".$c["execution"]. "<br>"; + if (isset($c["showoutput"]) && $c["showoutput"]!="") echo "<b>Showing Output Line:</b> ". $c["showoutput"]. "<br>"; + + if (isset($c["scriptname"]) && $c["scriptname"]!="") { + echo "<b>Script for judging:</b> <a href=\"../filedownload.php?". filedownload($c["scriptoid"],$c["scriptname"]) ."\">"; + echo $c["scriptname"] . "</a>"; + } +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Team's code:</b></td> + <td width="83%"> +<?php //' +echo "<a href=\"../filedownload.php?". filedownload($a["sourceoid"],$a["sourcename"]) . "\">" . $a["sourcename"] . "</a>\n"; +echo "<a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?" . +filedownload($a["sourceoid"],$a["sourcename"]) ."', 'View - SOURCE', 'width=680,height=600,scrollbars=yes,resizable=yes')\">view</a>\n"; +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Answer:</b></td> + <td width="83%"> + <select name="answer"> +<?php +$ans = DBGetAnswers($_SESSION["usertable"]["contestnumber"]); +//$isfak = true; +for ($i=0;$i<count($ans);$i++) + if ($a["answer"] == $ans[$i]["number"]) { +// if($ans[$i]["fake"] != "t") $isfak = false; + echo "<option selected value=\"" . $ans[$i]["number"] . "\">" . $ans[$i]["desc"] . "</option>\n"; + } else + echo "<option value=\"" . $ans[$i]["number"] . "\">" . $ans[$i]["desc"] . "</option>\n"; + echo "</select>"; +// if(!$isfak) { + if($a["judgesite"] != "" && $a["judge"] != "") { + $uu = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $a["judgesite"], $a["judge"]); + echo " [judge=" . $uu["username"] . " (" . $a["judgesite"] . ")]"; + } +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Answer 1:</b></td> + <td width="83%"> +<?php +$ans = DBGetAnswers($_SESSION["usertable"]["contestnumber"]); +for ($i=0;$i<count($ans);$i++) + if ($a["answer1"] == $ans[$i]["number"]) { +// if($ans[$i]["fake"] != "t") { + if($a["judgesite1"] != "" && $a["judge1"] != "") { + $uu = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $a["judgesite1"], $a["judge1"]); + echo $ans[$i]["desc"] . " [judge=" . $uu["username"] . " (" . $a["judgesite1"] . ")]"; + } else + echo $ans[$i]["desc"]; + } +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Answer 2:</b></td> + <td width="83%"> +<?php +$ans = DBGetAnswers($_SESSION["usertable"]["contestnumber"]); +for ($i=0;$i<count($ans);$i++) + if ($a["answer2"] == $ans[$i]["number"]) { +// if($ans[$i]["fake"] != "t") { + if($a["judgesite2"] != "" && $a["judge2"] != "") { + $uu = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $a["judgesite2"], $a["judge2"]); + echo $ans[$i]["desc"] . " [judge=" . $uu["username"] . " (" . $a["judgesite2"] . ")]"; + } else + echo $ans[$i]["desc"]; + } +?> + </td> + </tr> + +<!-- + <tr> + <td width="27%" align=right><b>Notify user:</b></td> + <td width="83%"> + <input class=checkbox type=checkbox name="notifyuser" value="yes" +<?php +if (($s=DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +if ($a["timestamp"] < $s["sitelastmileanswer"]) echo "checked"; ?>> +(do not change this unless you know exactly what you are doing) + </td> + </tr> + <tr> + <td width="27%" align=right><b>Update score board:</b></td> + <td width="83%"> + <input class=checkbox type=checkbox name="updatescore" value="yes" +<?php if ($a["timestamp"] < $s["sitelastmilescore"]) echo "checked"; ?>> +(do not change this unless you know exactly what you are doing) + </td> + </tr> +--> + </table> + </center> + <br> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Judge" onClick="conf()"> + <input type="submit" name="open" value="Open run for rejudging" onClick="conf()"> + <input type="submit" name="cancel" value="Cancel editing"> + <input type="submit" name="delete" value="Delete" onClick="conf()"> + <input type="reset" name="Submit2" value="Clear"> +<br><br> + </center> + + <center> +<br> +<b>Autojudging:</b> +<input type="submit" name="giveup" value="Renew"> +<br><br> + <table border="1"> + <tr> + <td width="27%" align=right><b>Autojudging answer:</b></td> + <td width="83%"> +<?php +if($a["autobegin"]!="" && $a["autoend"]=="") + echo "in progress"; +else if($a["autoend"]!="") { + if($a["autoanswer"]!="") echo $a["autoanswer"]; + else echo "Autojudging error"; +} else + echo "unavailable"; +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Autojudged by:</b></td> +<?php if($a["autobegin"]!="" && $a["autoend"]=="") + echo "<td width=\"83%\">". $a["autoip"] ." since ". dateconvsimple($a["autobegin"]) ."</td>"; +else if($a["autoend"]!="") + echo "<td width=\"83%\">". $a["autoip"] ." from ". dateconvsimple($a["autobegin"]) ." to ". dateconvsimple($a["autoend"]) ."</td>"; +else + echo "<td width=\"83%\">unavailable</td>"; +?> + </tr> + <tr> + <td width="27%" align=right><b>Standard output:</b></td> + <td width="83%"> +<?php +if($a["autostdout"]!="") { + echo "<a href=\"../filedownload.php?".filedownload($a["autostdout"]."stdout") ."\">stdout</a>\n"; + echo "<a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($a["autostdout"]."stdout") ."', 'View - STDOUT','width=680,height=600,scrollbars=yes,". + "resizable=yes')\">view</a>\n"; +} else + echo "unavailable"; +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Standard error:</b></td> + <td width="83%"> +<?php +if($a["autostderr"]!="") { + echo "<a href=\"../filedownload.php?". filedownload($a["autostderr"],"stderr") . "\">stderr</a>\n"; + echo "<a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($a["autostderr"],"stderr") ."', 'View - STDERR','width=680,height=600,scrollbars=yes,". + "resizable=yes')\">view</a>\n"; +} else + echo "unavailable"; +?> + </td> + </tr> + </table></center> + +</form> +</body> +</html> diff --git a/boca-1.5.0/src/admin/score.php b/boca-1.5.0/src/admin/score.php new file mode 100644 index 0000000..ef9675d --- /dev/null +++ b/boca-1.5.0/src/admin/score.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +require('../scorelower.php'); +?> diff --git a/boca-1.5.0/src/admin/site.php b/boca-1.5.0/src/admin/site.php new file mode 100644 index 0000000..67a9ebe --- /dev/null +++ b/boca-1.5.0/src/admin/site.php @@ -0,0 +1,605 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require 'header.php'; + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); +if($ct["contestlocalsite"]==$ct["contestmainsite"]) $main=true; else $main=false; + +if ($main) { + if(isset($_GET["new"]) && $_GET["new"]=="1") { + $n = DBNewSite($_SESSION["usertable"]["contestnumber"]); + ForceLoad("site.php?site=$n"); + } +} +if (isset($_GET["site"]) && is_numeric($_GET["site"])) + $site=$_GET["site"]; +else if (isset($_POST["site"]) && is_numeric($_POST["site"])) + $site=$_POST["site"]; +else + $site=$ct["contestlocalsite"]; + +if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"], $site)) == null) + ForceLoad("../index.php"); +$sitetime = DBAllSiteTime($_SESSION["usertable"]["contestnumber"], $site); + +if (isset($_POST["Logoff"]) && $_POST["Logoff"] == "Logoff all users") { + if ($_POST["confirmation"] == "confirm") { + DBSiteLogoffAll ($_SESSION["usertable"]["contestnumber"], $site); + } + ForceLoad("site.php?site=$site"); +} +if (isset($_POST["Logins"]) && $_POST["Logins"] == "Enable logins") { + if ($_POST["confirmation"] == "confirm") { + DBSiteLogins ($_SESSION["usertable"]["contestnumber"], $site, "t"); + } + ForceLoad("site.php?site=$site"); +} +if (isset($_POST["Logins"]) && $_POST["Logins"] == "Disable logins") { + if ($_POST["confirmation"] == "confirm") { + DBSiteLogins ($_SESSION["usertable"]["contestnumber"], $site, "f"); + } + ForceLoad("site.php?site=$site"); +} +if (isset($_POST["Submit2"]) && $_POST["Submit2"] == "Start Now") { + if ($_POST["confirmation"] == "confirm") { + if(!DBSiteStartNow ($_SESSION["usertable"]["contestnumber"], $site)) + MSGError("Site is already running"); + } + ForceLoad("site.php?site=$site"); +} +if (isset($_POST["SubmitDC"]) && $_POST["SubmitDC"] == "Delete ALL site clars") { + if ($_POST["confirmation"] == "confirm") { + DBSiteDeleteAllClars ($_SESSION["usertable"]["contestnumber"], $site, + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"]); + } + ForceLoad("site.php?site=$site"); +} +if (isset($_POST["SubmitDR"]) && $_POST["SubmitDR"] == "Delete ALL site runs") { + if ($_POST["confirmation"] == "confirm") { + DBSiteDeleteAllRuns ($_SESSION["usertable"]["contestnumber"], $site, + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"]); + } + ForceLoad("site.php?site=$site"); +} +if (isset($_POST["SubmitDT"]) && $_POST["SubmitDT"] == "Delete ALL site tasks") { + if ($_POST["confirmation"] == "confirm") { + DBSiteDeleteAllTasks ($_SESSION["usertable"]["contestnumber"], $site, + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"]); + } + ForceLoad("site.php?site=$site"); +} +if (isset($_POST["SubmitDB"]) && $_POST["SubmitDB"] == "Delete ALL site bkps") { + if ($_POST["confirmation"] == "confirm") { + DBSiteDeleteAllBkps ($_SESSION["usertable"]["contestnumber"], $site, + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"]); + } + ForceLoad("site.php?site=$site"); +} +if (isset($_POST["Submit3"]) && $_POST["Submit3"] == "Stop Now") { + if ($_POST["confirmation"] == "confirm") { + if(DBSiteEndNow ($_SESSION["usertable"]["contestnumber"], $site)) + MSGError("Site has been finished"); + } + ForceLoad("site.php?site=$site"); +} +if (isset($_POST["endat"]) && $_POST["endat"] == "Stop At") { + if ($_POST["confirmation"] == "confirm" && + isset($_POST["enddateh"]) && $_POST["enddateh"] >= 0 && $_POST["enddateh"] <= 23 && + isset($_POST["enddatemin"]) && $_POST["enddatemin"] >= 0 && $_POST["enddatemin"] <= 59 && + isset($_POST["enddated"]) && isset($_POST["enddatem"]) && isset($_POST["enddatey"]) && + checkdate($_POST["enddatem"], $_POST["enddated"], $_POST["enddatey"])) { + $te = mktime ($_POST["enddateh"], $_POST["enddatemin"], 0, $_POST["enddatem"], $_POST["enddated"], $_POST["enddatey"]); + if($te > time()) + MSGError("Impossible to stop at a future time. Still running"); + else { + if(DBSiteEndNow ($_SESSION["usertable"]["contestnumber"], $site, $te)) + MSGError("Site has been finished"); + } + } + ForceLoad("site.php?site=$site"); +} +if (isset($_POST["Submit1"]) && $_POST["Submit1"] == "Send" && isset($_POST["name"]) && isset($_POST["site"]) && is_numeric($_POST["site"]) && + $_POST["name"] != "" && isset($_POST["lastmileanswer"]) && isset($_POST["scorelevel"]) && + is_numeric($_POST["lastmileanswer"]) && isset($_POST["lastmilescore"]) && + is_numeric($_POST["lastmilescore"]) && is_numeric($_POST["scorelevel"]) && + isset($_POST["chiefname"]) && + isset($_POST["startdateh"]) && $_POST["startdateh"] >= 0 && $_POST["startdateh"] <= 23 && + isset($_POST["startdatemin"]) && $_POST["startdatemin"] >= 0 && $_POST["startdatemin"] <= 59 && + isset($_POST["startdated"]) && isset($_POST["startdatem"]) && isset($_POST["startdatey"]) && + + checkdate($_POST["startdatem"], $_POST["startdated"], $_POST["startdatey"])) { + if ($_POST["confirmation"] == "confirm") { + $t = mktime ($_POST["startdateh"], $_POST["startdatemin"], 0, $_POST["startdatem"], $_POST["startdated"], $_POST["startdatey"]); + + $param['contestnumber']=$_SESSION["usertable"]["contestnumber"]; + $param['sitenumber']=$_POST["site"]; + $param['sitename']=$_POST["name"]; + $param['siteip']=$_POST["ip"]; + $param['siteduration']=$_POST["duration"]*60; + $param['sitelastmileanswer']= $_POST["lastmileanswer"]*60; + $param['sitelastmilescore']= $_POST["lastmilescore"]*60; + $param['sitejudging']= $_POST["judging"]; + $param['sitetasking']= $_POST["tasking"]; + if(isset($_POST["autoend"])) + $param['siteautoend']= $_POST["autoend"]; + if(isset($_POST["globalscore"])) + $param['siteglobalscore']= $_POST["globalscore"]; + if(isset($_POST["active"])) + $param['siteactive']=$_POST["active"]; + $param['sitescorelevel']=$_POST["scorelevel"]; + $param['sitepermitlogins']=''; + if(isset($_POST["autojudge"])) + $param['siteautojudge']=$_POST["autojudge"]; + $param['sitechiefname']=$_POST["chiefname"]; + DBUpdateSite ($param); + $st1 = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_POST["site"]); + if($t != $st1["sitestartdate"]) { + $param = array('contest'=>$_SESSION["usertable"]["contestnumber"], + 'site'=>$_POST["site"], + 'start'=>$t); + DBRenewSiteTime($param); + } + } + ForceLoad("site.php?site=".$_POST["site"]); +} + + +if ($main && isset($_FILES["importfile"]) && isset($_POST["Submit"]) && $_POST["Submit"]=='Import' && $_FILES["importfile"]["name"]!="") { + if ($_POST["confirmation"] == "confirm") { + $type=myhtmlspecialchars($_FILES["importfile"]["type"]); + $size=myhtmlspecialchars($_FILES["importfile"]["size"]); + $name=myhtmlspecialchars($_FILES["importfile"]["name"]); + $temp=myhtmlspecialchars($_FILES["importfile"]["tmp_name"]); + if (!is_uploaded_file($temp)) { + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + + if (($ar = file($temp)) === false) { + IntrusionNotify("Unable to open the uploaded file."); + ForceLoad("site.php"); + } + $userlist=array(); + if(strtolower(substr($name,-4))==".tsv") { + for ($i=0; $i<count($ar) && strpos($ar[$i], "File_Version\t1") === false; $i++) ; + if($i >= $count($ar)) MSGError('File format not recognized'); + $oklines=0; + for ($i++; $i<count($ar); $i++) { + $x = explode("\t",trim($ar[$i])); + if(count($x)==2) { + $param=array(); + $param['sitenumber']=trim($x[0]); + $param['sitename']=trim($x[1]); + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + if($_SESSION["usertable"]["usersitenumber"] == $param['sitenumber'] || $main) + if(DBNewSite($param['contest'],null,$param)) { + $oklines++; + $param=array(); + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + $param['site']=$ct["contestmainsite"]; + $param['username']='site' . trim($x[0]); + $param['usericpcid']=trim($x[0]); + $param['usernumber']=trim($x[0]); + $param['userfull']='Site connection'; + $param['userdesc']=''; + $param['type']='site'; + $param['enabled']='t'; + $param['multilogin']='t'; + $userlist[$param['username']] = randstr(10); + $param['pass']=myhash($userlist[$param['username']]); + DBNewUser($param); + } + } + } + MSGError($oklines . ' sites included/updated successfully'); + } else if(strtolower(substr($name,-4))==".tab") { + $oklines=0; + for ($i=0; $i<count($ar); $i++) { + $x = explode("\t",trim($ar[$i])); + if(count($x)==8) { + $param=array(); + $param['sitenumber']=trim($x[0]); + $param['sitename']=trim($x[2]); + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + if($_SESSION["usertable"]["usersitenumber"] == $param['sitenumber'] || $main) + if(DBNewSite($param['contest'],null,$param)) { + $oklines++; + $param=array(); + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + $param['site']=$ct["contestmainsite"]; + $param['username']='site' . trim($x[0]); + $param['usericpcid']=trim($x[0]); + $param['usernumber']=trim($x[0]); + $param['userfull']='Site connection'; + $param['userdesc']=''; + $param['type']='site'; + $param['enabled']='t'; + $param['multilogin']='t'; + $userlist[$param['username']] = randstr(10); + $param['pass']=myhash($userlist[$param['username']]); + DBNewUser($param); + } + } + } + MSGError($oklines . ' sites included/updated successfully'); + if(count($userlist) > 0) { +?> +<center> +<br><u><b>TAKE NOTE OF THE USERS AND PASSWORDS AND KEEP THEM SECRET</b></u><br><br> +<table border=1> + <tr> + <td><b>Username</b></td> + <td><b>Password</b></td> + </tr> +<?php + foreach($userlist as $user => $pass) { + echo "<tr><td>$user</td><td>$pass</td></tr>\n"; + } +?> +</table><br><br><u><b>TAKE NOTE OF THE USERS AND PASSWORDS AND KEEP THEM SECRET</b></u></center></body></html> +<?php + exit; + } + } else { + MSGError('File format not recognized'); + } + } + ForceLoad("site.php"); +} + +?> +<br> +<form name="form1" enctype="multipart/form-data" method="post" action="site.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <script language="javascript" type="text/javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + function conf2() { + if (confirm("Confirm DELETING EVERYTHING?")) { + if (confirm("This operation has no come back. DATA WILL BE LOST. Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + } + function newsite() { + document.location='site.php?new=1'; + } + function sitech(n) { + if(n==null) { + k=document.form1.site[document.form1.site.selectedIndex].value; + if(k=='new') newsite(); + else document.location='site.php?site='+k; + } else { + document.location='site.php?site='+n; + } + } + </script> + <center> + <table border="0"> + <tr> + <td width="35%" align=right>Site number:</td> + <td width="65%"> +<?php +echo "<select onChange=\"sitech()\" name=\"site\">\n"; +$cs = DBAllSiteInfo($_SESSION["usertable"]["contestnumber"]); +for ($i=0; $i<count($cs); $i++) { + echo "<option value=\"" . $cs[$i]["sitenumber"] . "\" "; + if ($site == $cs[$i]["sitenumber"]) + echo "selected"; + echo ">" . $cs[$i]["sitenumber"] . "</option>\n"; +} +if($main) { + echo "<option value=\"new\">new</option>\n"; +} +echo "</select>\n"; + +//else +// echo "<input type=\"text\" readonly name=\"site\" value=\"$site\" size=\"2\" maxlength=\"2\" />\n"; + +if($ct["contestlocalsite"]==$site) echo "(local site)"; +?> + </td> + </tr> + <tr> + <td width="35%" align=right>Name:</td> + <td width="65%"> + <input type="text" name="name" value="<?php echo $st["sitename"]; ?>" size="50" maxlength="50" /> + </td> + </tr> +<?php + if(0) { + if($main) { +?> + <tr> +<td width="35%" align=right>IP (plus boca path):</td> + <td width="65%"> + <input type="text" name="ip" value="<?php echo $st["siteip"]; ?>" size="50" maxlength="200" /> + </td> + </tr> +<?php + } else { +?> + <tr> +<td width="35%" align=right>IP (plus boca path):</td> + <td width="65%"> + <?php echo $st["siteip"]; ?> + </td> + </tr> +<?php + } + } +?> + <tr> +<?php +echo " <td nowrap width=\"35%\" align=right>Start date (contest=" . dateconv($ct["conteststartdate"]) . "):</td>"; +?> + <td width="65%"> hh:mm + <input type="text" name="startdateh" value="<?php echo date("H", $st["sitestartdate"]); ?>" size="2" maxlength="2" /> + : + <input type="text" name="startdatemin" value="<?php echo date("i", $st["sitestartdate"]); ?>" size="2" maxlength="2" /> + dd/mm/yyyy + <input type="text" name="startdated" value="<?php echo date("d", $st["sitestartdate"]); ?>" size="2" maxlength="2" /> + / + <input type="text" name="startdatem" value="<?php echo date("m", $st["sitestartdate"]); ?>" size="2" maxlength="2" /> + / + <input type="text" name="startdatey" value="<?php echo date("Y", $st["sitestartdate"]); ?>" size="4" maxlength="4" /> + </td> + </tr> + <tr> +<?php +if (!$st["siterunning"]) { + echo " <tr>\n"; + echo " <td nowrap width=\"35%\" align=right><b>Site finished at:</b></td>\n"; + echo " <td width=\"65%\"><b>" . dateconv($st["siteendeddate"]) . "</b></td>\n"; + echo " </tr>\n"; + if($st["siteautoended"]) + $w = (int) ($st["siteduration"]/60); + else + $w = (int) ($st["currenttime"]/60); + echo " <tr>\n"; + echo " <td nowrap width=\"35%\" align=right><b>Real duration:</b></td>\n"; + echo " <td width=\"65%\"><b>" . $w . " minutes</b></td>\n"; + echo " </tr>\n"; +} +?> + <tr> +<?php +echo " <td width=\"35%\" align=right>Duration (contest="; +echo $ct["contestduration"]/60; +echo "):</td>"; +?> + <td width="65%"> + <input type="text" name="duration" value="<?php echo $st["siteduration"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> +<?php +echo " <td width=\"35%\" align=right>Stop answering (contest="; +echo $ct["contestlastmileanswer"]/60; +echo "):</td>"; +?> + <td width="65%"> + <input type="text" name="lastmileanswer" value="<?php echo $st["sitelastmileanswer"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> +<?php +echo " <td width=\"35%\" align=right>Stop scoreboard (contest="; +echo $ct["contestlastmilescore"]/60; +echo "):</td>"; +?> + <td width="65%"> + <input type="text" name="lastmilescore" value="<?php echo $st["sitelastmilescore"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Runs/clars that will be judged here (comma sep):</td> + <td width="65%"> + <input type="text" name="judging" value="<?php echo $st["sitejudging"]; ?>" size="20" maxlength="200" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Tasks that will be treated here (comma sep):</td> + <td width="65%"> + <input type="text" name="tasking" value="<?php echo $st["sitetasking"]; ?>" size="20" maxlength="200" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Username of the chief judge (if any):</td> + <td width="65%"> + <input type="text" name="chiefname" value="<?php echo $st["sitechiefname"]; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Active:</td> + <td width="65%"> +<?php + if ($st["siteactive"] == "t") + echo "<input class=checkbox type=\"checkbox\" name=\"active\" checked value=\"t\" />"; + else + echo "<input class=checkbox type=\"checkbox\" name=\"active\" value=\"t\" />"; +?> + </td> + </tr> + <tr> + <td width="35%" align=right>Autoend:</td> + <td width="65%"> +<?php + if ($st["siteautoend"] == "t") + echo "<input class=checkbox type=\"checkbox\" name=\"autoend\" checked value=\"t\" />"; + else + echo "<input class=checkbox type=\"checkbox\" name=\"autoend\" value=\"t\" />"; +?> + </td> + </tr> + <tr> + <td width="35%" align=right>Global score:</td> + <td width="65%"> + <input type="text" name="globalscore" value="<?php echo $st["siteglobalscore"]; ?>" size="20" maxlength="50" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Autojudge (without human interaction):</td> + <td width="65%"> +<?php + if ($st["siteautojudge"] == "t") + echo "<input class=checkbox type=\"checkbox\" name=\"autojudge\" checked value=\"t\" />"; + else + echo "<input class=checkbox type=\"checkbox\" name=\"autojudge\" value=\"t\" />"; + echo " <- experimental"; +?> + </td> + </tr> + <tr> + <td width="35%" align=right>Logins are:</td> + <td width="65%"> +<?php + if ($st["sitepermitlogins"] == "t") + echo "enabled"; + else + echo "disabled"; +?> + </td> + </tr> + <tr> + <td width=\"35%\" align=right>Score level:</td> + <td width="65%"> + <input type="text" name="scorelevel" value="<?php echo $st["sitescorelevel"]; ?>" size="2" maxlength="2" /> + </td> + </tr> + <tr> + <td width=\"35%\" align=right>Number of Clars:</td> + <td width="65%"><?php echo $st["sitenextclar"]; ?> + </td> + </tr> + <tr> + <td width=\"35%\" align=right>Number of Runs:</td> + <td width="65%"><?php echo $st["sitenextrun"]; ?> + </td> + </tr> + <tr> + <td width=\"35%\" align=right>Number of Tasks:</td> + <td width="65%"><?php echo $st["sitenexttask"]; ?> + </td> + </tr> + </table> + </center> + <center> +<?php + if($main || $site == $ct["contestlocalsite"]) { +?> + <input type="submit" name="Submit1" value="Send" onClick="conf()"> + <input type="submit" name="Submit2" value="Start Now" onClick="conf()"> + <input type="submit" name="Submit3" value="Stop Now" onClick="conf()"> + <input type="reset" name="Submit4" value="Restore fields"> +<br> + <input type="submit" name="Logoff" value="Logoff all users" onClick="conf()"> + <input type="submit" name="Logins" value="Disable logins" onClick="conf()"> + <input type="submit" name="Logins" value="Enable logins" onClick="conf()"> +<br><br><br> + + <input type="submit" name="SubmitDC" value="Delete ALL site clars" onClick="conf2()"> + <input type="submit" name="SubmitDR" value="Delete ALL site runs" onClick="conf2()"> + <input type="submit" name="SubmitDT" value="Delete ALL site tasks" onClick="conf2()"> + <input type="submit" name="SubmitDB" value="Delete ALL site bkps" onClick="conf2()"> +<?php + } +?> + </center> +<center> +<br /> +<table border=1> +<tr> +<td nowrap width=\"50%\" align=right>Starting at</td><td nowrap width=\"50%\" align=left>Ending at</td> +</tr> +<?php +$n = count($sitetime); +for ($i=0; $i< $n; $i++) { + echo "<tr>"; + echo "<td nowrap align=right>"; + echo dateconv($sitetime[$i]["sitestartdate"]); + echo "</td>"; + echo "<td nowrap align=left>"; + if($sitetime[$i]["siteenddate"] == 0) { + if($st["siterunning"]) + echo "still open"; + else echo "auto-ended"; + } + else + echo dateconv($sitetime[$i]["siteenddate"]); + echo "</td>"; + echo "</tr>"; +} +?> +</table> +</center> + +<?php + if($main || $site == $ct["contestlocalsite"]) { +?> + <center> + <table border="0"> + <tr> +<td nowrap width="50%" align=right> +(Do not use this button unless really necessary) + <input type="submit" name="endat" value="Stop At" onClick="conf()">: +</td> +<?php +$w = $st["siteendeddate"]; +?> + <td width="50%"> hh:mm + <input type="text" name="enddateh" value="<?php echo date("H", $w); ?>" size="2" maxlength="2" /> + : + <input type="text" name="enddatemin" value="<?php echo date("i", $w); ?>" size="2" maxlength="2" /> + dd/mm/yyyy + <input type="text" name="enddated" value="<?php echo date("d", $w); ?>" size="2" maxlength="2" /> + / + <input type="text" name="enddatem" value="<?php echo date("m", $w); ?>" size="2" maxlength="2" /> + / + <input type="text" name="enddatey" value="<?php echo date("Y", $w); ?>" size="4" maxlength="4" /> + </td> + </tr> + </table> + </center> +<?php + } +if($main) { +?> +<br><br> + <center> + <table border="0"> + <tr> + <td width="25%" align=right>Import file:</td> + <td width="75%"> + <input type="file" name="importfile" size="40"> + </td> + </tr> + </table> + <input type="submit" name="Submit" value="Import" onClick="conf()"> + </center> + <?php } ?> +</form> + + +</body> +</html> diff --git a/boca-1.5.0/src/admin/task.php b/boca-1.5.0/src/admin/task.php new file mode 100644 index 0000000..95aca10 --- /dev/null +++ b/boca-1.5.0/src/admin/task.php @@ -0,0 +1,147 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require_once('header.php'); +if(isset($_GET["order"]) && $_GET["order"] != "") { +$order = myhtmlspecialchars($_GET["order"]); + $_SESSION["taskline"] = $order; +} else { + if(isset($_SESSION["taskline"])) + $order = $_SESSION["taskline"]; + else + $order=''; +} + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); + +if (isset($_GET["delete"]) && is_numeric($_GET["delete"]) && isset($_GET["site"]) && is_numeric($_GET["site"])) { + DBTaskDelete ($_GET["delete"], $_GET["site"], $_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"]); + ForceLoad("task.php"); +} + +if (isset($_GET["return"]) && is_numeric($_GET["return"]) && isset($_GET["site"]) && is_numeric($_GET["site"])) { + DBTaskGiveUp ($_GET["return"], $_GET["site"], $_SESSION["usertable"]["contestnumber"], -1, -1); +// $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"]); + ForceLoad("task.php"); +} + +if (isset($_GET["get"]) && is_numeric($_GET["get"]) && isset($_GET["site"]) && is_numeric($_GET["site"])) { + DBGetTaskToAnswer($_GET["get"], $_GET["site"], $_SESSION["usertable"]["contestnumber"]); + ForceLoad("task.php"); +} + +if (isset($_GET["done"]) && is_numeric($_GET["done"]) && isset($_GET["site"]) && is_numeric($_GET["site"])) { + DBChiefUpdateTask( $_SESSION["usertable"]["contestnumber"], $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], $_GET["site"], $_GET["done"], 'done'); + ForceLoad("task.php"); +} + + + +?> +<br> + <script language="javascript"> + function conf2(url) { +// if (confirm("Confirm?")) { + document.location=url; +// } else { +// document.location='task.php'; +// } + } + </script> +<table width="100%" border=1> + <tr> + <td><b><a href="task.php?order=task">Task #</a></b></td> + <td><b>Time</b></td> + <td><b><a href="task.php?order=user">User / Site</a></b></td> + <td><b><a href="task.php?order=description">Description</a></b></td> + <td><b>File</b></td> + <td><b><a href="task.php?order=staff">Staff / Site</a></b></td> + <td><b><a href="task.php?order=status">Status</a></b></td> + <td><b>Actions</b></td> + </tr> +<?php +if (($s=DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +$task = DBAllTasksInSites($_SESSION["usertable"]["contestnumber"], $s["sitetasking"], $order); +for ($i=0; $i<count($task); $i++) { + $st = $task[$i]["status"]; + + if($st == "processing" && $task[$i]["staff"]==$_SESSION["usertable"]["usernumber"] && + $task[$i]["staffsite"]==$_SESSION["usertable"]["usersitenumber"]) $mine=1; + else $mine=0; + + echo " <tr>\n"; + echo " <td nowrap>" . $task[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . dateconvminutes($task[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>".$task[$i]["username"]."(" . $task[$i]["user"] . ") / ".$task[$i]["site"]."</td>\n"; + echo " <td>" . $task[$i]["description"]; + if($task[$i]["color"] != "") { + echo " <img alt=\"".$task[$i]["colorname"]."\" width=\"10\" ". + "src=\"" . balloonurl($task[$i]["color"]) ."\" />"; + + } + echo "</td>\n"; + if ($task[$i]["oid"] != null) { + $msg = $task[$i]["username"]." ".$task[$i]["username"]." ".$task[$i]["username"]." ". + $task[$i]["username"]." ".$task[$i]["username"]." ".$task[$i]["username"]; + echo " <td nowrap><a href=\"../filedownload.php?" . filedownload($task[$i]["oid"], $task[$i]["filename"]) . "\">" . $task[$i]["filename"] . "</a>"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($task[$i]["oid"], $task[$i]["filename"], $msg) . "', 'Viewx$i','width=680,height=600,scrollbars=yes,". + "resizable=yes')\">view</a>"; + echo "</td>\n"; + } + else + echo " <td nowrap> </td>\n"; + if($st != "opentask") + echo " <td nowrap>". $task[$i]["staffname"] . "(" . $task[$i]["staff"] .") / ".$task[$i]["staffsite"]."</td>\n"; + else + echo " <td nowrap> </td>\n"; + + if ($mine) $color="ff7777"; + else if ($st == "done") $color="bbbbff"; + else if ($st == "processing") $color="77ff77"; + else if ($st == "opentask") $color="ffff88"; + else $color="ffffff"; + + echo " <td nowrap bgcolor=\"#$color\">$st</td>\n <td nowrap>"; + + if($st != "deleted") + echo " <a href=\"javascript: conf2('task.php?delete=" . $task[$i]["number"] . "&site=" . + $task[$i]["site"] . "')\">delete</a>\n"; + if($st == "opentask") + echo " <a href=\"javascript: conf2('task.php?get=" . $task[$i]["number"] . "&site=" . + $task[$i]["site"] . "')\">get</a>\n"; + if($st != "opentask") + echo " <a href=\"javascript: conf2('task.php?return=" . $task[$i]["number"] . "&site=" . + $task[$i]["site"] . "')\">return</a>\n"; + if($st == "processing") + echo " <a href=\"javascript: conf2('task.php?done=" . $task[$i]["number"] . "&site=" . + $task[$i]["site"] . "')\">done</a>\n"; + echo "</td>\n"; +} +echo "</table>"; +if (count($task) == 0) echo "<br><center><b><font color=\"#ff0000\">NO TASKS FOUND</font></b></center>"; + +?> + +</body> +</html> diff --git a/boca-1.5.0/src/admin/user.php b/boca-1.5.0/src/admin/user.php new file mode 100644 index 0000000..88cc148 --- /dev/null +++ b/boca-1.5.0/src/admin/user.php @@ -0,0 +1,444 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +if (isset($_GET["site"]) && isset($_GET["user"]) && is_numeric($_GET["site"]) && is_numeric($_GET["user"]) && + isset($_GET["logout"]) && $_GET["logout"] == 1) { + DBLogOut($_SESSION["usertable"]["contestnumber"], $_GET["site"], $_GET["user"]); + ForceLoad("user.php"); +} +if (isset($_POST["usersitenumber"]) && isset($_POST["usernumber"]) && is_numeric($_POST["usersitenumber"]) && + is_numeric($_POST["usernumber"]) && isset($_POST["confirmation"]) && $_POST["confirmation"] == "delete") { + if (!DBDeleteUser($_SESSION["usertable"]["contestnumber"], $_POST["usersitenumber"], $_POST["usernumber"])) + MSGError("User could not be removed."); + ForceLoad("user.php"); +} + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); +if($ct["contestlocalsite"]==$ct["contestmainsite"]) $main=true; else $main=false; + +if (isset($_POST["username"]) && isset($_POST["userfullname"]) && isset($_POST["userdesc"]) && isset($_POST["userip"]) && + isset($_POST["usernumber"]) && isset($_POST["usersitenumber"]) && isset($_POST["userenabled"]) && isset($_POST["usericpcid"]) && + isset($_POST["usermultilogin"]) && isset($_POST["usertype"]) && isset($_POST["confirmation"]) && + isset($_POST["passwordn1"]) && isset($_POST["passwordn2"]) && $_POST["confirmation"] == "confirm") { + $param['user'] = htmlspecialchars($_POST["usernumber"]); + $param['site'] = htmlspecialchars($_POST["usersitenumber"]); + $param['username'] = htmlspecialchars($_POST["username"]); + $param['usericpcid'] = htmlspecialchars($_POST["usericpcid"]); + $param['enabled'] = htmlspecialchars($_POST["userenabled"]); + $param['multilogin'] = htmlspecialchars($_POST["usermultilogin"]); + $param['userfull'] = htmlspecialchars($_POST["userfullname"]); + $param['userdesc'] = htmlspecialchars($_POST["userdesc"]); + $param['type'] = htmlspecialchars($_POST["usertype"]); + $param['pass'] = htmlspecialchars($_POST["passwordn1"]); + $param['permitip'] = htmlspecialchars($_POST["userip"]); + $param['contest'] = $_SESSION["usertable"]["contestnumber"]; + if ($_POST["passwordn1"] == $_POST["passwordn2"]) { + DBNewUser($param); + } + else MSGError ("Passwords don't match."); + ForceLoad("user.php"); +} +else if (isset($_FILES["importfile"]) && isset($_POST["Submit"]) && $_FILES["importfile"]["name"]!="") { + if ($_POST["confirmation"] == "confirm") { + $type=myhtmlspecialchars($_FILES["importfile"]["type"]); + $size=myhtmlspecialchars($_FILES["importfile"]["size"]); + $name=myhtmlspecialchars($_FILES["importfile"]["name"]); + $temp=myhtmlspecialchars($_FILES["importfile"]["tmp_name"]); + if (!is_uploaded_file($temp)) { + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + + if (($ar = file($temp)) === false) { + IntrusionNotify("Unable to open the uploaded file."); + ForceLoad("user.php"); + } + $userlist=array(); + if(strtolower(substr($name,-4))==".tsv") { + for ($i=0; $i<count($ar) && strpos($ar[$i], "File_Version\t1") === false; $i++) ; + if($i >= $count($ar)) MSGError('File format not recognized'); + $oklines=0; + for ($i++; $i<count($ar); $i++) { + $x = explode("\t",trim($ar[$i])); + if(count($x)==7) { + $param['site']=trim($x[2]); + $param['username']=trim($x[1]); + $param['usericpcid']=trim($x[1]); + $param['usernumber']=trim($x[1]); + if(trim($x[5])!='') + $param['userfull']=trim($x[3]) . ' - ' . trim($x[5]); + else + $param['userfull']=trim($x[3]); + $param['userdesc']=trim($x[4]); + $param['type']='team'; + $param['enabled']='t'; + $param['multilogin']='f'; + $userlist[$param['site'] . '-' . $param['usernumber']] = randstr(6,'0123456789'); + $param['pass']=myhash($userlist[$param['site'] . '-' . $param['usernumber']]); + + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + if($_SESSION["usertable"]["usersitenumber"] == $param['site'] || $main) + if(DBNewUser($param)) + $oklines++; + } + } + MSGError($oklines . ' users included/updated successfully'); + } else if(strtolower(substr($name,-4))==".tab") { + $oklines=0; + for ($i=0; $i<count($ar); $i++) { + $x = explode("\t",trim($ar[$i])); + if(count($x)==9) { + $param=array(); + $param['site']=trim($x[1]); + $param['username']=trim($x[0]); + $param['usericpcid']=trim($x[0]); + $param['usernumber']=trim($x[0]); + if(trim($x[5])!='') + $param['userfull']=trim($x[3]) . ' - ' . trim($x[5]); + else + $param['userfull']=trim($x[3]); + $param['userdesc']=trim($x[4]); + $param['type']='team'; + $param['enabled']='t'; + $param['multilogin']='f'; + $userlist[$param['site'] . '-' . $param['usernumber']] = randstr(6,'0123456789'); + $param['pass']=myhash($userlist[$param['site'] . '-' . $param['usernumber']]); + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + if($_SESSION["usertable"]["usersitenumber"] == $param['site'] || $main) + if(DBNewUser($param)) + $oklines++; + } + } + MSGError($oklines . ' users included/updated successfully'); + } else { + for ($i=0; $i<count($ar) && strpos($ar[$i], "[user]") === false; $i++) ; + if($i >= $count($ar)) MSGError('File format not recognized'); + for ($i++; $i<count($ar) && $ar[$i][0] != "["; $i++) { + $x = trim($ar[$i]); + if (strpos($x, "user") !== false && strpos($x, "user") == 0) { + $param = array(); + while (strpos($x, "user") !== false && strpos($x, "user") == 0) { + $tmp = explode ("=", $x, 2); + switch (trim($tmp[0])) { + case "usersitenumber": $param['site']=trim($tmp[1]); break; + case "username": $param['username']=trim($tmp[1]); break; + case "usericpcid": $param['usericpcid']=trim($tmp[1]); break; + case "usernumber": $param['usernumber']=trim($tmp[1]); break; + case "userfullname": $param['userfull']=trim($tmp[1]); break; + case "userdesc": $param['userdesc']=trim($tmp[1]); break; + case "usertype": $param['type']=trim($tmp[1]); break; + case "userenabled": $param['enabled']=trim($tmp[1]); break; + case "usermultilogin": $param['multilogin']=trim($tmp[1]); break; + case "userpassword": $param['pass']=myhash(trim($tmp[1])); break; + case "userip": $param['permitip']=trim($tmp[1]); break; + } + $i++; + if ($i>=count($ar)) break; + $x = trim($ar[$i]); + } + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + if($_SESSION["usertable"]["usersitenumber"] == $param['site'] || $main) + DBNewUser($param); + } + } + } + if(count($userlist) > 0) { +?> +<center> +<br><u><b>TAKE NOTE OF THE USERS AND PASSWORDS AND KEEP THEM SECRET</b></u><br><br> +<table border=1> + <tr> + <td nowrap><b>Site</b></td><td><b>User #</b></td> + <td><b>Password</b></td> + </tr> +<?php + foreach($userlist as $user => $pass) { + $x = explode('-',$user); + echo "<tr><td>" . $x[0] . "</td><td>" . $x[1] . "</td><td>$pass</td></tr>\n"; + } +?> +</table><br><br><u><b>TAKE NOTE OF THE USERS AND PASSWORDS AND KEEP THEM SECRET</b></u></center></body></html> +<?php + exit; + } + } + ForceLoad("user.php"); +} + +if($main) + $usr = DBAllUserInfo($_SESSION["usertable"]["contestnumber"]); +else + $usr = DBAllUserInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"]); +?> + + <script language="javascript"> + function conf2(url) { + if (confirm("Are you sure?")) { + document.location=url; + } else { + document.location='user.php'; + } + } + </script> +<br> +<table width="100%" border=1> + <tr> + <td nowrap><b>User #</b></td> + <td><b>Site</b></td> + <td><b>Username</b></td> + <td><b>ICPC ID</b></td> + <td><b>Type</b></td> + <td><b>IP</b></td> + <td><b>LastLogin</b></td> + <td><b>LastLogout</b></td> + <td><b>Enabled</b></td> + <td><b>Multi</b></td> + <td><b>Fullname</b></td> + <td><b>Description</b></td> + </tr> +<?php +for ($i=0; $i<count($usr); $i++) { + echo " <tr>\n"; + if(($usr[$i]["usersitenumber"] == $_SESSION["usertable"]["usersitenumber"] || $main==true) && + //$usr[$i]["usertype"] != 'site' && + ($usr[$i]["usernumber"] != $_SESSION["usertable"]["usernumber"] || + $usr[$i]["usersitenumber"] != $_SESSION["usertable"]["usersitenumber"])) + echo " <td nowrap><a href=\"user.php?site=" . $usr[$i]["usersitenumber"] . "&user=" . + $usr[$i]["usernumber"] . "\">" . $usr[$i]["usernumber"] . "</a></td>\n"; + else + echo " <td nowrap>" . $usr[$i]["usernumber"] . "</td>\n"; + + echo " <td nowrap>" . $usr[$i]["usersitenumber"] . "</td>\n"; + echo " <td nowrap>" . $usr[$i]["username"] . " </td>\n"; + echo " <td nowrap>" . $usr[$i]["usericpcid"] . " </td>\n"; + echo " <td nowrap>" . $usr[$i]["usertype"] . " </td>\n"; + if ($usr[$i]["userpermitip"]!="") + echo " <td nowrap>" . $usr[$i]["userpermitip"] . "* </td>\n"; + else + echo " <td nowrap>" . $usr[$i]["userip"] . " </td>\n"; + if ($usr[$i]["userlastlogin"] < 1) + echo " <td nowrap>never</td>\n"; + else + echo " <td nowrap>" . dateconv($usr[$i]["userlastlogin"]) . "</td>\n"; + if ($usr[$i]["usersession"] != "") + echo " <td nowrap><a href=\"javascript: conf2('user.php?logout=1&site=" . $usr[$i]["usersitenumber"] . "&user=" . + $usr[$i]["usernumber"] . "')\">Force Logout</a></td>\n"; + else { + if ($usr[$i]["userlastlogout"] < 1) + echo " <td nowrap>never</td>\n"; + else + echo " <td nowrap>" . dateconv($usr[$i]["userlastlogout"]) . "</td>\n"; + } + if ($usr[$i]["userenabled"] == "t") + echo " <td nowrap>Yes</td>\n"; + else + echo " <td nowrap>No</td>\n"; + if ($usr[$i]["usermultilogin"] == "t") + echo " <td nowrap>Yes</td>\n"; + else + echo " <td nowrap>No</td>\n"; + echo " <td nowrap>" . $usr[$i]["userfullname"] . " </td>\n"; + echo " <td nowrap>" . $usr[$i]["userdesc"] . " </td>\n"; + echo "</tr>"; +} +echo "</table>\n"; + +unset($u); +if (isset($_GET["site"]) && isset($_GET["user"]) && is_numeric($_GET["site"]) && is_numeric($_GET["user"])) + $u = DBUserInfo($_SESSION["usertable"]["contestnumber"], $_GET["site"], $_GET["user"]); + +?> +<script language="JavaScript" src="../sha256.js"></script> +<script language="JavaScript" src="../hex.js"></script> +<script language="JavaScript"> +function computeHASH() +{ + document.form3.passwordn1.value = js_myhash(document.form3.passwordn1.value); + document.form3.passwordn2.value = js_myhash(document.form3.passwordn2.value); +} +</script> + +<br><br><center><b>Clicking on a user number will bring the user data for edition.<br> +To import the users, just fill in the import file field.<br> +The file must be in the format defined in the admin's manual.</b></center> + +<form name="form1" enctype="multipart/form-data" method="post" action="user.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="0"> + <tr> + <td width="25%" align=right>Import file:</td> + <td width="75%"> + <input type="file" name="importfile" size="40"> + </td> + </tr> + </table> + </center> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Import" onClick="conf()"> + <input type="reset" name="Submit2" value="Clear"> + </center> +</form> + + <br><br> + <center> +<b>To create/edit one user, enter the data below.<br> +Note that any changes will overwrite the already defined data.<br> +(Specially care if you use a user number that is already existent.)<br> +<br> +</b> + <table border="0"> +<form name="form3" action="user.php" method="post"> + <input type=hidden name="confirmation" value="noconfirm" /> + <script language="javascript"> + function conf3() { + computeHASH(); + if (confirm("Confirm?")) { + document.form3.confirmation.value='confirm'; + } + } +<?php +if (isset($u)) { + echo " function conf4() {\n"; + echo " if (confirm('Confirm the deletion?')) {\n"; + echo " document.form3.confirmation.value='delete';\n"; + echo " }\n"; + echo " }\n"; + $usite = $u['usersitenumber']; +} else + $usite = $ct['contestlocalsite']; +?> + function conf5() { + document.form3.confirmation.value='noconfirm'; + } + </script> + <center> + <table border="0"> + <tr> + <td width="35%" align=right>User Site Number:</td> + <td width="65%"> + <input type="text" name="usersitenumber" <?php if(!$main) echo "readonly "; echo "value=\"" . $usite . "\""; ?> size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>User Number:</td> + <td width="65%"> + <input type="text" name="usernumber" value="<?php if(isset($u)) echo $u["usernumber"]; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Username:</td> + <td width="65%"> + <input type="text" name="username" value="<?php if(isset($u)) echo $u["username"]; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>ICPC ID:</td> + <td width="65%"> + <input type="text" name="usericpcid" value="<?php if(isset($u)) echo $u["usericpcid"]; ?>" size="20" maxlength="50" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Type:</td> + <td width="65%"> + <select name="usertype"> + <option <?php if(!isset($u) || $u["usertype"] == "team") echo "selected"; ?> value="team">Team</option> + <option <?php if(isset($u)) if($u["usertype"] == "judge") echo "selected"; ?> value="judge">Judge</option> + <option <?php if(isset($u)) if($u["usertype"] == "admin") echo "selected"; ?> value="admin">Admin</option> + <option <?php if(isset($u)) if($u["usertype"] == "staff") echo "selected"; ?> value="staff">Staff</option> + <option <?php if(isset($u)) if($u["usertype"] == "score") echo "selected"; ?> value="score">Score</option> + <?php if(1 || $main) { ?> + <option <?php if(isset($u)) if($u["usertype"] == "site") echo "selected"; ?> value="site">Site</option> + <?php } ?> + </select> + </td> + </tr> + <tr> + <td width="35%" align=right>Enabled:</td> + <td width="65%"> + <select name="userenabled"> + <option <?php if(!isset($u) || $u["userenabled"] != "f") echo "selected"; ?> value="t">Yes</option> + <option <?php if(isset($u) && $u["userenabled"] == "f") echo "selected"; ?> value="f">No</option> + </select> + </td> + </tr> + <tr> + <td width="35%" align=right>MultiLogins (local teams should be set to <b>No</b>):</td> + <td width="65%"> + <select name="usermultilogin"> + <option <?php if(isset($u) && $u["usermultilogin"] == "t") echo "selected"; ?> value="t">Yes</option> + <option <?php if(!isset($u) || $u["usermultilogin"] != "t") echo "selected"; ?> value="f">No</option> + </select> + </td> + </tr> + <tr> + <td width="35%" align=right>User Full Name:</td> + <td width="65%"> + <input type="text" name="userfullname" value="<?php if(isset($u)) echo $u["userfullname"]; ?>" size="50" maxlength="200" /> + </td> + </tr> + <tr> + <td width="35%" align=right>User Description:</td> + <td width="65%"> + <input type="text" name="userdesc" value="<?php if(isset($u)) echo $u["userdesc"]; ?>" size="50" maxlength="300" /> + </td> + </tr> + <tr> + <td width="35%" align=right>User IP:</td> + <td width="65%"> + <input type="text" name="userip" value="<?php if(isset($u)) echo $u["userpermitip"]; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Password:</td> + <td width="65%"> + <input type="password" name="passwordn1" value="" size="20" maxlength="200" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Retype Password:</td> + <td width="65%"> + <input type="password" name="passwordn2" value="" size="20" maxlength="200" /> + </td> + </tr> + </table> + </center> + <center> + <input type="submit" name="Submit" value="Send" onClick="conf3()"> +<?php if(isset($u)) { ?> + <input type="submit" name="Delete" value="Delete" onClick="conf4()"> +<?php } ?> + <input type="submit" name="Cancel" value="Cancel" onClick="conf5()"> +<?php if(isset($u)) { ?> +<br><br><b>WARNING: deleting a user will completely remove EVERYTHING related to it (including runs, clarifications, etc).<b><br> +<?php } ?> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/balloon.php b/boca-1.5.0/src/balloon.php new file mode 100644 index 0000000..ae5e186 --- /dev/null +++ b/boca-1.5.0/src/balloon.php @@ -0,0 +1,37 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +header('Content-type: image/png'); +ob_end_flush(); + +require_once('fballoon.php'); + +$get_s=false; +if(isset($_GET["s"])) + $get_s=true; +$get_color=null; +if(isset($_GET["color"])) + $get_color=$_GET["color"]; + +balloonpng($_SESSION["locr"],$get_s,$get_color,null); +?> diff --git a/boca-1.5.0/src/balloons/index.html b/boca-1.5.0/src/balloons/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/boca-1.5.0/src/balloons/index.html diff --git a/boca-1.5.0/src/db.php b/boca-1.5.0/src/db.php new file mode 100644 index 0000000..da83707 --- /dev/null +++ b/boca-1.5.0/src/db.php @@ -0,0 +1,307 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +if(isset($_SESSION["locr"]) && isset($_SESSION["loc"]) && !is_readable($_SESSION["locr"] . '/private/conf.php')) { + MSGError('Permission problems in ' . $_SESSION["locr"] . '/private/conf.php - the file must be readable to the user running the web server'); + exit; +} +require_once('hex.php'); +require_once('globals.php'); +require_once('private/conf.php'); + +//para compatibilidade com versoes velhas e novas do php, varias das funcoes foram +//colocadas aqui para guarantir a portabilidade. Infelizmente algumas trocas de nomes +//e parametros aconteceram com a versao 4.2.0 do php. +function DB_lo_open($conn, $file, $mode) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loopen ($conn, $file, $mode); + else + return pg_lo_open ($conn, $file, $mode); +} +function DB_lo_read_tobrowser($contest,$id) { + $str = DB_lo_read($contest,$id); + echo $str; + return true; +} + +function DB_lo_read($contest,$id,$s=-1) { + if (strcmp(phpversion(),'4.2.0')<0) { + if($s<0) { + $str=''; + while (($buf = pg_loread ($id, 100000)) != false) $str .= $buf; + } else + $str = pg_loread ($id, $s); + } + else { + if($s<0) { + $str=''; + while (($buf = pg_lo_read ($id, 100000)) != false) $str .= $buf; + } else + $str = pg_lo_read ($id, $s); + } + if(($str2 = DB_unlock($contest,$str))===false) return $str; + return $str2; +} +function DB_unlock($contest,$str,$c=null) { + if($contest <= 0) return false; + if(($ct = DBContestInfo($contest,$c)) == null) return false; + if(strlen($ct['contestunlockkey']) > 1) { + $ar=explode(',',$ct['contestkeys']); + foreach($ar as $key) { + if(substr($key,0,10) == substr($str,0,10)) { + $pass=decryptData(substr($key,15),$ct['contestunlockkey'],'db_unlock'); + if(substr($pass,0,5) != '#####') continue; + $str2=decryptData($str,$pass,'db_unlock2'); + if($str2=='') continue; + return $str2; + } + } + } + return false; +} + +function DB_lo_import($conn, $file) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loimport ($file, $conn); + else + return pg_lo_import ($conn, $file); +} +function DB_lo_export($contest, $conn, $oid, $file) { + if (strcmp(phpversion(),'4.2.0')<0) + $stat= pg_loexport ($oid, $file, $conn); + else + $stat= pg_lo_export ($oid, $file, $conn); + if($stat===false) return false; + if(!is_readable($file)) return false; + if(($str=DB_unlock($contest,file_get_contents($file),$conn))!==false) { + file_put_contents($file,$str); + return 2; + } + return 1; +} +function DB_lo_close($id) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_loclose ($id); + else + return pg_lo_close ($id); +} +function DB_lo_create($conn) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_locreate ($conn); + else + return pg_lo_create ($conn); +} +function DB_lo_write($fp, $data) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_lowrite ($fp, $data); + else + return pg_lo_write ($fp, $data); +} +function DB_lo_unlink($conn, $data) { + if(($fp = DB_lo_open ($conn, $data, "r"))===false) return false; + DB_lo_close($fp); + if (strcmp(phpversion(),'4.2.0')<0) + return pg_lounlink ($conn, $data); + else + return pg_lo_unlink ($conn, $data); +} +function DB_pg_exec($conn, $data) { + if (strcmp(phpversion(),'4.2.0')<0) + return pg_exec ($conn, $data); + else + return pg_query ($conn, $data); +} +function escape_string($str) { + if(strcmp(phpversion(),'4.2.0')<0) + return addslashes($str); + else + return pg_escape_string($str); +} + +//abrir conexao com o banco de dados +//temos aqui um problema de seguranca. A senha/usuario para acesso ao postgresql +//fica guardada em texto plano em um arquivo com permissao de acesso para todos com shell +//na maquina. O melhor a fazer eh configurar o postgres para permitir acesso no banco de +//dados do boca ao usuario dono desses arquivos php. Esses problemas nao existem quando +//shell no servidor do boca+postgres eh restrito. +function DBConnect($forcenew=false) { + // procura por arquivo com as configuracao. se nao achar, usa padroes + $conf = globalconf(); + if($conf["dblocal"]=="true") { + if($forcenew) + $conn = @pg_connect ("connect_timeout=10 dbname=".$conf["dbname"]." user=".$conf["dbuser"]. + " password=".$conf["dbpass"],PGSQL_CONNECT_FORCE_NEW); + else + $conn = @pg_connect ("connect_timeout=10 dbname=".$conf["dbname"]." user=".$conf["dbuser"]. + " password=".$conf["dbpass"]); + } else { + if($forcenew) + $conn = @pg_connect ("connect_timeout=10 host=".$conf["dbhost"]." port=".$conf["dbport"]." dbname=".$conf["dbname"]. + " user=".$conf["dbuser"]." password=".$conf["dbpass"],PGSQL_CONNECT_FORCE_NEW); + else + $conn = @pg_connect ("connect_timeout=10 host=".$conf["dbhost"]." port=".$conf["dbport"]." dbname=".$conf["dbname"]. + " user=".$conf["dbuser"]." password=".$conf["dbpass"]); + } + if (!$conn) { + LOGError("Unable to connect to database (${conf["dbhost"]},${conf["dbname"]},${conf["dbuser"]})."); + MSGError("Unable to connect to database (${conf["dbhost"]}:${conf["dbport"]},${conf["dbname"]},${conf["dbuser"]}). ". + "Is it running? Is the DB password in conf.php correct?"); + exit; + } + DBExecNonStop($conn,"SET NAMES '${conf["dbclientenc"]}'","set client encoding"); + return $conn; +} +//fecha a conexao com o banco (isso nao eh realmente necessario, ja que o php/apache cuidam do servico) +function DBClose($c) { + pg_close($c); +} +//executar instrucao no banco de dados, sem finalizar a execucao do php +//em caso de erro (mas com uma chamada para a funcao LOGLevel) +//$conn eh a conexao com o banco +//$sql eh a instrucao sql +//$txt eh um pequeno texto descrevendo o que esta sendo feito no sql +function DBExecNonStop($conn,$sql,$txt='') { + if($txt=='') $txt='unknown at '.getFunctionName(); + $result = @DB_pg_exec ($conn, $sql); + if (!$result) { + LOGLevel("Unable to exec SQL in the database ($txt). " . + " Error=(" . pg_errormessage($conn) . ")", 2); + } + return $result; +} +//executar instrucao no banco de dados, finalizando a execucao do php +//em caso de erro (alem da chamada para a funcao LOGLevel e alerta na tela) +//$conn eh a conexao com o banco +//$sql eh a instrucao sql +//$txt eh um pequeno texto descrevendo o que esta sendo feito no sql +function DBExec($conn,$sql,$txt='') { + if($txt=='') $txt='unknown at '.getFunctionName(); + $result = DB_pg_exec ($conn, $sql); + if (!$result) { + LOGError("Unable to exec SQL in the database ($txt). " . + " SQL=(" . sanitizeText(str_replace("\n", " ",$sql)) . "Error=(" . sanitizeText(str_replace("\n", " ",pg_errormessage($conn))) . ")"); + MSGError("Unable to exec SQL in the database ($txt). Aborting."); + exit; + } + return $result; +} +//executar instrucao no banco de dados, sem finalizar a execucao do php +//mesmo em caso de erro (apenas uma janela de aviso tentara ser mostrada ao usuario +//$conn eh a conexao com o banco +//$sql eh a instrucao sql +//$txt eh um pequeno texto descrevendo o que esta sendo feito no sql +function DBExecNoSQLLog($sql,$txt='') { + if($txt=='') $txt='unknown at '.getFunctionName(); + $conn = DBConnect(true); + $result = DB_pg_exec ($conn, $sql); + pg_close($conn); + if (!$result) { + MSGError("Unable to exec SQL in the database ($txt)."); + } + return $result; +} +//devolve o numero de linhas da consulta +function DBnlines ($result) { + return pg_numrows ($result); +} +//pega uma linha da consulta no formato de array +function DBRow ($r, $i) { + return pg_fetch_array ($r, $i, PGSQL_ASSOC); +} +//faz a consulta e pega uma linha da consulta no formato de array +//$sql eh a consulta em sql +//$i eh a linha desejada, comecando de zero +//$txt eh uma descricao da consulta sendo feita +function DBGetRow ($sql,$i,$c=null,$txt='') { + if($txt=='') $txt='unknown at '.getFunctionName(); + if($c==null) + $c = DBConnect(); + $r = DBExec($c,$sql,$txt); + if (DBnlines($r) < $i+1) return null; + $a = DBRow ($r, $i); + if (!$a) { + LOGError("Unable to get row $i from a query ($txt). SQL=(" . $sql . ")"); + MSGError("Unable to get row from query ($txt)."); + exit; + } + return $a; +} +function DBDropDatabase() { + $conf = globalconf(); + if($conf["dblocal"]=="true") + $conn = pg_connect ("connect_timeout=10 dbname=template1 user=".$conf["dbsuperuser"]." password=".$conf["dbsuperpass"]); + else + $conn = pg_connect ("connect_timeout=10 host=".$conf["dbhost"]." port=".$conf["dbport"]." dbname=template1 user=".$conf["dbsuperuser"]. + " password=".$conf["dbsuperpass"]); + if(!$conn) { + MSGError("Unable to connect to template1 as ".$conf["dbsuperuser"]); + exit; + } + $r = DBExecNonStop($conn, "drop database ${conf["dbname"]}", "DBDropDatabase(drop)"); +} +// pg_connect ("options='--client_encoding=UTF8' dbname=template1 ... ???? +function DBCreateDatabase() { + $conf = globalconf(); + if($conf["dblocal"]=="true") + $conn = pg_connect ("connect_timeout=10 dbname=template1 user=".$conf["dbsuperuser"]." password=".$conf["dbsuperpass"]); + else + $conn = pg_connect ("connect_timeout=10 host=".$conf["dbhost"]." port=".$conf["dbport"]." dbname=template1 user=".$conf["dbsuperuser"]. + " password=".$conf["dbsuperpass"]); + + if(!$conn) { + MSGError("Unable to connect to template1 as ".$conf["dbsuperuser"]); + exit; + } + $r = DBExec($conn, "create database ${conf["dbname"]} with encoding = '${conf["dbencoding"]}'", "DBCreateDatabase(create)"); +} + +function DBcrc($contest,$id, $c=null) { + $docommit=false; + if($c == null) { + $docommit=true; + $c = DBConnect(); + DBExec($c, "begin work", "DBcrc(begin)"); + } + if(($f = DB_lo_open($c, $id, "r")) === false) { + if($docommit) + DBExec($c, "commit work", "DBcrc(commit)"); + // just to return a unique string that will not match any other... + return "no-HASH-" . rand() . "-" . rand() . "-" . time(); + } + $str = DB_lo_read($contest,$f); + DB_lo_close($f); + if($docommit) + DBExec($c, "commit work", "DBcrc(commit)"); + return myshorthash($str); +} + +require_once('flog.php'); +require_once('fclar.php'); +require_once('frun.php'); +require_once('ftask.php'); +require_once('fproblem.php'); +require_once('flanguage.php'); +require_once('fscore.php'); +require_once('fanswer.php'); +require_once('fcontest.php'); +require_once('fbkp.php'); +require_once('fextdata.php'); +require_once('fzip.php'); +require_once('fballoon.php'); +// eof +?> diff --git a/boca-1.5.0/src/fanswer.php b/boca-1.5.0/src/fanswer.php new file mode 100644 index 0000000..b689a72 --- /dev/null +++ b/boca-1.5.0/src/fanswer.php @@ -0,0 +1,151 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +function DBDropAnswerTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"answertable\"", "DBDropAnswerTable(drop table)"); +} +function DBCreateAnswerTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"answertable\" ( +\"contestnumber\" int4 NOT NULL, -- (id do concurso) +\"answernumber\" int4 NOT NULL, -- (id da reposta) +\"runanswer\" varchar(50) NOT NULL, -- (reposta dada no julgamento) +\"yes\" bool DEFAULT 'f' NOT NULL, -- (flag para indicar se conta ponto) +\"fake\" bool DEFAULT 'f' NOT NULL, -- (flag para indicar se eh resposta valida) +\"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +-- (tipos possiveis de respostas dos juizes. O flag eh para indicar se a resposta eh YES ou NO.) +CONSTRAINT \"answer_pkey\" PRIMARY KEY (\"contestnumber\", \"answernumber\"), +CONSTRAINT \"contest_fk\" FOREIGN KEY (\"contestnumber\") REFERENCES \"contesttable\" (\"contestnumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateAnswerTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"answertable\" FROM PUBLIC", "DBCreateAnswerTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"answertable\" TO \"".$conf["dbuser"]."\"", "DBCreateAnswerTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"answer_index\" ON \"answertable\" USING btree ". + "(\"contestnumber\" int4_ops, \"answernumber\" int4_ops)", "DBCreateAnswerTable(create index)"); +} + +/////////////////////////////////funcoes de respostas a runs/////////////////////////////////////////// +//recebe o numero do contest +//devolve um array, onde cada linha tem os atributos number (numero da resposta) e desc (descricao da resposta) +function DBGetAnswers($contest) { + $c = DBConnect(); + $r = DBExec($c, "select distinct a.answernumber as number, a.runanswer as desc, a.yes as yes, a.fake as fake ". + "from answertable as a where a.contestnumber=$contest and a.runanswer !~ '(DEL)' order by a.answernumber", "DBGetAnswers(get answers)"); + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) + $a[$i] = DBRow($r,$i); + return $a; +} + +//recebe o numero do contest e o numero da resposta e remove-a caso seu tipo nao seja fake +function DBDeleteAnswer($contest,$param,$c=null) { + $ac=array('number'); + foreach($ac as $key) { + if(!isset($param[$key])) return false; + $$key = sanitizeText($param[$key]); + } + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBDeleteAnswer(transaction)"); + } + $r = DBExec($c, "select * from answertable where contestnumber=$contest and answernumber=$number ". + "and fake='f' for update", "DBDeleteAnswers(delete)"); + if(DBnlines($r)>0) { + $a = DBRow($r,0); + $r = DBExec($c, "update answertable set runanswer='".$a["runanswer"] ."(DEL)', updatetime=".time(). + " where contestnumber=$contest and answernumber=$number ". + "and fake='f'", "DBDeleteAnswers(update)"); + $r = DBExec($c,"select runnumber as number, runsitenumber as site from runtable where contestnumber=$contest and runanswer=$number for update"); + $n = DBnlines($r); + for ($i=0;$i<$n;$i++) { + $a = DBRow($r,$i); + DBRunDelete($a["number"],$a["site"],$contest,$_SESSION["usertable"]["usernumber"],$_SESSION["usertable"]["usersitenumber"]); + } + } + if($cw) DBExec($c, "commit", "DBDeleteAnswer(commit)"); + LOGLevel("Answer $number deleted from contest $contest (user=".$_SESSION["usertable"]["username"]."/".$_SESSION["usertable"]["usersitenumber"].")", 2); + return true; +} + +//insere nova resposta (ou altera o conteudo se a mesma ja existir) +function DBNewAnswer($contest, $param, $c=null) { + if(isset($param["action"]) && $param["action"]=="delete") { + return DBDeleteAnswer($contestnumber, $param, $c); + } + + $ac=array('number','name','yes'); + $type['number']=1; + foreach($ac as $key) { + if(!isset($param[$key])) { + MSGError("DBNewAnswer param error: $key is not set"); + return false; + } + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewAnswer param error: $key is not numeric"); + return false; + } + } + $t = time(); + $updatetime=$t; + if(isset($param['updatetime']) && is_numeric($param["updatetime"])) $updatetime=$param["updatetime"]; + + if($yes!="t") $y = "f"; + else $y = "t"; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBNewAnswer(transaction)"); + } + $r = DBExec($c, "select * from answertable as a where a.contestnumber=$contest and a.answernumber=$number for update", + "DBNewAnswer(get answer)"); + $n = DBnlines($r); + $ret=1; + if ($n == 0) { + $ret=2; + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, updatetime) values " . + "($contest, $number, '$name', '$y', $t)", "DBNewAnswer(insert answer)"); + if($cw) DBExec($c, "commit work", "DBNewAnswer(commit)"); + LOGLevel("Answer $number inserted (contest=$contest,user=".$_SESSION["usertable"]["username"]."/".$_SESSION["usertable"]["usersitenumber"].")", 2); + } else { + $lr = DBRow($r,0); + if($updatetime > $lr['updatetime']) { + $ret=2; + DBExec($c, "update answertable set runanswer='$name', yes='$y', updatetime=". $updatetime . " where ". + "contestnumber=$contest and answernumber=$number and fake='f'", "DBNewAnswer(update answer)"); + if($cw) DBExec($c, "commit work", "DBNewAnswer(commit)"); + LOGLevel("Answer $number updated (contest=$contest,user=".$_SESSION["usertable"]["username"]."/".$_SESSION["usertable"]["usersitenumber"].")", 2); + } else { + if($cw) DBExec($c, "commit work", "DBNewAnswer(commit)"); + } + } + return $ret; +} +// eof +?> diff --git a/boca-1.5.0/src/favicon.ico b/boca-1.5.0/src/favicon.ico Binary files differnew file mode 100644 index 0000000..a64595a --- /dev/null +++ b/boca-1.5.0/src/favicon.ico diff --git a/boca-1.5.0/src/fballoon.php b/boca-1.5.0/src/fballoon.php new file mode 100644 index 0000000..ffe6596 --- /dev/null +++ b/boca-1.5.0/src/fballoon.php @@ -0,0 +1,60 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +function balloonpng($dir,$get_s,$get_color=null,$get_file=null) { + if($get_s) + $smile=imagecreatefrompng($dir . "/images/smallballoontransp.png"); + else + $smile=imagecreatefrompng($dir . "/images/bigballoontransp.png"); + + imageSaveAlpha($smile, true); + if($get_color != null) { + $r = hexdec( substr($get_color, 0, 2) ); + $g = hexdec( substr($get_color, 2, 2) ); + $b = hexdec( substr($get_color, 4, 2) ); + + $kek=imagecolorallocate($smile,$r,$g,$b); + if($get_s) + imagefill($smile,5,5,$kek); + else + imagefill($smile,12,25,$kek); + } + if($get_file != null) + imagepng($smile,$get_file); + else + imagepng($smile); +} + +function balloonurl($color) { + $locr=$_SESSION['locr']; + $loc=$_SESSION['loc']; + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + if(!is_readable($locr . $ds . 'balloons' . $ds . md5($color) . '.png')) { + if($color<0 || $color=='') + @copy($locr. $ds . 'images' . $ds . 'bigballoonboca1.png', $locr . $ds . 'balloons' . $ds . md5($color) . '.png'); + else + balloonpng($locr,false,$color,$locr . $ds . 'balloons' . $ds . md5($color) . '.png'); + if(!is_readable($locr . $ds . 'balloons' . $ds . md5($color) . '.png')) { + return $loc . "/images/bigballoontransp.png"; +// return $loc . "/balloon.php?color=" . $color; + } + } + return $loc . "/balloons/" . md5($color) . '.png'; +} +?> diff --git a/boca-1.5.0/src/fbkp.php b/boca-1.5.0/src/fbkp.php new file mode 100644 index 0000000..b5bcd97 --- /dev/null +++ b/boca-1.5.0/src/fbkp.php @@ -0,0 +1,172 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +function DBDropBkpTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"bkptable\"", "DBDropBkpTable(drop table)"); +} +function DBCreateBkpTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"bkptable\" ( +\"contestnumber\" int4 NOT NULL, -- (id do concurso) +\"sitenumber\" int4 NOT NULL, -- (local de origem da submissao) +\"bkpnumber\" int4 NOT NULL, -- (numero da submissao) +\"usernumber\" int4 NOT NULL, -- (numero do time) +\"bkpdate\" int4 NOT NULL, -- (dia/hora da submissao no local de origem) +\"bkpfilename\" varchar(200) NOT NULL, -- (nome do arquivo submetido) +\"bkpdata\" oid NOT NULL, -- (codigo fonte do arquivo submetido) +\"bkpstatus\" varchar(50) NOT NULL, +\"bkpsize\" int4 NOT NULL, +\"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +CONSTRAINT \"bkp_pkey\" PRIMARY KEY (\"contestnumber\", \"sitenumber\", \"bkpnumber\"), +CONSTRAINT \"user_fk\" FOREIGN KEY (\"contestnumber\", \"sitenumber\", \"usernumber\") + REFERENCES \"usertable\" (\"contestnumber\", \"usersitenumber\", \"usernumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE)", "DBCreateBkpTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"bkptable\" FROM PUBLIC", "DBCreateBkpTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"bkptable\" TO \"".$conf["dbuser"]."\"", "DBCreateBkpTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"bkp_index\" ON \"bkptable\" USING btree ". + "(\"contestnumber\" int4_ops, \"sitenumber\" int4_ops, \"bkpnumber\" int4_ops)", + "DBCreateBkpTable(create bkp_index)"); + $r = DBExec($c, "CREATE INDEX \"bkp_index2\" ON \"bkptable\" USING btree ". + "(\"contestnumber\" int4_ops, \"sitenumber\" int4_ops, \"usernumber\" int4_ops)", + "DBCreateBkpTable(create bkp_index2)"); +} + +///////////////////////////////funcoes de runs/////////////////////////////////////////////////////// +function DBBkpDelete($number,$site,$contest,$user,$adm='') { + $c = DBConnect(); + DBExec($c, "begin work", "DBBkpDelete(transaction)"); + $sql = "select r.bkpdata as oid from bkptable as r where r.contestnumber=$contest and " . + "r.sitenumber=$site and r.bkpnumber=$number and r.usernumber=$user"; + $r = DBExec ($c, $sql . " for update", "DBBkpDelete(get bkp for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBBkpDelete(rollback)"); + LogLevel("Unable to delete a bkp. ". + "(bkp=$number, site=$site, contest=$contest, user=$user)",1); + return false; + } + $temp = DBRow($r, 0); + + if (DB_lo_unlink($c, $temp['oid']) === false) { + DBExec($c, "rollback work", "DBBkpDelete(rollback-import)"); + LOGError("Unable to delete a large object (user=$user, contest=$contest, site=$site, number=$number)."); + MSGError("problem deleting bkp from database. Contact an admin."); + exit; + } + if (strlen($adm)>0) $str = "deleted by " . $adm; + else $str="deleted"; + DBExec($c, "update bkptable set bkpstatus='$str', updatetime=" . + time()." where contestnumber=$contest and bkpnumber=$number and sitenumber=$site", + "DBBkpDelete(update bkp)"); + + DBExec($c, "commit work", "DBBkpDelete(commit)"); + LOGLevel("Bkp deleted (bkp=$number, site=$site, contest=$contest, user=$user).", 3); + return true; +} + +function DBNewBkp($contest, $site, $user, $filename, $filepath, $size) { + $c = DBConnect(); + DBExec($c, "begin work", "DBNewBkp(transaction)"); + DBExec($c, "lock table bkptable"); + $sql = "select count(*) as n from " . + "bkptable where sitenumber=$site and contestnumber=$contest and usernumber=$user and bkpstatus='active'"; + $r = DBExec($c, $sql, "DBNewBkp(get bkp of user)"); + if (DBnlines($r) != 1) { + DBExec($c, "rollback work", "DBNewBkp(rollback-toomanyerror)"); + LOGError("Error in bkp table. SQL=(" . $sql . ")"); + MSGError("Error in bkp table."); + exit; + } + $a = DBRow($r,0); + if($a['n']>100) { + DBExec($c, "rollback work", "DBNewBkp(rollback-toomany)"); + LOGError("Too many bkps from user=$user, site=$site, contest=$contest.",2); + MSGError("Too many bkp files. Try remove some of them before uploading another."); + return false; + } + + $sql = "select max(bkpnumber) as nextbkp from " . + "bkptable where sitenumber=$site and contestnumber=$contest"; + $r = DBExec($c, $sql, "DBNewBkp(get bkp for update)"); + if (DBnlines($r) != 1) { + DBExec($c, "rollback work", "DBNewBkp(rollback-max)"); + LOGError("Error in bkp table. SQL=(" . $sql . ")"); + MSGError("Error in bkp table."); + exit; + } + $a = DBRow($r,0); + $t = time(); + $n = $a["nextbkp"] + 1; + + if (($oid = DB_lo_import($c, $filepath)) === false) { + DBExec($c, "rollback work", "DBNewBkp(rollback-import)"); + LOGError("Unable to create a large object for file $filepath."); + MSGError("problem importing bkp to database. Contact an admin now!"); + exit; + } + + DBExec($c, "INSERT INTO bkptable (contestnumber, sitenumber, bkpnumber, usernumber, bkpdate, bkpfilename, bkpdata, bkpstatus, bkpsize) " . + "VALUES ($contest, $site, $n, $user, $t, '$filename', $oid, 'active', $size)", + "DBNewBkp(insert bkp)"); + + DBExec($c, "commit work", "DBNewBkp(commit)"); + LOGLevel("User $user submitted a bkp (#$n) on site #$site " . + "(filename=$filename, contest=$contest).",2); + +/* // isso gera problemas de portabilidade e de seguranca (quando outros usuarios tambem tem shell + // no servidor e podem construir paginas web. Eles podem usar essas paginas para acessar esses arquivos, + // pois os mesmos ficaram com dono apache/www-data/etc) + umask(0077); + @mkdir("/tmp/boca"); + if (!move_uploaded_file ($filepath, + "/tmp/boca/contest${contest}.site${site}.run${n}.user${user}.problem${problem}.time${t}.${filename}")) + LOGLevel("Run not saved as file (run=$n,site=$site,contest=$contest", 1); +*/ +} +//recebe o numero do contest, o numero do site e o numero do usuario +//devolve um array, onde cada linha tem os atributos +// number (numero da run) +// timestamp (hora da criacao da run) +// problem (nome do problema) +// status (situacao da run) +// answer (texto com a resposta) +function DBUserBkps($contest,$site,$user) { + $c = DBConnect(); + $st = "select distinct r.bkpnumber as number, r.usernumber as usernumber, r.sitenumber as usersitenumber, r.bkpdate as timestamp, " . + "r.bkpstatus as status, r.bkpfilename as filename, r.bkpdata as oid, r.bkpsize as size " . + "from bkptable as r " . + "where r.contestnumber=$contest"; + if($site>0 || $user>0) + $st = $st . " and r.sitenumber=$site and r.usernumber=$user and r.bkpstatus='active'"; + $st = $st . " order by r.bkpnumber"; + $r = DBExec($c, $st, "DBUserBkps(get bkps)"); + $n = DBnlines($r); + + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + return $a; +} +// eof +?> diff --git a/boca-1.5.0/src/fclar.php b/boca-1.5.0/src/fclar.php new file mode 100644 index 0000000..d0e6481 --- /dev/null +++ b/boca-1.5.0/src/fclar.php @@ -0,0 +1,490 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +function DBDropClarTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table clartable", "DBDropClarTable(drop table)"); +} +function DBCreateClarTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE clartable ( +contestnumber int4 NOT NULL, -- (id do concurso) +clarsitenumber int4 NOT NULL, -- (local de origem da pergunta) +clarnumber int4 NOT NULL, -- (id da pergunta) +usernumber int4 NOT NULL, -- (id do usuario) +clardate int4 NOT NULL, -- (dia/hora da pergunta no local de origem) +clardatediff int4 NOT NULL, -- (diferenca entre inicio da competicao e dia/hora da pergunta em seg) +clardatediffans int4 NOT NULL, -- (diferenca entre inicio da competicao e dia/hora da resposta em seg) +clarproblem int4 NOT NULL, -- (id do problema) +clardata text NOT NULL, -- (texto da pergunta) +claranswer text, -- (resposta dada aa pergunta) +clarstatus varchar(20) NOT NULL, -- (status da submissao: openclar, answering, answered, + -- answeredsite, answeredall, deleted) +clarjudge int4 DEFAULT NULL, -- (juiz que esta julgando) +clarjudgesite int4 DEFAULT NULL, -- (juiz que esta julgando) +updatetime int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +CONSTRAINT clar_pkey PRIMARY KEY (contestnumber, clarsitenumber, clarnumber), +CONSTRAINT user_fk FOREIGN KEY (contestnumber, clarsitenumber, usernumber) + REFERENCES usertable (contestnumber, usersitenumber, usernumber) + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, +CONSTRAINT problem_fk FOREIGN KEY (contestnumber, clarproblem) + REFERENCES problemtable (contestnumber, problemnumber) + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateClarTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON clartable FROM PUBLIC", "DBCreateClarTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON clartable TO \"".$conf["dbuser"]."\"", "DBCreateClarTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX clar_index ON clartable USING btree ". + "(contestnumber int4_ops, clarsitenumber int4_ops, clarnumber int4_ops)", + "DBCreateClarTable(create clar_index)"); + $r = DBExec($c, "CREATE INDEX clar_index2 ON clartable USING btree ". + "(contestnumber int4_ops, clarsitenumber int4_ops, usernumber int4_ops)", + "DBCreateClarTable(create clar_index2)"); +} + +//////////////////////////////funcoes de clarifications///////////////////////////////////////// +//recebe o numero do contest, o numero do site e o numero do usuario +//devolve um array, onde cada linha tem os atributos +// number (numero da clarification) +// timestamp (hora da criacao da clar) +// problem (nome do problema) +// status (situacao da clarification) +// question (texto da clar) +// answer (texto com a resposta) +function DBUserClars($contest,$site,$user) { + $b = DBSiteInfo($contest, $site); + if ($b == null) { + exit; + } + + $t = $b["currenttime"]; + + $c = DBConnect(); + $r = DBExec($c, "select distinct c.clarsitenumber as site, c.clarnumber as number, c.clardatediff as timestamp, " . + "p.problemname as problem, c.clarstatus as status, c.clardata as question, " . + "c.claranswer as answer, c.updatetime as updatetime " . + "from clartable as c, problemtable as p " . + "where c.contestnumber=$contest and p.contestnumber=c.contestnumber and " . + "c.clarproblem=p.problemnumber and not clarstatus ~ 'deleted' and " . + "(c.clardatediffans<=$t or (c.clarstatus !~ 'answered' and c.clardatediff<=$t)) and " . + "((clarsitenumber=$site and c.usernumber=$user) or (clarstatus ~ 'answeredall') or ". + " (clarstatus ~ 'answeredsite' and clarsitenumber=$site)) order by c.updatetime desc", + "DBUserClars(get clars)"); + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) + $a[$i] = DBRow($r,$i); + return $a; +} +//recebe o numero do contest, o numero do site do juiz e o numero do juiz +//devolve um array, onde cada linha tem os atributos +// number (numero da clarification) +// timestamp (hora da criacao da clar) +// problem (nome do problema) +// status (situacao da clarification) +// question (texto da clar) +// answer (texto com a resposta) +function DBJudgedClars($contest,$site,$user) { + $c = DBConnect(); + $r = DBExec($c, "select distinct c.clarsitenumber as site, c.clarnumber as number, c.clardatediff as timestamp, " . + "p.problemname as problem, c.clarstatus as status, c.clardata as question, " . + "c.claranswer as answer, c.updatetime " . + "from clartable as c, problemtable as p " . + "where c.contestnumber=$contest and p.contestnumber=c.contestnumber and " . + "c.clarproblem=p.problemnumber and c.clarjudge=$user and " . + "c.clarjudgesite=$site order by c.updatetime", "DBJudgesClars(get clars)"); + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) + $a[$i] = DBRow($r,$i); + return $a; +} +//responde uma clarification. Recebe o numero do contest, site do usuario, num do usuario, site da clar, +//numero da clar e a resposta. +//tenta alterar o status para 'answered...', dependendo do type. +function DBUpdateClar($contest, $usersite, $usernumber, $clarsite, $clarnumber, $answer, $type) { + return DBUpdateClarC($contest, $usersite, $usernumber, $clarsite, $clarnumber, $answer, $type, 0); +} +function DBChiefUpdateClar($contest, $usersite, $usernumber, $clarsite, $clarnumber, $answer, $type) { + return DBUpdateClarC($contest, $usersite, $usernumber, $clarsite, $clarnumber, $answer, $type, 1); +} +function DBUpdateClarC($contest, $usersite, $usernumber, $clarsite, $clarnumber, $answer, $type, $chief) { + if(($b = DBSiteInfo($contest, $clarsite)) == null) + exit; + + $c = DBConnect(); + DBExec($c, "begin work", "DBUpdateClarC(transaction)"); + $sql = "select * from clartable as c where c.contestnumber=$contest and " . + "c.clarsitenumber=$clarsite and c.clarnumber=$clarnumber"; + $tx = "Chief"; + if ($chief != 1) { + $sql .= " and c.clarstatus='answering' and " . + "c.clarjudge=$usernumber and clarjudgesite=$usersite for update"; + $tx = "Judge"; + } + $r = DBExec($c, $sql); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBUpdateClarC(rollback)"); + LogLevel("Unable to answer a clar (maybe it was already answered or catched by a chief) " . + "(clar=$clarnumber, site=$clarsite, contest=$contest).",0); + MSGError("Unable to answer the clarification (maybe it was already answered or catched by a chief)"); + return false; + } + + if ($type=="all") $status="answeredall"; + else if ($type=="site") $status="answeredsite"; + else $status="answered"; + + $time = time(); + $t = $b["currenttime"]; + + DBExec($c, "update clartable set clarstatus='$status', clarjudge=$usernumber, clarjudgesite=$usersite, " . + "claranswer='$answer', clardatediffans=$t, updatetime=".time()." " . + "where contestnumber=$contest and clarnumber=$clarnumber and clarsitenumber=$clarsite", + "DBUpdateClarC(update clar)"); + + DBExec($c, "commit work", "DBUpdateClarC(commit)"); + LOGLevel("Clarification updated (clar=$clarnumber, site=$clarsite, contest=$contest, status=$status, " . + "user=$usernumber(site=$usersite)).", 3); + return true; +} +//devolve uma clarification que estava sendo respondida. Recebe o numero da clar, o numero do site e o numero do contest. +//tenta alterar o status para 'openclar'. Se nao conseguir retorna false +function DBChiefClarGiveUp($number,$site,$contest) { + return DBClarGiveUp($number,$site,$contest, -1, -1); +} +function DBClarGiveUp($number,$site,$contest, $usernumber, $usersite) { + $c = DBConnect(); + DBExec($c, "begin work", "DBClarGiveUp(transaction)"); + $sql = "select * from clartable as c where c.contestnumber=$contest and " . + "c.clarsitenumber=$site and c.clarnumber=$number"; + $tx = "Chief"; + if ($usernumber != -1 && $usersite != -1) { + $sql .= " and c.clarstatus='answering' and c.clarjudge=$usernumber and clarjudgesite=$usersite"; + $tx = "Judge"; + } + $r = DBExec($c, $sql . " for update", "DBClarGiveUp(get clar for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBClarGiveUp(rollback)"); + LogLevel("Unable to return a clar (maybe the timeout or a chief returned it first). " . + "(clar=$number, site=$site, contest=$contest)",1); + return false; + } + + DBExec($c, "update clartable set clarstatus='openclar', claranswer='', clarjudge=NULL, " . + "clarjudgesite=NULL, updatetime=".time()." " . + "where contestnumber=$contest and clarnumber=$number and clarsitenumber=$site", + "DBClarGiveUp(update clar)"); + + DBExec($c, "commit work", "DBClarGiveUp(commit)"); + LOGLevel("Clarification returned (clar=$number, site=$site, contest=$contest, user=$usernumber(site=$usersite)).",3); + return true; +} +//seta o status como 'deleted' de uma clarification que estava sendo respondida. Recebe o numero da clar, +//o numero do site e o numero do contest. Se nao conseguir retorna false. +function DBClarDelete($number,$site,$contest,$user,$usersite) { + $c = DBConnect(); + DBExec($c, "begin work", "DBClarDelete(transaction)"); + $r = DBExec($c, "select * from clartable as c where c.contestnumber=$contest and " . + "c.clarsitenumber=$site and c.clarnumber=$number for update", "DBClarDelete(get clar for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBClarDelete(rollback)"); + LogLevel("Unable to delete a clar. " . + "(clar=$number, site=$site, contest=$contest)",1); + return false; + } + + DBExec($c, "update clartable set clarstatus='deleted', clarjudge=$user, clarjudgesite=$usersite, updatetime=" . + time(). " where contestnumber=$contest and clarnumber=$number and clarsitenumber=$site", + "DBClarDelete(update clar)"); + + DBExec($c, "commit work", "DBClarDelete(commit)"); + LOGLevel("Clarification deleted (clar=$number, site=$site, contest=$contest, user=$user(site=$usersite)).", 3); + return true; +} +function DBNewClar($param,$c=null) { + if(isset($param['contestnumber']) && !isset($param['contest'])) $param['contest']=$param['contestnumber']; + if(isset($param['sitenumber']) && !isset($param['site'])) $param['site']=$param['sitenumber']; + if(isset($param['usernumber']) && !isset($param['user'])) $param['user']=$param['usernumber']; + if(isset($param['number']) && !isset($param['clarnumber'])) $param['clarnumber']=$param['number']; + + $ac=array('contest','site','user','problem','question'); + $ac1=array('clarnumber','clardate','clardatediff','clardatediffans','claranswer','clarstatus','clarjudge','clarjudgesite','updatetime'); + $type['contest']=1; + $type['problem']=1; + $type['updatetime']=1; + $type['site']=1; + $type['user']=1; + $type['clarnumber']=1; + $type['clardatediffans']=1; + $type['clardatediff']=1; + $type['clardate']=1; + $type['clarjudge']=1; + $type['clarjudgesite']=1; + foreach($ac as $key) { + if(!isset($param[$key]) || $param[$key]=="") { + MSGError("DBNewClar param error: $key not found"); + return false; + } + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewClar param error: $key is not numeric"); + return false; + } + $$key = sanitizeText($param[$key]); + } + $t = time(); + $clarnumber=-1; + $updatetime = -1; + $clardatediff = -1; + $clardate = $t; + $claranswer=''; + $clardatediffans = 999999999; + $clarjudge='NULL'; + $clarjudgesite='NULL'; + $clarstatus='openclar'; + foreach($ac1 as $key) { + if(isset($param[$key])) { + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewClar param error: $key is not numeric"); + return false; + } + } + } + if($updatetime < 0) + $updatetime=$t; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBNewClar(transaction)"); + } + $insert=true; + if($clarnumber < 0) { + $sql = "select sitenextclar as nextclar from sitetable where sitenumber=$site and contestnumber=$contest for update"; + $r = DBExec($c, $sql, "DBNewClar(get site for update)"); + if (DBnlines($r) != 1) { + DBExec($c, "rollback work", "DBNewClar(rollback-site)"); + LOGError("Unable to find a unique site/contest in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find a unique site/contest in the database. Contact an admin now!"); + exit; + } + $a = DBRow($r,0); + $n = $a["nextclar"] + 1; + $clarnumber = $n; + } else { + $sql = "select * from clartable as t where t.contestnumber=$contest and " . + "t.clarsitenumber=$site and t.clarnumber=$clarnumber"; + $r = DBExec ($c, $sql . " for update", "DBNewClar(get clar for update)"); + $n = DBnlines($r); + if ($n > 0) { + $insert=false; + $lr = DBRow($r,0); + $t = $lr['updatetime']; + } + $n = $clarnumber; + } + DBExec($c, "update sitetable set sitenextclar=$clarnumber, updatetime=" . $t . + " where sitenumber=$site and contestnumber=$contest and sitenextclar<$clarnumber", + "DBNewClar(update site)"); + + if($clardatediff < 0) { + $b = DBSiteInfo($contest, $site, $c); + $dif = $b["currenttime"]; + $clardatediff = $dif; + if ($dif < 0) { + DBExec($c, "rollback work", "DBNewClar(rollback-started)"); + LOGError("Tried to submit a clarification but the contest is not started. SQL=(" . $sql . ")"); + MSGError("The contest is not started yet!"); + return false; + } + if (!$b["siterunning"]) { + DBExec($c, "rollback work", "DBNewClar(rollback-over)"); + LOGError("Tried to submit a clarification but the contest is over. SQL=(" . $sql . ")"); + MSGError("The contest is over!"); + return false; + } + } else { + $dif = $clardatediff; + } + + $ret=1; + if($insert) { + DBExec($c, "INSERT INTO clartable (contestnumber, clarsitenumber, clarnumber, usernumber, clardate, " . + "clardatediff, clardatediffans, clarproblem, clardata, claranswer, clarjudge, clarjudgesite, clarstatus, updatetime) VALUES " . + "($contest, $site, $n, $user, $clardate, $clardatediff, $clardatediffans, $problem, '$question', " . + "'$claranswer', $clarjudge, $clarjudgesite, '$clarstatus', $updatetime)", + "DBNewClar(insert clar)"); + if($cw) DBExec($c, "commit work", "DBNewClar(commit-insert)"); + LOGLevel("User $user submitted a clarification (#$n) on site #$site " . + "(problem=$problem, contest=$contest).",2); + $ret=2; + } else { + if($updatetime > $t) { + $ret=2; + DBExec($c, "update clartable set clardate=$clardate, clardatediff=$clardatediff, " . + "clardatediffans=$clardatediffans, claranswer='$claranswer', clarstatus='$clarstatus', ". + "clarjudge=$clarjudge, clarjudgesite=$clarjudgesite, updatetime=$updatetime, clardata='$question', clarproblem=$problem ". + "where clarnumber=$clarnumber and contestnumber=$contest and clarsitenumber=$site", "DBNewClar(update clar)"); + } + if($cw) DBExec($c, "commit work", "DBNewClar(commit-update)"); + } + return $ret; +/* // isso gera problemas de portabilidade e de seguranca se os demais usuarios tiverem shell no servidor + // por outro lado, garante que as coisas estao guardadas em arquivos fora do banco, caso haja outros problemas. + umask(0077); + @mkdir("/tmp/boca"); + $fp = fopen("/tmp/boca/contest${contest}.site${site}.clar${n}.user${user}.problem${problem}.time${t}", "w"); + if ($fp) { + fwrite($fp, $question); + fclose($fp); + } else + LOGLevel("Clarification not saved as file (clar=$n,site=$site,contest=$contest)", 1); +*/ +} +//pega uma clarification para responder. Recebe o numero da clar, o numero do site e o numero do contest. +//tenta alterar o status para 'answering' e se conseguir, devolve um array com dados da clar. Se nao conseguir, +//retorna false. Se for chief, nao ha restricoes com relacao a outro juiz julgando. Isso deve ser passado na +//variavel $chief +//Retorna no array: contestnumber, sitenumber, number, timestamp (em segundos), problemname, +// problemnumber, question, status +function DBChiefGetClarToAnswer($number,$site,$contest) { + return DBGetClarToAnswerC($number,$site,$contest,1); +} +function DBGetClarToAnswer($number,$site,$contest) { + return DBGetClarToAnswerC($number,$site,$contest,0); +} +function DBGetClarToAnswerC($number,$site,$contest,$chief) { + $c = DBConnect(); + DBExec($c, "begin work", "DBGetClarToAnswerC(transaction)"); + $sql = "select c.contestnumber as contestnumber, c.clarsitenumber as sitenumber, c.claranswer as answer, " . + "c.clarnumber as number, c.clardatediff as timestamp, c.clarstatus as status, " . + "p.problemname as problemname, p.problemnumber as problemnumber, c.clardata as question " . + "from clartable as c, problemtable as p " . + "where c.contestnumber=$contest and p.contestnumber=c.contestnumber and " . + "c.clarproblem=p.problemnumber and c.clarsitenumber=$site and " . + "c.clarnumber=$number"; + if ($chief != 1) { + $sql .= " and (c.clarstatus='openclar' or (c.clarstatus='answering' and " . + "c.clarjudge=".$_SESSION["usertable"]["usernumber"]." and " . + "c.clarjudgesite=".$_SESSION["usertable"]["usersitenumber"]."))"; + $tx = "Chief is answering"; + } + else $tx = "Judge is answering"; + + $r = DBExec($c, $sql . " for update", "DBGetClarToAnswerC(get clar/prob for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBGetClarToAnswerC(rollback)"); + LogLevel("Unable to get a clar (maybe other judge got it first). (clar=$number, site=$site, ". + "contest=$contest)",2); + return false; + } + $a = DBRow($r,0); + if ($a["status"] == "answering") $st = "DNA"; + else $st = "started"; + + if ($chief != 1) { + DBExec($c, "update clartable set clarjudge=" . $_SESSION["usertable"]["usernumber"] . + ", clarstatus='answering', updatetime=".time().", " . + "clarjudgesite=" . $_SESSION["usertable"]["usersitenumber"] . " " . + "where contestnumber=$contest and clarnumber=$number and clarsitenumber=$site", + "DBGetClarToAnswerC(update clar)"); + } + + DBExec($c, "commit work", "DBGetClarToAnswerC(commit)"); + LOGLevel("User got a clarification (clar=$number, site=$site, contest=$contest, status=$status, " . + "user=".$_SESSION["usertable"]["usernumber"]."(site=".$_SESSION["usertable"]["usersitenumber"].")).", 3); + return $a; +} +//recebe o numero do contest, o numero do site (ou -1 para todos) +//devolve um array, onde cada linha tem os atributos +// number (numero da clarification) +// site (numero do site onde a clarification foi criada) +// timestamp (hora da criacao da clar) +// problem (nome do problema) +// status (situacao da clarification) +//(devolve apenas aquelas que a situacao eh <> de answered.*) +// question (texto da clar) +function DBAllClars($contest) { + return DBOpenClarsSNS($contest,"x",-1); +} +function DBAllClarsInSites($contest,$site,$order) { + return DBOpenClarsSNS($contest,$site,-1,$order); +} +//function DBOpenClars($contest) { +// return DBOpenClarsSNS($contest,"x",1); +//} +function DBOpenClarsInSites($contest,$site) { + return DBOpenClarsSNS($contest,$site,1); +} +function DBOpenClarsSNS($contest,$site,$st,$order='clar') { + $c = DBConnect(); + $sql = "select distinct c.clarnumber as number, c.clardatediff as timestamp, c.claranswer as answer, " . + "p.problemname as problem, c.clarstatus as status, c.clardata as question, " . + "c.clarsitenumber as site, c.clarjudge as judge, c.clarjudgesite as judgesite, " . + "c.usernumber as user " . + "from clartable as c, problemtable as p " . + "where c.contestnumber=$contest and p.contestnumber=c.contestnumber and " . + "c.clarproblem=p.problemnumber"; + if ($site != "x") { + $str = explode(",", $site); + $sql .= " and (c.clarstatus='answeredall'"; + for ($i=0;$i<count($str);$i++) { + if (is_numeric($str[$i])) $sql .= " or c.clarsitenumber=".$str[$i]; + } + $sql .= ")"; + } + + if ($st == 1) + $sql .= " and not c.clarstatus ~ 'answered' and not c.clarstatus ~ 'deleted' order by "; + else $sql .= " order by "; + + if($order == "site") + $sql .= "c.clarsitenumber,"; + else if ($order == "status") + $sql .= "c.clarstatus,"; + else if ($order == "judge") + $sql .= "c.clarjudge,c.clarjudgesite,"; + else if ($order == "problem") + $sql .= "p.problemname,"; + else if ($order == "user") + $sql .= "c.usernumber,c.clarsitenumber,"; + + if ($st == 1 || $order == "normal") + $sql .= "c.clarnumber"; + else + $sql .= "c.clardatediff desc"; + + $r = DBExec($c, $sql, "DBOpenClarsSNS(get clar/prob)"); + + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) + $a[$i] = DBRow($r,$i); + return $a; +} +// eof +?> diff --git a/boca-1.5.0/src/fcontest.php b/boca-1.5.0/src/fcontest.php new file mode 100644 index 0000000..8771291 --- /dev/null +++ b/boca-1.5.0/src/fcontest.php @@ -0,0 +1,1237 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA System (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +//Last updated 10/jul/2012 by cassio@ime.usp.br + +function DBDropContestTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"contesttable\"", "DBDropContestTable(drop table)"); +} +function DBCreateContestTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"contesttable\" ( + \"contestnumber\" int4 NOT NULL, -- (id do concurso) + \"contestname\" varchar(100) NOT NULL, -- (nome do concurso) + \"conteststartdate\" int4 NOT NULL, -- (dia/horario de inicio) + \"contestduration\" int4 NOT NULL, -- (duracao em segundos do contest) + \"contestlastmileanswer\" int4, -- (qtd segundos a partir do inicio para nao responder aos times) + \"contestlastmilescore\" int4, -- (qtd segundos a partir do inicio para nao atualizar placar) + \"contestlocalsite\" int4 NOT NULL, -- (id do site local com relacao a este servidor) + \"contestpenalty\" int4 NOT NULL, -- (qtd de segundos perdidos para cada run errada) + \"contestmaxfilesize\" int4 NOT NULL, -- (tamanho max em bytes dos codigos que podem ser submetidos) + \"contestactive\" bool NOT NULL, -- (indica se o contest esta ativo) + \"contestmainsite\" int4 NOT NULL, -- (id do site principal com relacao ao contest) + \"contestkeys\" text NOT NULL, -- (list of keys relevant to the contest) + \"contestunlockkey\" varchar(100) NOT NULL, -- (key to decrypt problem files) + \"contestmainsiteurl\" varchar(200) NOT NULL, -- (id do site principal com relacao ao contest) + \"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +-- (esta tabela eh igual em todos os sites, com excecao do campo contestlocalsite, +-- que guarda qual o site local. Na verdade a ideia eh que todas as tabelas sejam +-- iguais em todos os sites.) + CONSTRAINT \"contest_pkey\" PRIMARY KEY (\"contestnumber\") +)", "DBCreateContestTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"contesttable\" FROM PUBLIC", "DBCreateContestTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"contesttable\" TO \"".$conf["dbuser"]."\"", "DBCreateContestTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"contestnumber_index\" ON \"contesttable\" USING btree ". + "(\"contestnumber\" int4_ops)", "DBCreateContestTable(create index)"); +} +function DBDropSiteTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"sitetable\"", "DBDropSiteTable(drop table)"); +} +function DBCreateSiteTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"sitetable\" ( + \"contestnumber\" int4 NOT NULL, -- (id do concurso) + \"sitenumber\" int4 NOT NULL, -- (id do local) + \"siteip\" varchar(200) NOT NULL, -- (ip publico do servidor do site) + \"sitename\" varchar(50) NOT NULL, -- (nome do local) + \"siteactive\" bool NOT NULL, -- (site ativo?) + \"sitepermitlogins\" bool NOT NULL, -- (logins estao aceitos?) + \"sitelastmileanswer\" int4, -- (hora (em seg do inicio) que este site para de responder aos times) + \"sitelastmilescore\" int4, -- (hora (em seg do inicio) que o placar eh congelado neste site) + \"siteduration\" int4, -- (tamanho da competicao em segundos) + \"siteautoend\" bool, -- (?) + \"sitejudging\" text, -- (indica quais sites sao julgados neste site) + \"sitetasking\" text, -- (indica quais sites sao processadas as tasks neste site) + \"siteglobalscore\" varchar(50) DEFAULT '' NOT NULL, -- (indica se este site deve mostrar placar global) + \"sitescorelevel\" int4 DEFAULT 0 NOT NULL, -- (indica o nivel de detalhes do placar exibido aos times) + \"sitenextuser\" int4 DEFAULT 0 NOT NULL, + \"sitenextclar\" int4 DEFAULT 0 NOT NULL, + \"sitenextrun\" int4 DEFAULT 0 NOT NULL, + \"sitenexttask\" int4 DEFAULT 0 NOT NULL, + \"sitemaxtask\" int4 DEFAULT 8 NOT NULL, + \"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) + \"sitechiefname\" varchar(20) DEFAULT '' NOT NULL, -- (username do juiz chefe, se existir) +-- (esta tabela contem uma linha para cada site do contest) + \"siteautojudge\" bool DEFAULT 'f', + \"sitemaxruntime\" int4 DEFAULT 600 NOT NULL, + \"sitemaxjudgewaittime\" int4 DEFAULT 900 NOT NULL, + CONSTRAINT \"site_pkey\" PRIMARY KEY (\"contestnumber\", \"sitenumber\"), + CONSTRAINT \"contest_fk\" FOREIGN KEY (\"contestnumber\") REFERENCES \"contesttable\" (\"contestnumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateSiteTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"sitetable\" FROM PUBLIC", "DBCreateSiteTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"sitetable\" TO \"".$conf["dbuser"]."\"", "DBCreateSiteTable(grant bocauser)"); + $r = DBexec($c, "CREATE UNIQUE INDEX \"site_index\" ON \"sitetable\" USING btree ". + "(\"contestnumber\" int4_ops, \"sitenumber\" int4_ops)", "DBCreateSiteTable(create index)"); +} +function DBDropSiteTimeTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"sitetimetable\"", "DBDropSiteTimeTable(drop table)"); +} +function DBCreateSiteTimeTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"sitetimetable\" ( + \"contestnumber\" int4 NOT NULL, -- (id do concurso) + \"sitenumber\" int4 NOT NULL, -- (id do local) + \"sitestartdate\" int4 NOT NULL, -- (hora que o local comecou) + \"siteenddate\" int4 NOT NULL, -- (hora que o local deve terminar, zero nao terminado) + \"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +-- (esta tabela contem uma linha para cada reinicio de um site do contest) + CONSTRAINT \"sitetime_pkey\" PRIMARY KEY (\"contestnumber\", \"sitenumber\", \"sitestartdate\"), + CONSTRAINT \"site_fk\" FOREIGN KEY (\"contestnumber\", \"sitenumber\") + REFERENCES \"sitetable\" (\"contestnumber\", \"sitenumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateSiteTimeTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"sitetimetable\" FROM PUBLIC", "DBCreateSiteTimeTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"sitetimetable\" TO \"".$conf["dbuser"]."\"", "DBCreateSiteTimeTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"sitetime_index\" ON \"sitetimetable\" USING btree ". + "(\"contestnumber\" int4_ops, \"sitenumber\" int4_ops, \"sitestartdate\" int4_ops)", + "DBCreateSiteTimeTable(create index)"); + $r = DBexec($c, "CREATE INDEX \"sitetimesite_index\" ON \"sitetimetable\" USING btree ". + "(\"contestnumber\" int4_ops, \"sitenumber\" int4_ops)", "DBCreateSiteTimeTable(create site_index)"); +} +function DBDropUserTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"usertable\"", "DBDropUserTable(drop table)"); +} +function DBCreateUserTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"usertable\" ( + \"contestnumber\" int4 NOT NULL, -- (id do concurso) + \"usersitenumber\" int4 NOT NULL, -- (id do local do time) + \"usernumber\" int4 NOT NULL, -- (id do usuario) + \"username\" varchar(20) NOT NULL, -- (nome do usuario) + \"userfullname\" varchar(200) NOT NULL, -- (nome completo do usuario) + \"userdesc\" varchar(300), -- (descricao: escola ou integrantes ou etc) + \"usertype\" varchar(20) NOT NULL, -- (judge, team, admin, system) + \"userenabled\" bool DEFAULT 't' NOT NULL, -- (usuario ativo) + \"usermultilogin\" bool DEFAULT 'f' NOT NULL, -- (usuario pode se logar multiplas vezes) + \"userpassword\" varchar(200) DEFAULT '', -- (senha) + \"userip\" varchar(300), -- (ip do ult acesso) + \"userlastlogin\" int4, -- (data em seg desde epoch do ult login) + \"usersession\" varchar(50) DEFAULT '', -- (sessao do usuario) + \"usersessionextra\" varchar(50) DEFAULT '', -- (sessao do usuario) + \"userlastlogout\" int4, -- (data em seg desde epoch do ult logout) + \"userpermitip\" varchar(300), -- (ip permitido para acesso) + \"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +-- (esta tabela contem uma linha para cada usuario, seja ele administrador, juiz ou time. ) + \"usericpcid\" varchar(50) DEFAULT '', -- (compatibilidade com dados do ICPC) + CONSTRAINT \"user_pkey\" PRIMARY KEY (\"contestnumber\", \"usersitenumber\", \"usernumber\"), + CONSTRAINT \"site_fk\" FOREIGN KEY (\"contestnumber\", \"usersitenumber\") + REFERENCES \"sitetable\" (\"contestnumber\", \"sitenumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateUserTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"usertable\" FROM PUBLIC", "DBCreateUserTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"usertable\" TO \"".$conf["dbuser"]."\"", "DBCreateUserTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"user_index\" ON \"usertable\" USING btree ". + "(\"contestnumber\" int4_ops, \"usersitenumber\" int4_ops, \"usernumber\" int4_ops)", + "DBCreateUserTable(create user_index)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"user_index2\" ON \"usertable\" USING btree ". + "(\"contestnumber\" int4_ops, \"usersitenumber\" int4_ops, \"username\" varchar_ops)", + "DBCreateUserTable(create user_index2)"); +} + +//////////////////////////////funcoes de usuarios/sites/contests/////////////////////////////////////// +function DBFakeContest() { + $c = DBConnect(); + DBExec($c, "begin work"); + DBExec($c, "insert into contesttable (contestnumber, contestname, conteststartdate, contestduration, ". + "contestlastmileanswer, contestlastmilescore, contestlocalsite, contestpenalty, contestmaxfilesize, ". + "contestactive, contestmainsite, contestmainsiteurl,contestkeys,contestunlockkey) " . + "values (0, 'Fake contest (just for initial purposes)', ". + "EXTRACT(EPOCH FROM now()), ". + "0, 0, 0, 1, 20*60, 100000, 't', 1, '', '', '')", "DBFakeContest(insert contest)"); + + DBExec($c, "insert into sitetable (contestnumber, sitenumber, siteip, sitename, siteactive, sitepermitlogins, ". + "sitelastmileanswer, sitelastmilescore, siteduration, siteautoend, sitejudging, sitetasking, ". + "siteglobalscore, sitescorelevel) ". + "values (0, 1, '', 'Fake Site (just for initial purposes)', ". + "'t', 't', 0, 0, 1, 't', '1', ". + "'1', '0', 4)", "DBFakeContest(insert site)"); + + $param['contest']=0; + $param['site']=1; + $param['start']=1; + DBRenewSiteTime($param, $c); + $cf = globalconf(); + $pass = myhash($cf["basepass"]); + DBExec($c, "insert into usertable (contestnumber, usersitenumber, usernumber, username, userfullname, ". + "userdesc, usertype, userenabled, usermultilogin, userpassword, userip, userlastlogin, usersession, ". + "userlastlogout, userpermitip) ". + "values (0, 1, 1, 'system', 'Systems', NULL, 'system', 't', ". + "'t', '$pass', NULL, NULL, '', NULL, NULL)", "DBFakeContest(insert system user)"); + DBExec($c, "commit work"); +} +function DBAllUserInfo($contest,$site=-1) { + $sql = "select * from usertable where contestnumber=$contest "; + if($site > 0) $sql .= "and usersitenumber=$site "; + $sql .= "order by usersitenumber, usernumber"; + $c = DBConnect(); + $r = DBExec ($c, $sql, "DBAllUserInfo(get users)"); + $n = DBnlines($r); + if ($n == 0) { + LOGError("Unable to find users in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find users in the database!"); + } + + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + $a[$i]['userpassword'] = myhash($a[$i]['userpassword'] . $a[$i]['usersessionextra']); + } + return $a; +} +function DBAllSiteTime($contest, $site) { + $sql = "select * from sitetimetable where contestnumber=$contest and sitenumber=$site order by sitestartdate"; + $c = DBConnect(); + $r = DBExec ($c, $sql, "DBAllSiteTime(get times)"); + $n = DBnlines($r); + if ($n == 0) { + LOGError("Unable to find Site times in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find site times in the database!"); + } + + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + + return $a; +} +function DBUserInfo($contest, $site, $user) { + $sql = "select * from usertable where usernumber=$user and usersitenumber=$site and " . + "contestnumber=$contest"; + $a = DBGetRow ($sql, 0); + if ($a == null) { + LOGError("Unable to find the user in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find the user in the database. Contact an admin now!"); + } + $a['userpassword'] = myhash($a['userpassword'] . $a['usersessionextra']); + return $a; +} +function DBDeleteUser($contest, $site, $user) { + if ($contest==$_SESSION["usertable"]["contestnumber"] && + $site==$_SESSION["usertable"]["usersitenumber"] && + $user==$_SESSION["usertable"]["usernumber"]) return false; + $c = DBConnect(); + DBExec($c, "begin work"); + DBExec($c, "lock table usertable"); + $sql = "select * from usertable where usernumber=$user and usersitenumber=$site and " . + "contestnumber=$contest"; + $a = DBGetRow ($sql, 0); + if ($a != null) { + $sql = "delete from usertable where usernumber=$user and usersitenumber=$site and " . + "contestnumber=$contest"; + DBExec ($c, $sql); + DBExec($c, "commit work"); + LOGLevel("User $user (site=$site,contest=$contest) removed.", 1); + return true; + } else { + DBExec($c, "rollback work"); + LOGLevel("User $user (site=$site,contest=$contest) could not be removed.", 1); + return false; + } +} +function DBSiteInfo($contest, $site, $c=null, $msg=true) { + $sql = "select * from sitetable where sitenumber=$site and contestnumber=$contest"; + if($c == null) $c = DBConnect(); + $r = DBExec($c, $sql); + if(DBnLines($r) < 1) { + if($msg) { + LOGError("Unable to find the site in the database (site=$site, contest=$contest). SQL=(" . $sql . ")"); + MSGError("Unable to find the site in the database. Contact an admin now!"); + } else return null; + } + $a = DBRow($r, 0); + + $sql = "select sitestartdate as s, siteenddate as e from sitetimetable ". + "where sitenumber=$site and contestnumber=$contest order by sitestartdate"; + $r = DBExec($c, $sql); + $n = DBnLines($r); + $a["currenttime"] = 0; + $a["siterunning"] = false; + $ti = time(); + for($i = 0; $i < $n; $i++) { + $b = DBRow($r, $i); + if($i == 0) $a["sitestartdate"] = $b["s"]; + if($b["e"] == 0) { + $a["siterunning"] = true; + $a["currenttime"] += $ti - $b["s"]; + } else + $a["currenttime"] += $b["e"] - $b["s"]; + $a["siteendeddate"] = $b["e"]; + } + if($a["siteendeddate"] == 0) $a["siteendeddate"] = $ti + $a["siteduration"] - $a["currenttime"]; + $a["siteautoended"] = false; + if($a["siteautoend"] == "t" && $a["currenttime"] >= $a["siteduration"]) { + $a["siterunning"] = false; + $a["siteautoended"] = true; + } + return $a; +} +function DBSiteLogoffAll($contest, $site) { + $c = DBConnect(); + DBExec($c, "begin work"); + $r = DBExec($c,"update usertable set usersessionextra='', usersession='', updatetime=".time()." where usertype!='admin' and " . + "contestnumber=$contest and usersitenumber=$site"); + $r = DBExec($c,"update usertable set userlastlogout=".time()." where usertype!='admin' and " . + "contestnumber=$contest and usersitenumber=$site and (userlastlogin>userlastlogout or " . + "(userlastlogout is null and userlastlogin is not null))"); + DBExec($c, "commit work"); + + LOGLevel("Logoff all (contest=$contest,site=$site).",2); +} + +function DBAllSiteInfo($contest) { + $sql = "select * from sitetable where contestnumber=$contest"; + $c = DBConnect(); + $r = DBExec ($c, $sql); + $n = DBnlines($r); + if ($n == 0) { + LOGError("Unable to find sites in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find sites in the database!"); + } + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + return $a; +} +function DBAllContestInfo() { + $sql = "select * from contesttable"; + $c = DBConnect(); + $r = DBExec ($c, $sql); + $n = DBnlines($r); + if ($n == 0) { + LOGError("Unable to find contests in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find contests in the database!"); + } + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + return $a; +} +function DBContestInfo($contest, $c=null) { + $sql = "select * from contesttable where contestnumber=$contest"; + $a = DBGetRow ($sql, 0, $c); + if ($a == null) { + LOGError("Unable to find the contest $contest in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find the contest $contest in the database. Contact an admin now!"); + return null; + } + return $a; +} +function DBGetActiveContest() { + $sql = "select * from contesttable where contestactive='t'"; + $a = DBGetRow ($sql, 0); + if ($a == null) { + LOGError("Unable to find active contests in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find active contests in the database."); + } + return $a; +} +function DBSiteStartNow ($contest, $site) { + $s = DBSiteInfo($contest, $site); + if($s["siterunning"]) return false; + $t = time(); + $c = DBConnect(); + DBExec($c, "begin work"); + DBExec($c, "lock table sitetable"); + DBExec($c, "lock table sitetimetable"); + DBExec($c, "update sitetimetable set siteenddate=".$s['siteendeddate']." where ". + "siteenddate=0 and sitenumber=$site and contestnumber=$contest"); + DBExec($c, "insert into sitetimetable (contestnumber, sitenumber, sitestartdate, siteenddate) ". + "values ($contest, $site, $t, 0)"); + DBExec($c, "commit work"); + LOGLevel("Site $site (contest=$contest) started at ".dateconv($t),2); + return true; +} +function DBSiteEndNow ($contest, $site, $w=0) { + $s = DBSiteInfo($contest, $site); + if(!$s["siterunning"]) return false; + if($w == 0) $t = time(); + else $t = $w; + $c = DBConnect(); + DBExec($c, "begin work"); + DBExec($c, "lock table runtable"); + $a = DBGetRow("select max(rundate) as t from runtable where contestnumber=$contest and ". + "runsitenumber=$site and not runstatus ~ 'deleted'", 0); + if($a["t"] >= $t) { + LOGLevel("Unable to stop a contest before an existing run",2); + MSGError("Impossible to stop a contest before an existing run"); + DBExec($c, "commit work"); + return false; + } + DBExec($c, "update sitetimetable set siteenddate=$t, updatetime=".time()." " . + "where contestnumber=$contest and sitenumber=$site and siteenddate=0"); + DBExec($c, "commit work"); + LOGLevel("Site $site (contest=$contest) stopped at ".dateconv(time()),2); + return true; +} +function DBSiteLogins ($contest, $site, $logins) { + $s = DBSiteInfo($contest, $site); + $param = $s; + $param['contestnumber']=$contest; + $param['sitenumber']=$site; + $param['sitepermitlogins']=$logins; + DBUpdateSite ($param); + LOGLevel("Site logins=$logins (contest=$contest)",2); +} +function DBSiteDeleteAllClars ($contest, $site, $user, $usersite, $c=null) { + $cw=false; + if($c==null) { + $cw=true; + $c = DBConnect(); + DBExec($c, "begin work"); + } + DBExec($c, "lock table sitetable"); + DBExec($c, "lock table clartable"); + DBExec($c, "select * from sitetable where contestnumber=$contest and sitenumber=$site for update"); + $r = DBExec($c, "select * from clartable as c where c.contestnumber=$contest and " . + "c.clarsitenumber=$site for update"); + DBExec($c, "delete from clartable where contestnumber=$contest and clarsitenumber=$site"); + DBExec($c, "update sitetable set sitenextclar=0, updatetime=".time()." " . + "where contestnumber=$contest and sitenumber=$site"); + if($cw) { + DBExec($c, "commit work"); + LOGLevel("All Clarifications deleted (site=$site, contest=$contest, user=$user(site=$usersite)).", 3); + } + return true; +} +function DBSiteDeleteAllTasks ($contest, $site, $user, $usersite,$c=null) { + $cw=false; + if($c==null) { + $cw=true; + $c = DBConnect(); + DBExec($c, "begin work"); + } + DBExec($c, "lock table sitetable"); + DBExec($c, "lock table tasktable"); + DBExec($c, "select * from sitetable where contestnumber=$contest and sitenumber=$site for update"); + $r = DBExec($c, "select * from tasktable as t where t.contestnumber=$contest and " . + "t.sitenumber=$site for update"); + DBExec($c, "delete from tasktable where contestnumber=$contest and sitenumber=$site"); + DBExec($c, "update sitetable set sitenexttask=0, updatetime=".time()." " . + "where contestnumber=$contest and sitenumber=$site"); + if($cw) { + DBExec($c, "commit work"); + LOGLevel("All Tasks deleted (site=$site, contest=$contest, user=$user(site=$usersite)).", 3); + } + return true; +} +function DBSiteDeleteAllBkps ($contest, $site, $user, $usersite,$c=null) { + $cw=false; + if($c==null) { + $cw=true; + $c = DBConnect(); + DBExec($c, "begin work"); + } + DBExec($c, "lock table bkptable"); + $r = DBExec($c, "select bkpdata from bkptable where contestnumber=$contest and sitenumber=$site and bkpstatus='active'"); + $n = DBnlines($r); + for ($i=0;$i<$n;$i++) { + $a = DBRow($r,$i); + DB_lo_unlink($c,$a["bkpdata"]); + } + DBExec($c, "delete from bkptable where contestnumber=$contest and sitenumber=$site"); + if($cw) { + DBExec($c, "commit work"); + LOGLevel("All Bkps deleted (site=$site, contest=$contest, user=$user(site=$usersite)).", 3); + } + return true; +} +function DBSiteDeleteAllRuns ($contest, $site, $user, $usersite,$c=null) { + $cw=false; + if($c==null) { + $cw=true; + $c = DBConnect(); + DBExec($c, "begin work"); + } + DBExec($c, "lock table sitetable"); + DBExec($c, "lock table runtable"); + DBExec($c, "select * from sitetable where contestnumber=$contest and sitenumber=$site for update"); + $sql = "select * from runtable as r where r.contestnumber=$contest and " . + "r.runsitenumber=$site"; + $r = DBExec ($c, $sql . " for update"); + DBExec($c, "delete from runtable where contestnumber=$contest and runsitenumber=$site"); + DBExec($c, "update sitetable set sitenextrun=0, updatetime=".time()." " . + "where contestnumber=$contest and sitenumber=$site"); + if($cw) { + DBExec($c, "commit work"); + LOGLevel("All Runs deleted (site=$site, contest=$contest, user=$user(site=$usersite)).", 3); + } + return true; +} +function DBUpdateSite ($param,$c=null) { + $ac=array('contestnumber','sitenumber','sitename','sitepermitlogins','sitescorelevel'); + $ac1=array('updatetime','siteautoend','siteglobalscore','siteip','siteactive','siteduration','sitelastmileanswer','sitelastmilescore', + 'siteautojudge','sitenextuser','sitenextclar','sitenextrun','sitenexttask','sitemaxtask','sitechiefname','sitejudging','sitetasking'); + + if(isset($param['number']) && !isset($param['sitenumber'])) $param['sitenumber']=$param['number']; + $type['contestnumber']=1; + $type['sitenumber']=1; + $type['updatetime']=1; + $type['siteduration']=1; + $type['sitelastmilescore']=1; + $type['sitelastmileanswer']=1; + $type['sitenextuser']=1; + $type['sitenextclar']=1; + $type['sitenextrun']=1; + $type['sitenexttask']=1; + $type['sitemaxtask']=1; + foreach($ac as $key) { + if(!isset($param[$key])) { + MSGError("DBUpdateSite param error: $key is not set"); + return false; + } + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBUpdateSite param error: $key is not numeric"); + return false; + } + } + $siteduration=-1; + $sitelastmileanswer=-1; + $sitelastmilescore=-1; + $sitenextuser = -1; + $sitenextclar = -1; + $sitenextrun = -1; + $sitenexttask = -1; + $sitemaxtask = -1; + $sitejudging = ''; + $sitetasking = ''; + $sitechiefname = ''; + $siteip=''; + $updatetime = -1; + $siteautojudge = 'f'; + $siteautoend='f'; + $siteglobalscore=''; + $siteactive='f'; + foreach($ac1 as $key) { + if(isset($param[$key])) { + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBUpdateSite param error: $key is not numeric"); + return false; + } + } + } + $t = time(); + if($updatetime <= 0) + $updatetime=$t; + + if ($siteautoend != "t" && $siteautoend != "") $siteautoend = "f"; + if ($siteactive != "t" && $siteactive != "") $siteactive = "f"; + if ($siteautojudge != "t" && $siteautojudge != "") $siteautojudge = "f"; + if ($sitescorelevel == "" || !is_numeric($sitescorelevel)) $sitescorelevel = 0; + if ($sitescorelevel < -3) $sitescorelevel = -4; + if ($sitescorelevel > 3) $sitescorelevel = 4; + + $docommit=false; + if($c==null) { + $c = DBConnect(); + DBExec($c, "begin work", "DBUpdateSite(begin)"); + $docommit=true; + } + $a = DBGetRow ("select * from sitetable where contestnumber=$contestnumber and sitenumber=$sitenumber", 0, $c); + $ret=1; + if ($a == null) { + $ret=2; + $param['number']=$sitenumber; + DBNewSite($contestnumber,$c,$param); + $a = DBGetRow ("select * from sitetable where contestnumber=$contestnumber and sitenumber=$sitenumber", 0, $c); + if ($a == null) { + DBExec($c, "rollback work", "DBUpdateSite(rollback-errorsite)"); + MSGError("DBUpdateSite update error: impossible to create a site in the DB"); + LOGLevel("DBUpdateSite update error: impossible to create a site in the DB",0); + return false; + } + } + if($updatetime > $a['updatetime']) { + $ret=2; + if($sitenextrun==0) + DBSiteDeleteAllRuns($contestnumber,$sitenumber,$_SESSION["usertable"]["usernumber"],$_SESSION["usertable"]["usersitenumber"],$c); + if($sitenextclar==0) + DBSiteDeleteAllClars($contestnumber,$sitenumber,$_SESSION["usertable"]["usernumber"],$_SESSION["usertable"]["usersitenumber"],$c); + if($sitenexttask==0) + DBSiteDeleteAllTasks($contestnumber,$sitenumber,$_SESSION["usertable"]["usernumber"],$_SESSION["usertable"]["usersitenumber"],$c); + + $sql = "update sitetable set sitename='$sitename', updatetime=".$updatetime.", "; + if ($sitepermitlogins!="") $sql .= "sitepermitlogins='$sitepermitlogins', "; + if ($siteduration > 0) + $sql .= "siteduration=$siteduration, "; + if($siteip != '') + $sql .= "siteip='$siteip',"; + if($siteautoend != "") + $sql .= "siteautoend='$siteautoend', "; + if($siteactive != "") + $sql .= "siteactive='$siteactive', "; + if($siteglobalscore != "") + $sql .= "siteglobalscore='$siteglobalscore', "; + if($sitenextuser >= 0) + $sql .= "sitenextuser=$sitenextuser, "; + if($sitenextclar >= 0) + $sql .= "sitenextclar=$sitenextclar, "; + if($sitenextrun >= 0) + $sql .= "sitenextrun=$sitenextrun, "; + if($sitenexttask >= 0) + $sql .= "sitenexttask=$sitenexttask, "; + if($sitemaxtask >= 0) + $sql .= "sitemaxtask=$sitemaxtask, "; + if($sitechiefname != '') + $sql .= "sitechiefname='$sitechiefname', "; + if($siteautojudge != '') + $sql .= "siteautojudge='$siteautojudge', "; + if($sitejudging != '') + $sql .= "sitejudging='$sitejudging', "; + if($sitetasking != '') + $sql .= "sitetasking='$sitetasking', "; + if($sitelastmileanswer > 0) + $sql .= " sitelastmileanswer=$sitelastmileanswer, "; + if($sitelastmilescore > 0) + $sql .= " sitelastmilescore=$sitelastmilescore, "; + $sql .= " sitescorelevel=$sitescorelevel where contestnumber=$contestnumber and sitenumber=$sitenumber " . + "and updatetime < $updatetime"; + DBExec($c,$sql, "DBUpdateSite(update site)"); + if($docommit) + DBExec($c, "commit work", "DBUpdateSite(commit-update)"); + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . + " changed the site $sitenumber (contest=$contestnumber) settings.",2); + } else { + if($docommit) + DBExec($c, "commit work", "DBUpdateSite(commit-noupdate)"); + } + return $ret; +} +function DBUpdateContest ($param, $c=null) { + if(isset($param['contestnumber']) && !isset($param['number'])) $param['number']=$param['contestnumber']; + + $ac=array('number'); + $ac1=array('updatetime','atualizasites','scorelevel','mainsite','localsite','mainsiteurl','keys','unlockkey', + 'active','lastmileanswer','lastmilescore','penalty','startdate', 'duration', 'maxfilesize'); + $type['number']=1; + $type['scorelevel']=1; + $type['startdate']=1; + $type['updatetime']=1; + $type['duration']=1; + $type['penalty']=1; + $type['maxfilesize']=1; + $type['active']=1; + $type['lastmilescore']=1; + $type['lastmileanswer']=1; + $type['mainsite']=1; + $type['localsite']=1; + foreach($ac as $key) { + if(!isset($param[$key])) { + MSGError("DBUpdateContest param error: $key is not set"); + return false; + } + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBUpdateContest param error: $key is not numeric"); + return false; + } + } + $name=''; + $atualizasites = false; + $mainsiteurl=''; + $keys=''; + $unlockkey=''; + $mainsite=-1; + $duration=-1; + $lastmilescore=-1; + $lastmileanswer=-1; + $penalty=-1; + $maxfilesize=-1; + $active=0; + $startdate=-1; + $localsite=-1; + $updatetime=-1; + foreach($ac1 as $key) { + if(isset($param[$key])) { + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBUpdateContest param error: $key is not numeric"); + return false; + } + } + } + $t = time(); + if($updatetime <= 0) + $updatetime=$t; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBUpdateContest(begin)"); + } + $a = DBGetRow("select * from contesttable where contestnumber=$number for update", 0, $c, "DBUpdateContest(get for update)"); + if($a == null) { + MSGError("Error updating contest $number -- not found"); + LOGError("DBUpdateContest contest $number not found"); + return false; + } + $ret=1; + if ($active == 1) { + $ret=2; + DBExec($c, "update contesttable set contestactive='f'", "DBUpdateContest(deactivate)"); + DBExec($c, "update contesttable set contestactive='t' where contestnumber=$number", + "DBUpdateContest(active)"); + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " activated contest $number.",2); + } + if($updatetime > $a['updatetime']) { + $ret=2; + $sql = "update contesttable set updatetime=".$updatetime; + if($name != '') $sql .= ", contestname='$name'"; + if($maxfilesize > 0) $sql .= ", contestmaxfilesize=$maxfilesize"; + if($penalty > 0) $sql .= ", contestpenalty=$penalty"; + if($lastmileanswer > 0) $sql .= ", contestlastmileanswer=$lastmileanswer"; + if($lastmilescore > 0) $sql .= ", contestlastmilescore=$lastmilescore"; + if($startdate > 0) $sql .= ", conteststartdate=$startdate"; + if($duration > 0) $sql .= ", contestduration=$duration"; + if ($mainsite > 0) $sql .= ", contestmainsite=$mainsite"; + if ($mainsiteurl != '') $sql .= ", contestmainsiteurl='$mainsiteurl'"; + if ($unlockkey != '') $sql .= ", contestunlockkey='$unlockkey'"; + if ($keys != '') $sql .= ", contestkeys='$keys'"; + if ($localsite > 0) $sql .= ", contestlocalsite=$localsite"; + $sql .= " where contestnumber=$number"; + DBExec($c, $sql, "DBUpdateContest(update contest)"); + + if($localsite > 0) { + $param['contestnumber']=$number; + $param['sitename']='Local site'; + if($duration > 0) + $param['siteduration']=$duration; + if(isset($param['scorelevel'])) + $param['sitescorelevel']=$scorelevel; + if($lastmileanswer > 0) + $param['sitelastmileanswer']=$lastmileanswer; + if($lastmilescore > 0) + $param['sitelastmilescore']=$lastmilescore; + $param['number']=$localsite; + DBNewSite ($number,$c,$param); + } + if($mainsite > 0) { + $param['contestnumber']=$number; + $param['sitename']='Main site'; + if($duration > 0) + $param['siteduration']=$duration; + if(isset($param['scorelevel'])) + $param['sitescorelevel']=$scorelevel; + if($lastmileanswer > 0) + $param['sitelastmileanswer']=$lastmileanswer; + if($lastmilescore > 0) + $param['sitelastmilescore']=$lastmilescore; + $param['number']=$mainsite; + DBNewSite ($number,$c,$param); + } + + if($atualizasites) { + $s = DBAllSiteInfo($number); + for($i=0; $i<count($s); $i++) { + $param = $s[$i]; + $param['contestnumber']=$number; + if($duration > 0) + $param['siteduration']=$duration; + if(isset($param['scorelevel'])) + $param['sitescorelevel']=$scorelevel; + if($lastmileanswer > 0) + $param['sitelastmileanswer']=$lastmileanswer; + if($lastmilescore > 0) + $param['sitelastmilescore']=$lastmilescore; + + DBUpdateSite ($param,$c); + + if($startdate > 0) { + $p=array(); + $p['contest']=$number; + $p['site']=$s[$i]["sitenumber"]; + $p['start']=$startdate; + DBRenewSiteTime($p, $c); + } + } + } + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " changed the contest $number settings.",2); + } + if($cw) { + DBExec($c, "commit work", "DBUpdateContest(commit)"); + } + return $ret; +} +function DBRenewSiteTime($param, $c=null) { + if(!isset($param[0])) { + $tmp = $param; + $param = array(); + $param[0] = $tmp; + } + $ac=array('contest','site','start'); + $ac1=array('enddate','updatetime'); + $type['contest']=1; + $type['site']=1; + $type['start']=1; + $type['enddate']=1; + + $t = time(); + $maxtime = 0; + for($i=0; isset($param[$i]); $i++) { +// LOGLevel(implode(" ",array_keys($param[$i])),2); +// LOGLevel(implode(" ",$param[$i]),2); + if(isset($param[$i]['contestnumber']) && !isset($param[$i]['contest'])) $param[$i]['contest']=$param[$i]['contestnumber']; + if(isset($param[$i]['sitenumber']) && !isset($param[$i]['site'])) $param[$i]['site']=$param[$i]['sitenumber']; + foreach($ac as $key) { + if(!isset($param[$i][$key])) { + MSGError("DBRenewSiteTime param error: $key is not set"); + return false; + } + if(isset($type[$key]) && !is_numeric($param[$i][$key])) { + MSGError("DBRenewSiteTime param error: $key is not numeric"); + return false; + } + } + foreach($ac1 as $key) { + if(isset($param[$i][$key])) { + if(isset($type[$key]) && !is_numeric($param[$i][$key])) { + MSGError("DBRenewSiteTime param error: $key is not numeric"); + return false; + } + } + } + if(!isset($param[$i]['updatetime'])) $param[$i]['updatetime']=$t; + if($param[$i]['updatetime'] > $maxtime) $maxtime = $param[$i]['updatetime']; + if(!isset($param[$i]['enddate'])) $param[$i]['enddate']=0; + + if($param[$i]['contest'] != $param[0]['contest'] || $param[$i]['site'] != $param[0]['site']) { + MSGError("DBRenewSiteTime param error: contest and site have to match over all instances"); + return false; + } + } + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBRenewSiteTime(begin)"); + } + DBExec($c,"lock table sitetimetable","DBRenewSiteTime(lock)"); + + $a = DBGetRow ("select max(updatetime) as maxtime from sitetimetable where contestnumber=". $param[0]['contest']. + " and sitenumber=". $param[0]['site'], 0, $c); + $ret = 1; + if ($a == null || $a['maxtime'] < $maxtime) { + DBExec($c, "delete from sitetimetable where contestnumber=" . $param[0]['contest']. + " and sitenumber=". $param[0]['site'], "DBRenewSiteTime(delete)"); + for($i=0; isset($param[$i]); $i++) { + DBExec($c, "insert into sitetimetable (contestnumber, sitenumber, sitestartdate, siteenddate, updatetime) ". + "values (". $param[0]['contest'].", ". $param[0]['site'].", ".$param[$i]['start'].", ". + $param[$i]['enddate'].", ".$param[$i]['updatetime'].")", "DBRenewSiteTime(insert)"); + } + $ret = 2; + } + if($cw) DBExec($c, "commit work", "DBRenewSiteTime(commit)"); + return $ret; +} +function DBNewContest ($param=array(), $c=null) { + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBNewContest(begin)"); + } + $a = DBGetRow ("select max(contestnumber) as contest from contesttable", 0, $c, + "DBNewContest(max(contest))"); + if ($a == null) $n=1; + else $n = $a["contest"]+1; + + $ac=array('name','startdate','duration','lastmileanswer','lastmilescore','penalty','updatetime','localsite','mainsite','mainsiteurl','keys','unlockkey'); //'active' + $type['startdate']=1; + $type['duration']=1; + $type['lastmileanswer']=1; + $type['lastmilescore']=1; + $type['penalty']=1; + $type['updatetime']=1; + $type['mainsite']=1; + $type['localsite']=1; + $mainsiteurl=''; + $keys=''; + $unlockkey=''; + foreach($ac as $key) { + if(isset($param[$key]) && (!isset($type[$key]) || is_numeric($param[$key]))) + $$key = sanitizeText($param[$key]); + else + $$key = ""; + } + if($mainsite=="") $mainsite=1; + if($localsite=="") $localsite=1; + if($name=="") $name="Contest"; + if($startdate=="") $startdate="EXTRACT(EPOCH FROM now())+600"; + if($duration=="") $duration=300*60; + if($lastmileanswer=="") $lastmileanswer=285*60; + if($lastmilescore=="") $lastmilescore=240*60; + if($penalty=="") $penalty=20*60; + //if($active=="") + $active="f"; + if($updatetime=="") $updatetime=time(); + + DBExec($c, "insert into contesttable (contestnumber, contestname, conteststartdate, contestduration, ". + "contestlastmileanswer, contestlastmilescore, contestlocalsite, contestpenalty, ". + "contestmaxfilesize, contestactive, contestmainsite, contestmainsiteurl,contestkeys,contestunlockkey, updatetime) values ($n, '$name', ". + "$startdate, $duration, $lastmileanswer, " . + "$lastmilescore, $localsite, $penalty, 100000, '$active', $mainsite, '$mainsiteurl', '$keys','$unlockkey',$updatetime)", "DBNewContest(insert contest)"); + + DBNewSite($n, $c, $param); + + insertanswers($n,$c); + insertlanguages($n,$c); + + DBExec($c, "insert into problemtable (contestnumber, problemnumber, problemname, problemfullname, ". + "problembasefilename, problemdescfilename, problemdescfile, probleminputfilename, probleminputfile, ". + "problemsolfilename, problemsolfile, fake) values ($n, 0, 'General', 'General', NULL, NULL, ". + "NULL, NULL, NULL, NULL, NULL, 't')", "DBNewContest(insert problem)"); + + if($cw) { + DBExec($c, "commit work", "DBNewContest(commit)"); + } + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " created a new contest ($n).",2); + return $n; +} +function insertlanguages($n,$c=null) { + $ok=false; + $param=null; + $param['number']=1; + $param['name']='C'; + $param['extension']='c'; + DBNewLanguage($n, $param, $c); + $param['number']=2; + $param['name']='C++'; + $param['extension']='cpp'; + DBNewLanguage($n, $param, $c); + $param['number']=3; + $param['name']='Java'; + $param['extension']='java'; + DBNewLanguage($n, $param, $c); +} +function insertanswers($n,$c) { + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 0, 'Not answered yet', 'f', 't')", "DBNewContest(insert fake answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 1, 'YES', 't', 'f')", "DBNewContest(insert YES answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 2, 'NO - Compilation error', 'f', 'f')", "DBNewContest(insert CE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 3, 'NO - Runtime error', 'f', 'f')", "DBNewContest(insert RE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 4, 'NO - Time limit exceeded', 'f', 'f')", "DBNewContest(insert TLE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 5, 'NO - Presentation error', 'f', 'f')", "DBNewContest(insert PE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 6, 'NO - Wrong answer', 'f', 'f')", "DBNewContest(insert WA answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 7, 'NO - If possible, contact staff', 'f', 'f')", "DBNewContest(insert CS answer)"); +} +function DBNewSite ($contest, $c=null, $param=array()) { + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work"); + } + $ct = DBContestInfo ($contest, $c); + if($ct==null) return false; + $f=$ct["contestduration"]; + + if(isset($param['sitenumber']) && !isset($param['number'])) $param['number']=$param['sitenumber']; + $ac=array('number','siteip','sitename','sitescorelevel','updatetime'); + $type=array(); + $type['number']=1; + $type['sitescorelevel']=1; + $type['updatetime']=1; + foreach($ac as $key) { + if(isset($param[$key]) && (!isset($type[$key]) || is_numeric($param[$key]))) + $$key = sanitizeText($param[$key]); + else + $$key = ""; + } + + if($number=="") { + $a = DBGetRow ("select max(sitenumber) as site from sitetable where contestnumber=$contest", 0, $c); + if ($a == null) $n=1; + else $n = $a["site"]+1; + $number=$n; + } else { + $a = DBGetRow ("select * from sitetable where contestnumber=$contest and sitenumber=$number", 0, $c); + if($a != null) return 1; + } + if($siteip=="") $siteip="127.0.0.1/boca"; + if($sitename=="") $sitename="Site"; + if($sitescorelevel=="") $sitescorelevel=3; + $t=time(); + if($updatetime=="") $updatetime=$t; + DBExec($c, "insert into sitetable (contestnumber, sitenumber, siteip, sitename, siteactive, sitepermitlogins, ". + "sitelastmileanswer, sitelastmilescore, siteduration, siteautoend, sitejudging, sitetasking, ". + "siteglobalscore, sitescorelevel, ". + "sitenextuser, sitenextclar, sitenextrun, sitenexttask, sitemaxtask, updatetime) values ". + "($contest, $number, '$siteip', '$sitename', 't', 't', ". + $ct["contestlastmileanswer"].",".$ct["contestlastmilescore"]. + ", $f, 't', '$number', '$number', '$number', $sitescorelevel, 0, 0, 0, 0, 10, $updatetime)"); + + $cf=globalconf(); + $admpass = myhash($cf["basepass"]); + + DBExec($c, "insert into usertable ". + "(contestnumber, usersitenumber, usernumber, username, userfullname, " . + "userdesc, usertype, userenabled, usermultilogin, userpassword, userip, userlastlogin, ". + "usersession, usersessionextra, userlastlogout, userpermitip, updatetime) values " . + "($contest, $number, 1000, 'admin', 'Administrator', NULL, 'admin', ". + "'t', 't', '$admpass', NULL, NULL, '', '', NULL, NULL, $updatetime)"); + $param=array(); + $param['contest']=$contest; + $param['site']=$number; + $param['start']=$ct["conteststartdate"]; + DBRenewSiteTime($param, $c); + if($cw) DBExec($c, "commit work"); + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . + " created site $number on contest $contest.",2); + return 2; +} + +function DBUserUpdate($contest, $site, $user, $username, $userfull, $userdesc, $passo, $passn) { + $a = DBUserInfo ($contest, $site, $user); + $p = myhash($a["userpassword"] . session_id()); + if ($a["userpassword"] != "" && $p != $passo) { + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " (contest=$contest, site=$site) " . + "tried to change settings, but password was incorrect.",2); + MSGError ("Incorrect password."); + } + else { + if ($a["userpassword"] == "") $temp = myhash(""); + else $temp = $a["userpassword"]; + $temp = bighexsub($passn, $temp); + $newpass = substr($temp, strlen($temp)-32, 32); + + $c = DBConnect(); + DBExec($c, "begin work"); + DBExec($c, "lock table usertable"); + $r = DBExec($c, "select * from usertable where username='$username' and usernumber!=$user and ". + "usersitenumber=$site and contestnumber=$contest"); + $n = DBnlines ($r); + if ($n == 0) { + $sql = "update usertable set username='$username', userdesc='$userdesc', userfullname='$userfull', updatetime=".time(); + if ($newpass != myhash("")) $sql .= ", userpassword='$newpass'"; + $sql .= " where usernumber=$user and usersitenumber=$site and contestnumber=$contest"; + $r = DBExec ($c, $sql); + DBExec ($c, "commit work"); + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " changed his settings (newname=$username) ". + "(user=$user,site=$site,contest=$contest)",2); + MSGError("Data updated."); + ForceLoad("index.php"); + } else { + DBExec ($c, "rollback work"); + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " couldn't change his settings " . + "(user=$user,site=$site,contest=$contest)",2); + MSGError ("Update problem (maybe username already in use). No data was changed."); + } + } +} + +function DBNewUser($param, $c=null) { + if(isset($param['contestnumber']) && !isset($param['contest'])) $param['contest']=$param['contestnumber']; + if(isset($param['sitenumber']) && !isset($param['site'])) $param['site']=$param['sitenumber']; + if(isset($param['usernumber']) && !isset($param['user'])) $param['user']=$param['usernumber']; + if(isset($param['number']) && !isset($param['user'])) $param['user']=$param['number']; + + $ac=array('contest','site','user'); + $ac1=array('updatetime','username','usericpcid','userfull','userdesc','type','enabled','multilogin','pass','permitip', + 'userip','userlastlogin','userlastlogout','usersession','usersessionextra'); + + $typei['contest']=1; + $typei['updatetime']=1; + $typei['site']=1; + $typei['user']=1; + foreach($ac as $key) { + if(!isset($param[$key]) || $param[$key]=="") { + MSGError("DBNewUser param error: $key not found"); + return false; + } + if(isset($typei[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewUser param error: $key is not numeric"); + return false; + } + $$key = sanitizeText($param[$key]); + } + $username= "team" . $user; + $updatetime=-1; + $pass = null; + $usericpcid=''; + $userfull=''; + $userdesc=''; + $type='team'; + $enabled='f'; + $multilogin='f'; + $permitip=''; + $usersession=null; + $usersessionextra=null; + $userip=null; + $userlastlogin=null; + $userlastlogout=null; + foreach($ac1 as $key) { + if(isset($param[$key])) { + $$key = sanitizeText($param[$key]); + if(isset($typei[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewUser param error: $key is not numeric"); + return false; + } + } + } + $t = time(); + if($updatetime <= 0) + $updatetime=$t; + + if ($type != "chief" && $type != "judge" && $type != "admin" && + $type != "score" && $type != "staff" && $type != "site") + $type = "team"; + if ($enabled != "f") $enabled = "t"; + if ($multilogin != "t") $multilogin = "f"; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBNewUser(begin)"); + } + DBExec($c, "lock table usertable", "DBNewUser(lock)"); + $r = DBExec($c, "select * from sitetable where sitenumber=$site and contestnumber=$contest", "DBNewUser(get site)"); + $n = DBnlines ($r); + if($n == 0) { + DBExec ($c, "rollback work","DBNewUser(no-site)"); + MSGError("DBNewUser param error: site $site does not exist"); + return false; + } + $r = DBExec($c, "select * from usertable where username='$username' and usernumber!=$user and ". + "usersitenumber=$site and contestnumber=$contest", "DBNewUser(get user)"); + $n = DBnlines ($r); + $ret=1; + if ($n == 0) { + $sql = "select * from usertable where usernumber=$user and usersitenumber=$site and " . + "contestnumber=$contest"; + $a = DBGetRow ($sql, 0, $c); + if ($a == null) { + $ret=2; + $sql = "select * from sitetable where sitenumber=$site and contestnumber=$contest"; + $aa = DBGetRow ($sql, 0); + if($aa==null) { + DBExec ($c, "rollback work"); + MSGError("Site $site does not exist"); + return false; + } + $sql = "insert into usertable (contestnumber, usersitenumber, usernumber, username, usericpcid, userfullname, " . + "userdesc, usertype, userenabled, usermultilogin, userpassword, userpermitip) values " . + "($contest, $site, $user, '$username', '$usericpcid', '$userfull', '$userdesc', '$type', '$enabled', " . + "'$multilogin', '$pass', '$permitip')"; + DBExec ($c, $sql, "DBNewUser(insert)"); + if($cw) { + DBExec ($c, "commit work"); + } + LOGLevel ("User $user (site=$site,contest=$contest) included.",2); + } else { + if($updatetime > $a['updatetime']) { + $ret=2; + $sql = "update usertable set username='$username', usericpcid='$usericpcid', userdesc='$userdesc', updatetime=$updatetime, " . + "userfullname='$userfull', usertype='$type', userpermitip='$permitip', "; + if($pass != null && $pass != myhash("")) $sql .= "userpassword='$pass', "; + if($usersession != null) $sql .= "usersession='$usersession', "; + if($usersessionextra != null) $sql .= "usersessionextra='$usersessionextra', "; + if($userip != null) $sql .= "userip='$userip', "; + if($userlastlogin != null) $sql .= "userlastlogin='$userlastlogin', "; + if($userlastlogout != null) $sql .= "userlastlogout='$userlastlogout', "; + $sql .= "userenabled='$enabled', usermultilogin='$multilogin'"; + $sql .= " where usernumber=$user and usersitenumber=$site and contestnumber=$contest"; + $r = DBExec ($c, $sql, "DBNewUser(update)"); + if($cw) { + DBExec ($c, "commit work"); + } + LOGLevel("User $user (username=$username,site=$site,contest=$contest) updated.",2); + } + } + } else { + DBExec ($c, "rollback work"); + LOGLevel ("Update problem for user $user (site=$site,contest=$contest) (maybe username already in use).",1); + MSGError ("Update problem for user $user, site $site (maybe username already in use)."); + return false; + } + return $ret; +} + +function siteclock() { + if (($s=DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + + if ($s["siteactive"]!="t") + return array("site is not active",-1000000000); + if (!$s["siterunning"]) + return array("contest not running",-1000000000); + if ($s["currenttime"]<0) { + $t = - $s["currenttime"]; + if ($t>60) { + $t = (int) ($t/60); + return array("> ". $t . " min(s) to start",$s["currenttime"]); + } else { + return array($t . " second(s) to start",$s["currenttime"]); + } + } + if ($s["currenttime"]>=0) { + $t = $s["siteduration"] - $s["currenttime"]; + if ($t>60) { + $t = (int) ($t/60); + return array("> " . $t . " minute(s) left",$s["currenttime"]); + } else { + if ($t>0) { + return array($t . " second(s) left",$s["currenttime"]); + } else { + $t = (int) (- $t/60); + return array($t . "min. of extra time",$s["currenttime"]); + } + } + } + else return array("not started",-1000000000); +} +// eof +?> diff --git a/boca-1.5.0/src/fextdata.php b/boca-1.5.0/src/fextdata.php new file mode 100644 index 0000000..2799bec --- /dev/null +++ b/boca-1.5.0/src/fextdata.php @@ -0,0 +1,580 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br + +function getMainXML($username,$sess,$pass,$pass2) { + $c = DBConnect(); + if ($c==null) return array(false,""); + $contest = $_SESSION["usertable"]["contestnumber"]; + $r = DBExec($c, "select * from contesttable where contestnumber=$contest"); + if (DBnLines($r)==0) { + echo "Unable to find the contest $contest in the database.\n"; + exit; + } + $ct = DBRow($r,0); + $localsite = $ct["contestlocalsite"]; + $mainsite = $ct["contestmainsite"]; + $siteurl = $ct['contestmainsiteurl'] . '/site/get.php'; +// if ($mainsite==$localsite) return array(true,""); +/* + $r = DBExec($c, "select * from sitetable where sitenumber=".$mainsite." and contestnumber=$contest"); + if (DBnLines($r)==0) { + echo "Unable to find the main site in the database (site=$mainsite, contest=$contest).\n"; + exit; + } + $st = DBRow($r,0); + $siteurl = $st["siteip"] . '/site/get.php'; +*/ + if(substr($siteurl,0,7) != 'http://') + $siteurl = 'http://' . $siteurl; + if($sess == '') { +// MSGError('session empty'); + $s = file_get_contents($siteurl); + if($s === false) return array(false,'',''); +// MSGError($s); + $t = strtok($s," \t"); + while($t !== false && substr($t,0,8) != '<SESSION' && substr($t,0,6) != '<ERROR' && $t != '<OK>' && $t != '<NOTOK>') { + echo $t . " "; + $t = strtok(" \t"); + } + if($t === false) return array(false,'',''); + echo $t . " -->\n"; + if(substr($t,0,8) == '<SESSION') { + $id = strtok(" \t"); + return array(false,$id,$id); + } + else + return array(false,'',''); + } + if($pass == $pass2) { +// MSGError('equal'); + $opts = array( + 'http' => array( + 'method' => 'GET', + 'header' => 'Cookie: PHPSESSID=' . $sess + ) + ); + $context = stream_context_create($opts); + $s = file_get_contents($siteurl . '?name='. $username . '&password=' . + $pass . '&check=nocheck', 0, $context); + } else { + $data = encryptData(generateXML($contest),myhash($pass2)); + $data_url = http_build_query(array('xml' => $data, + 'name' => $username, + 'password' => $pass, + 'check' => myhash($pass . $pass2) + )); + $opts = array( + 'http' => array( + 'method' => 'POST', + 'header' => 'Cookie: PHPSESSID=' . $sess . "\r\nContent-Type: application/x-www-form-urlencoded", + 'content' => $data_url + )); + $context = stream_context_create($opts); + $s = file_get_contents($siteurl, 0, $context); + } + if($s === false) return array(false,"",''); +// MSGError('OPA1: ' . $s); + $t = strtok($s," \t"); + while($t !== false && substr($t,0,8) != '<SESSION' && substr($t,0,6) != '<ERROR' && $t != '<OK>' && $t != '<NOTOK>') { + echo $t . " "; + $t = strtok(" \t"); + } + if($t === false) return array(false,'',''); + echo $t . " -->\n"; + if(substr($t,0,6) == "<ERROR") { + $id = strtok(" \t"); + if($id === false) return array(false,'',''); + return array(false,$id,""); + } + if(substr($t,0,8) == "<SESSION") { + $id = strtok(" \t"); + if($id === false) return array(false,'',''); + $idextra = strtok(" \t"); + if($idextra === false) return array(false,'',''); +// MSGError("id=$id idextra=$idextra"); + return array(false,$id,$idextra); + } + $id = strtok(" \t"); + if($id === false) return array(false,'',''); +//MSGError('OPA2: ' . $s); + if($pass2 != '') + $s = decryptData($id,myhash($pass2)); + if(strtoupper(substr($s,0,5)) != "<XML>") { + return array(false,'',$t); + } + return array(true,$s,$t); +} + +function importFromXML($ar,$acr,$contest=0,$localsite=0) { + $data = implode("",explode("\n",$ar)); + $parser = xml_parser_create(); + xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 1); + xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, 1); + xml_parse_into_struct($parser, $data, $values, $tags); + xml_parser_free($parser); +// print_r($tags); +// print_r($values); + + $orderkeys=array('CONTESTREC','SITETIME','SITEREC','USERREC','ANSWERREC','LANGUAGEREC','PROBLEMREC','CLARREC','RUNREC','TASKREC'); + $norderkeys=10; + $nc=0; + unset($sitetime); + unset($nsitetime); + $conn = DBConnect(); + if ($conn==null) return false; +// DBExec($conn,"begin work","importFromXML(begin)"); +// DBExec($conn,"lock","importFromXML(lock)"); + if($contest != 0) { + $r = DBExec($conn, "select * from contesttable where contestnumber=$contest"); + if (DBnLines($r)==0) { + echo "Unable to find the contest $contest in the database.\n"; + DBExec($conn,"rollback work"); + return false; + } + $ct = DBRow($r,0); + if($localsite==0) + $localsite = $ct["contestlocalsite"]; + } else if($localsite==0) $localsite=1; +// $mainsite = $ct["contestmainsite"]; + DBClose($conn); + $conn=null; + + for($keyindex=0; $keyindex < $norderkeys; $keyindex++) { + foreach($tags as $key=>$val) { + if($values[$val[0]]['type'] != 'open') continue; + if($key == "XML") continue; + if($key != $orderkeys[$keyindex]) continue; + if(isset($acr[$key])) + $ac = $acr[$key]; + else + continue; + foreach($val as $k=>$v) { + if($values[$v]['type'] != 'open') continue; + if(count($val) > $k+1) { + $param = array(); + if(isset($ac['site'])) { + for($i=$v; $i < $val[$k+1]; $i++) { + $p = strtolower($values[$i]["tag"]); + if($p=='site') { + if($values[$i]["type"]=="complete" && isset($values[$i]["value"])) { + $tmp = sanitizeText(trim(implode('',explode('\n',$values[$i]["value"])))); + if(is_array($ac['site']) && in_array($tmp,$ac['site'])) { + $param['site'] = $tmp; + } else { + if($ac['site']==-1 || ($ac['site']==-2 && $tmp==$localsite) || ($ac['site']==-3 && $tmp!=$localsite) || + ($ac['site']>0 && $ac['site']==$tmp)) + $param['site'] = $tmp; + } + } + } + } + } + for($i=$v; $i < $val[$k+1]; $i++) { + $p = strtolower($values[$i]["tag"]); + if(isset($ac[$p]) && $p != 'site') { + if($values[$i]["type"]=="complete" && isset($values[$i]["value"])) { + if(is_string($ac[$p])) $param[$p] = $ac[$p]; + else { + $tmp = sanitizeText(trim(implode('',explode('\n',$values[$i]["value"])))); + if(is_array($ac[$p]) && in_array($tmp,$ac[$p])) { + $param[$p] = $tmp; + } else { + if($ac[$p]==-1 || ($ac[$p]==-2 && $tmp==$localsite) || ($ac[$p]==-3 && $tmp!=$localsite) || + ($ac[$p]==0 && isset($param['site'])) || ($ac[$p]>0 && $ac[$p]==$tmp)) + $param[$p] = $tmp; + } + } + } + } + } +// echo "\nKEY KEY KEY\n"; +// print_r($key); +// echo "\nVAL VAL VAL\n"; +// print_r($val); +// echo "\n"; +// print_r($param); + $param['contestnumber'] = $contest; + if($key == "CONTESTREC") { + $param['number'] = $contest; + if($contest == 0) { + $nc=1; + $contest = DBNewContest($param, $conn); + if($contest > 0) + echo "<br><u>Contest $contest created</u> (not active by default)<br>"; + else { + echo "<br>Error creating contest<br>"; + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + } + $param['number'] = $contest; + $param['contestnumber'] = $contest; + if(($ret=DBUpdateContest($param, $conn))) { + if($ret==2) + echo "<br>Contest $contest updated<br>"; + } + else { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + } + if(!isset($param['number']) || count($param) < 2) continue; + if($key == "SITEREC") { + if(!DBNewSite($contest, $conn, $param)) { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + if(($ret=DBUpdateSite($param, $conn))) { + if($ret==2) { + echo "Site " . $param["number"] . " updated<br>"; + } + } else { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + if(isset($nsitetime[$param["number"]])) { + if(($qtd=DBRenewSiteTime($sitetime[$param["number"]], $conn))) { + if($qtd==2) { + echo "Time for site " . $param["number"] . " updated<br>"; + } + } else { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + } + } + if($key == "SITETIME") { + if(isset($param['site']) && is_numeric($param['site'])) { + $s = $param['site']; + if(!isset($nsitetime[$s])) $nsitetime[$s]=0; + $sitetime[$s][$nsitetime[$s]] = $param; + $nsitetime[$s]++; + } + } + if($key == "USERREC") { + if(($ret=DBNewUser($param, $conn))) { + if($ret==2) { + echo "User " . $param["number"]."/".$param['site']. " updated<br>"; + } + } else { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + } + if($key == "ANSWERREC") { + if(($ret=DBNewAnswer ($contest, $param, $conn))) { + if($ret==2) { + echo "Answer " . $param["number"] . " updated<br>"; + } + } + else { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + } + if($key == "LANGUAGEREC") { + if(($ret=DBNewLanguage ($contest,$param, $conn))) { + if($ret==2) { + echo "Language " . $param['number'] ." updated<br>"; + } + } + else { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + } + if($key == "PROBLEMREC") { + if(($ret=DBNewProblem ($contest,$param, $conn))) { + if($ret==2) + echo "Problem " . $param['number'] ." updated<br>"; + } + else { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + } + if($key == "TASKREC") { + if(($ret=DBNewTask ($param, $conn))) { + if($ret==2) + echo "Task " . $param['number']."/".$param['site']." updated<br>"; + } + else { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + } + if($key == "CLARREC") { + if(($ret=DBNewClar ($param, $conn))) { + if($ret==2) + echo "Clarification " . $param['number']."/".$param['site'] ." updated<br>"; + } + else { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + } + if($key == "RUNREC") { + if(($ret=DBNewRun ($param, $conn))) { + if($ret==2) + echo "Run " . $param['number'] ."/".$param['site']." updated<br>"; + } + else { + if($conn != null) + DBExec($conn,"rollback work"); + return false; + } + } + } + } + } + } +// DBExec($conn,"commit work","importFromXML(commit)"); + return true; +} + + +function generateXML($contest,$localsite=0,$sites=null,$reduced=false) { + $str = "<XML>\n"; + $ac['CONTESTREC']=array('number'=>'contestnumber', + 'name'=>'contestname', + 'startdate'=>'conteststartdate', + 'duration'=>'contestduration', + 'lastmileanswer'=>'contestlastmileanswer', + 'lastmilescore'=>'contestlastmilescore', + 'penalty'=>'contestpenalty', + 'maxfilesize'=>'contestmaxfilesize', + 'updatetime'=>'updatetime', + 'mainsite'=>'contestmainsite', + 'mainsiteurl'=>'contestmainsiteurl', + 'keys'=>'contestkeys', + 'unlockkey'=>'contestunlockkey', + 'updatetime'=>'updatetime'); + if($localsite > 0) + $ac['CONTESTREC']['localsite'] = array($localsite,2); + $sql['CONTESTREC']="select * from contesttable where contestnumber=$contest"; + $ac['ANSWERREC']=array('number'=>'answernumber', + 'name'=>'runanswer', + 'yes'=>'yes', + 'updatetime'=>'updatetime'); + $sql['ANSWERREC']="select * from answertable where contestnumber=$contest and fake='f'"; + + $ac['LANGUAGEREC']=array('number'=>'langnumber', + 'name'=>'langname', + 'updatetime'=>'updatetime'); + $sql['LANGUAGEREC']="select * from langtable where contestnumber=$contest"; + + $ac['PROBLEMREC']=array('number'=>'problemnumber', + 'name'=>'problemname', + 'fullname'=>'problemfullname', + 'basename'=>'problembasefilename', + 'inputfilename'=>'probleminputfilename', + 'inputfilepath'=>array('probleminputfile',1), + 'solfilename'=>'problemsolfilename', + 'solfilepath'=>array('problemsolfile',1), + 'descfilename'=>'problemdescfilename', + 'descfilepath'=>array('problemdescfile',1), + 'tl'=>'problemtimelimit', + 'colorname'=>'problemcolorname', + 'color'=>'problemcolor', + 'fake'=>'fake', + 'updatetime'=>'updatetime'); + $sql['PROBLEMREC']="select * from problemtable where contestnumber=$contest and fake='f'"; + + $sql['SITEREC']="select * from sitetable where contestnumber=$contest"; + $ac['SITEREC']=array('sitenumber'=>'sitenumber', + 'site'=>'sitenumber', + 'number'=>'sitenumber', + 'sitename'=>'sitename', + 'siteip'=>'siteip', + 'siteduration'=>'siteduration', + 'sitelastmileanswer'=>'sitelastmileanswer', + 'sitelastmilescore'=>'sitelastmilescore', + 'sitejudging'=>'sitejudging', + 'sitetasking'=>'sitetasking', + 'siteautoend'=>'siteautoend', + 'siteglobalscore'=>'siteglobalscore', + 'siteactive'=>'siteactive', + 'sitescorelevel'=>'sitescorelevel', + 'sitepermitlogins'=>'sitepermitlogins', + 'siteautojudge'=>'siteautojudge', + 'sitenextuser'=>'sitenextuser', + 'sitenextclar'=>'sitenextclar', + 'sitenextrun'=>'sitenextrun', + 'sitenexttask'=>'sitenexttask', + 'sitemaxtask'=>'sitemaxtask', + 'sitechiefname'=>'sitechiefname', + 'updatetime'=>'updatetime'); + $sql['SITETIME']="select * from sitetimetable where contestnumber=$contest"; + $ac['SITETIME']=array('site'=>'sitenumber', + 'number'=>'sitenumber', + 'start'=>'sitestartdate', + 'enddate'=>'siteenddate', + 'updatetime'=>'updatetime'); + + $sql['USERREC']="select * from usertable where contestnumber=$contest"; + $ac['USERREC']=array('site'=>'usersitenumber', + 'user'=>'usernumber', + 'number'=>'usernumber', + 'username'=>'username', + 'updatetime'=>'updatetime', + 'usericpcid'=>'usericpcid', + 'userfull'=>'userfullname', + 'userdesc'=>'userdesc', + 'type'=>'usertype', + 'enabled'=>'userenabled', + 'multilogin'=>'usermultilogin', +// 'pass'=>'userpassword', +// 'usersession'=>'usersession', + 'userip'=>'userip', + 'userlastlogin'=>'userlastlogin', + 'userlastlogout'=>'userlastlogout', + 'permitip'=>'userpermitip', + 'updatetime'=>'updatetime'); + + if(!$reduced) { + $sql['CLARREC']="select * from clartable where contestnumber=$contest"; + $ac['CLARREC']=array('site'=>'clarsitenumber', + 'user'=>'usernumber', + 'number'=>'clarnumber', + 'problem'=>'clarproblem', + 'question'=>'clardata', + 'clarnumber'=>'clarnumber', + 'clardate'=>'clardate', + 'clardatediff'=>'clardatediff', + 'clardatediffans'=>'clardatediffans', + 'claranswer'=>'claranswer', + 'clarstatus'=>'clarstatus', + 'clarjudge'=>'clarjudge', + 'clarjudgesite'=>'clarjudgesite', + 'updatetime'=>'updatetime'); + + $sql['RUNREC']="select * from runtable where contestnumber=$contest"; + if(is_array($sites)) { + $sql['RUNREC'] .= " and (1=0"; + foreach($sites as $k => $v) { + $sql['RUNREC'] .= " or runsitenumber=$v"; + } + $sql['RUNREC'] .= ")"; + } + $ac['RUNREC']=array('site'=>'runsitenumber', + 'user'=>'usernumber', + 'number'=>'runnumber', + 'runnumber'=>'runnumber', + 'problem'=>'runproblem', + 'lang'=>'runlangnumber', + 'filename'=>'runfilename', + 'filepath'=>array('rundata',1), + 'rundate'=>'rundate', + 'rundatediff'=>'rundatediff', + 'rundatediffans'=>'rundatediffans', + 'runanswer'=>'runanswer', + 'runstatus'=>'runstatus', + 'runjudge'=>'runjudge', + 'runjudgesite'=>'runjudgesite', + 'runjudge1'=>'runjudge1', + 'runjudgesite1'=>'runjudgesite1', + 'runanswer1'=>'runanswer1', + 'runjudge2'=>'runjudge2', + 'runjudgesite2'=>'runjudgesite2', + 'runanswer2'=>'runanswer2', + 'autoip'=>'autoip', + 'autobegindate'=>'autobegindate', + 'autoenddate'=>'autoenddate', + 'autoanswer'=>'autoanswer', + 'autostdout'=>array('autostdout',1), + 'autostderr'=>array('autostderr',1), + 'updatetime'=>'updatetime'); + $sql['TASKREC']="select * from tasktable where contestnumber=$contest"; + if(is_array($sites)) { + $sql['TASKREC'] .= " and (1=0"; + foreach($sites as $k => $v) { + $sql['TASKREC'] .= " or sitenumber=$v"; + } + $sql['TASKREC'] .= ")"; + } + $ac['TASKREC']=array( + 'site'=>'sitenumber', + 'user'=>'usernumber', + 'desc'=>'taskdesc', + 'number'=>'tasknumber', + 'tasknumber'=>'tasknumber', + 'color'=>'color', + 'colorname'=>'colorname', + 'updatetime'=>'updatetime', + 'filename'=>'taskfilename', + 'filepath'=>array('taskdata',1), + 'sys'=>'tasksystem', + 'status'=>'taskstatus', + 'taskdate'=>'taskdate', + 'taskdatediff'=>'taskdatediff', + 'taskdatediffans'=>'taskdatediffans', + 'taskstaffnumber'=>'taskstaffnumber', + 'taskstaffsite'=>'taskstaffsite'); + } + $c = DBConnect(); + if ($c==null) return null; + DBExec($c, "begin work"); + foreach($ac as $kk => $vv) { + $r = DBExec ($c, $sql[$kk], "generateXML($kk)"); + $n = DBnLines ($r); + for($i=0; $i<$n; $i++) { + $atual = DBRow($r,$i); + $str .= "<" . $kk . ">\n"; + foreach($vv as $key => $val) { + if(is_array($val)) { + if(is_array($val[0])) { + if(!isset($atual['site']) || in_array($atual['site'],$val[0])) + if(isset($atual[$val[1]])) + $str .= " <" . $key . ">" . $atual[$val[1]] . "</" . $key . ">\n"; + } + if($val[1]==2) { + $str .= " <" . $key . ">" . $val[0] . "</" . $key . ">\n"; + } + if($val[1]==1) { + if(isset($atual[$val[0]]) && $atual[$val[0]]!='') { + if (($lo = DB_lo_open ($c, $atual[$val[0]], "r")) !== false) { + $str .= " <" . $key . ">base64:" . base64_encode(DB_lo_read($contest,$lo)) . "</" . $key . ">\n"; + DB_lo_close($lo); + } + } + } + } else { + if(isset($atual[$val])) + $str .= " <" . $key . ">" . $atual[$val] . "</" . $key . ">\n"; + } + } + $str .= "</" . $kk . ">\n"; + } + } + $str .= "</XML>\n"; + DBExec($c,"commit work","generateXML(commit)"); + return $str; +} +?> diff --git a/boca-1.5.0/src/filedownload.php b/boca-1.5.0/src/filedownload.php new file mode 100644 index 0000000..92de694 --- /dev/null +++ b/boca-1.5.0/src/filedownload.php @@ -0,0 +1,114 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// modified 21/july/2012 by cassio@ime.usp.br +ob_start(); +session_start(); +require_once("globals.php"); + +if(!ValidSession()) { + echo "<html><head><title>Download Page</title>"; + InvalidSession("filedownload.php"); + ForceLoad("index.php"); +} + +if(!isset($_GET["oid"]) || !is_numeric($_GET["oid"]) || !isset($_GET["filename"]) || + !isset($_GET["check"]) || $_GET["check"]=="") { + echo "<html><head><title>Download Page</title>"; + IntrusionNotify("Bad parameters in filedownload.php"); + ForceLoad("index.php"); +} + +$cf = globalconf(); +$fname = decryptData(rawurldecode($_GET["filename"]), session_id() . $cf["key"]); + +if(isset($_GET["msg"])) + $p = myhash($_GET["oid"] . $fname . rawurldecode($_GET["msg"]) . session_id() . $cf["key"]); +else + $p = myhash($_GET["oid"] . $fname . session_id() . $cf["key"]); + +if($p != $_GET["check"]) { + echo "<html><head><title>View Page</title>"; + IntrusionNotify("Parameters modified in filedownload.php. "); + ForceLoad("index.php"); +} + +require_once("db.php"); + +if ($_GET["oid"]>=0) { + $c = DBConnect(); + DBExec($c, "begin work"); + + if (($lo = DB_lo_open ($c, $_GET["oid"], "r")) === false) { + echo "<html><head><title>Download Page</title>"; + DBExec($c, "rollback work"); + LOGError ("Unable to download file (" . basename($fname) . ")"); + MSGError ("Unable to download file (" . basename($fname) . ")"); + ForceLoad("index.php"); + } + + header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Cache-Control: no-cache, must-revalidate"); + header ("Pragma: no-cache"); + header ("Content-transfer-encoding: binary\n"); + header ("Content-type: application/force-download"); +//header ("Content-type: application/octet-stream"); +//if (strstr($_SERVER["HTTP_USER_AGENT"], "MSIE")) +// header("Content-Disposition: filename=" .$_GET["filename"]); // For IE +//else + header ("Content-Disposition: attachment; filename=" . basename($fname)); + ob_end_flush(); + + if (DB_lo_read_tobrowser ($_SESSION["usertable"]["contestnumber"],$lo) === false) { + echo "<html><head><title>Download Page</title>"; + DBExec($c, "rollback work"); + LOGError ("Unable to download file (" . basename($fname) . ")"); + MSGError ("Unable to download file (" . basename($fname) . ")"); + ForceLoad("index.php"); + } + DB_lo_close($lo); + + DBExec($c, "commit work"); + DBClose($c); +} else { + header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Cache-Control: no-cache, must-revalidate"); + header ("Pragma: no-cache"); +//header ("Content-type: application/octet-stream"); +//if (strstr($_SERVER["HTTP_USER_AGENT"], "MSIE")) +// header("Content-Disposition: filename=" .$_GET["filename"]); // For IE +//else + header ("Content-Disposition: attachment; filename=" . basename($fname)); + + if (($str=file_get_contents($fname))===false) { + header ("Content-type: text/html"); + echo "<html><head><title>Download Page</title>"; + MSGError ("Unable to open file (" . basename($fname) . ")"); + LOGError ("Unable to open file (" . basename($fname) . ")"); + ForceLoad('index.php'); + exit; + } else { + header ("Content-transfer-encoding: binary\n"); + header ("Content-type: application/force-download"); + echo decryptData($str, $cf["key"]); + } + ob_end_flush(); +} + +?> diff --git a/boca-1.5.0/src/filewindow.php b/boca-1.5.0/src/filewindow.php new file mode 100644 index 0000000..594e483 --- /dev/null +++ b/boca-1.5.0/src/filewindow.php @@ -0,0 +1,120 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// modified 21/july/2011 by cassio@ime.usp.br +ob_start(); +session_start(); +require_once("globals.php"); + +if(!ValidSession()) { + echo "<html><head><title>View Page</title>"; + InvalidSession("filewindow.php"); + echo "<script>window.close();</script></html>"; + exit; +} + +if(!isset($_GET["oid"]) || !is_numeric($_GET["oid"]) || !isset($_GET["filename"]) || + !isset($_GET["check"]) || $_GET["check"]=="") { + echo "<html><head><title>View Page</title>"; + IntrusionNotify("Bad parameters in filewindow.php"); + echo "<script>window.close();</script></html>"; + exit; +} + +$cf = globalconf(); +$fname = decryptData(rawurldecode($_GET["filename"]), session_id() . $cf["key"]); +$msg = ''; +if(isset($_GET["msg"])) + $msg = rawurldecode($_GET["msg"]); + +$p = myhash($_GET["oid"] . $fname . $msg . session_id() . $cf["key"]); + +if($p != $_GET["check"]) { + echo "<html><head><title>View Page</title>"; + IntrusionNotify("Parameters modified in filewindow.php"); + echo "<script>window.close();</script></html>"; + exit; +} + +require_once("db.php"); + +if ($_GET["oid"]>=0) { + $c = DBConnect(); + DBExec($c, "begin work"); + + if (($lo = DB_lo_open ($c, $_GET["oid"], "r")) === false) { + echo "<html><head><title>View Page</title>"; + DBExec($c, "rollback work"); + LOGError ("Unable to download file (" . basename($fname) . ")"); + MSGError ("Unable to download file (" . basename($fname) . ")"); + echo "<script>window.close();</script></html>"; + exit; + } + + header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Cache-Control: no-cache, must-revalidate"); + header ("Pragma: no-cache"); + header ("Content-type: text/plain"); + +// echo "<html><body>\n"; + if($msg != '') { +// echo " <a href=\"#\" onClick=\"window.print()\"><h1>".$_GET["msg"]."</h1></a>"; + echo $msg ."\n"; + echo $msg ."\n"; + echo $msg ."\n\n\n"; + } +// echo "<pre>\n"; + if (DB_lo_read_tobrowser ($_SESSION["usertable"]["contestnumber"],$lo) === false) { + header ("Content-type: text/html"); + echo "<html><head><title>View Page</title>"; + DBExec($c, "rollback work"); + LOGError ("Unable to open file (" . basename($fname) . ")"); + MSGError ("Unable to open file (" . basename($fname) . ")"); + echo "<script>window.close();</script></html>"; + exit; + } + ob_end_flush(); +// echo "</pre>\n"; + DB_lo_close($lo); + if($msg != '') { +// echo " <a href=\"#\" onClick=\"window.print()\"><h1>".$_GET["msg"]."</h1></a>"; + echo "\n\n\n".$msg ."\n"; + echo $msg ."\n"; + echo $msg ."\n"; + } + + DBExec($c, "commit work"); + DBClose($c); +} else { + header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Cache-Control: no-cache, must-revalidate"); + header ("Pragma: no-cache"); + if (($str = file_get_contents($fname))===false) { + header ("Content-type: text/html"); + echo "<html><head><title>View Page</title>"; + MSGError ("Unable to open file (" . basename($fname) . ")"); + LOGError ("Unable to open file (" . basename($fname) . ")"); + echo "<script>window.close();</script></html>"; + exit; + } + header ("Content-type: text/plain"); + echo decryptData($str, $cf["key"]); + ob_end_flush(); +} +?> diff --git a/boca-1.5.0/src/flanguage.php b/boca-1.5.0/src/flanguage.php new file mode 100644 index 0000000..120fad2 --- /dev/null +++ b/boca-1.5.0/src/flanguage.php @@ -0,0 +1,170 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +function DBDropLangTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"langtable\"", "DBDropLangTable(drop table)"); +} +function DBCreateLangTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"langtable\" ( + \"contestnumber\" int4 NOT NULL, + \"langnumber\" int4 NOT NULL, + \"langname\" varchar(50) NOT NULL, + \"langextension\" varchar(20) NOT NULL, + \"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) + CONSTRAINT \"lang_pkey\" PRIMARY KEY (\"contestnumber\", \"langnumber\"), + CONSTRAINT \"contest_fk\" FOREIGN KEY (\"contestnumber\") REFERENCES \"contesttable\" (\"contestnumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateLangTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"langtable\" FROM PUBLIC", "DBCreateLangTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"langtable\" TO \"".$conf["dbuser"]."\"", "DBCreateLangTable(grant bocauser)"); + $r = DBExec($c, "CREATE INDEX \"lang_index\" ON \"langtable\" USING btree ". + "(\"contestnumber\" int4_ops, \"langnumber\" int4_ops)", "DBCreateLangTable(create lang_index)"); + $r = DBExec($c, "CREATE INDEX \"lang_index2\" ON \"langtable\" USING btree ". + "(\"contestnumber\" int4_ops, \"langname\" varchar_ops)", "DBCreateLangTable(create lang_index2)"); +} + +//recebe o numero do contest +//devolve um array, onde cada linha tem os atributos number (numero da linguagem) e name (nome da linguagem) +function DBGetLanguages($contest) { + $c = DBConnect(); + $r = DBExec($c, "select distinct l.langnumber as number, l.langname as name, l.langextension as extension from langtable as l " . + "where l.contestnumber=$contest and l.langname !~ '(DEL)' order by l.langnumber", "DBGetLanguages(get lang)"); + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) + $a[$i] = DBRow($r,$i); + return $a; +} +//recebe o numero do contest e o numero da resposta e remove-a caso seu tipo nao seja fake + +function DBDeleteLanguage($contestnumber, $param, $c=null) { + $ac=array('number'); + foreach($ac as $key) { + if(!isset($param[$key])) { + MSGError("DBDeleteLanguage param error: $key not found"); + return false; + } + $$key = sanitizeText($param[$key]); + } + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBDeleteLanguage(transaction)"); + } + $sql = "select * from langtable where langnumber=$number and contestnumber=$contestnumber"; + + $r = DBExec($c, $sql . " for update", "DBDeleteLanguage(get lang for update)"); + + if(DBnlines($r)>0) { + $a = DBRow($r,0); + $r = DBExec($c, "update langtable set langname='".$a["langname"] ."(DEL)', updatetime=".time(). + " where contestnumber=$contestnumber and langnumber=$number ". + "", "DBDeleteLanguage(update)"); + $r = DBExec($c,"select runnumber as number, runsitenumber as site from runtable where contestnumber=$contestnumber and runlangnumber=$number for update"); + $n = DBnlines($r); + for ($i=0;$i<$n;$i++) { + $a = DBRow($r,$i); + DBRunDelete($a["number"],$a["site"],$contestnumber,$_SESSION["usertable"]["usernumber"],$_SESSION["usertable"]["usersitenumber"]); + } + } + if($cw) DBExec($c, "commit", "DBDeleteLanguage(commit)"); + LOGLevel("Language $number deleted (user=".$_SESSION["usertable"]["username"]. + "/".$_SESSION["usertable"]["usersitenumber"].")", 2); + return true; +} +function DBNewLanguage($contestnumber, $param, $c=null) { + if(isset($param["action"]) && $param["action"]=="delete") { + return DBDeleteLanguage($contestnumber, $param, $c); + } + $ac=array('number','name'); + $ac1=array('updatetime','extension'); + $type['number']=1; + $type['updatetime']=1; + $extension=''; + foreach($ac as $key) { + if(!isset($param[$key]) || $param[$key]=="") { + MSGError("DBNewLanguage param error: $key not found"); + return false; + } + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewLanguage param error: $key is not numeric"); + return false; + } + $$key = sanitizeText($param[$key]); + } + $updatetime=-1; + foreach($ac1 as $key) { + if(isset($param[$key])) { + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewLanguage param error: $key is not numeric"); + return false; + } + } + } + $t = time(); + if($updatetime <= 0) + $updatetime=$t; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBNewLanguage(transaction)"); + } + + $sql2 = "select * from langtable where contestnumber=$contestnumber and langnumber=$number"; + + $r = DBExec ($c, $sql2 . " for update", "DBNewLanguage(get lang)"); + $n = DBnlines($r); + $ret=1; + if ($n == 0) { + DBExec ($c, "insert into langtable (contestnumber,langnumber, langname,langextension) values ". + "($contestnumber, $number, '$name','$extension')", "DBNewLanguage(insert lang)"); + $s = "created"; + } + else { + $lr = DBRow($r,0); + $t = $lr['updatetime']; + if($updatetime > $t) { + if ($name != "") + DBExec ($c, "update langtable set langname='$name', updatetime=$updatetime where contestnumber=$contestnumber ". + "and langnumber=$number", "DBNewLanguage(update lang)"); + if ($extension != "") + DBExec ($c, "update langtable set langextension='$extension', updatetime=$updatetime where contestnumber=$contestnumber ". + "and langnumber=$number", "DBNewLanguage(update lang)"); + } + $s = "updated"; + } + if($cw) + DBExec($c, "commit work", "DBNewLanguage(commit)"); + if($s=="created" || $updatetime > $t) { + LOGLevel ("Language $number updated (user=".$_SESSION["usertable"]["usernumber"]. + ",site=".$_SESSION["usertable"]["usersitenumber"].",contest=$contestnumber)", 2); + $ret=2; + } + return $ret; +} +// eof +?> diff --git a/boca-1.5.0/src/flog.php b/boca-1.5.0/src/flog.php new file mode 100644 index 0000000..56fdfed --- /dev/null +++ b/boca-1.5.0/src/flog.php @@ -0,0 +1,228 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br + +function DBDropLogTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"logtable\"", "DBDropLogTable(drop table)"); +} +function DBCreateLogTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"logtable\" ( + \"lognumber\" serial, -- (serial para o log) + \"contestnumber\" int4 NOT NULL, -- (id do concurso) + \"sitenumber\" int4 NOT NULL, -- (id do site local) + \"loguser\" int4, -- (usuario envolvido com o log) + \"logip\" varchar(20) NOT NULL, -- (numero do site do usuario envolvido) + \"logdate\" int4 NOT NULL, -- (dia/hora da criacao deste registro) + \"logtype\" varchar(20) NOT NULL, -- (tipo de registro: error, warn, info, debug) + \"logdata\" text NOT NULL, -- (descricao do registro) + \"logstatus\" varchar(20) DEFAULT '', -- (status do registro) + CONSTRAINT \"log_pkey\" PRIMARY KEY (\"lognumber\"), + CONSTRAINT \"site_fk\" FOREIGN KEY (\"contestnumber\", \"sitenumber\") + REFERENCES \"sitetable\" (\"contestnumber\", \"sitenumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, + CONSTRAINT \"loguser\" FOREIGN KEY (\"contestnumber\", \"loguser\", \"sitenumber\") + REFERENCES \"usertable\" (\"contestnumber\", \"usernumber\", \"usersitenumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateLogTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"logtable\" FROM PUBLIC", "DBCreateLogTable(revoke public)"); + $r = DBExec($c, "GRANT INSERT, SELECT ON \"logtable\" TO \"".$conf["dbuser"]."\"", "DBCreateLogTable(grant bocauser)"); + $r = DBExec($c, "CREATE INDEX \"log_index\" ON \"logtable\" USING btree ". + "(\"contestnumber\" int4_ops, \"sitenumber\" int4_ops, \"logdate\" int4_ops)", + "DBCreateLogTable(create log_index)"); + $r = DBExec($c, "CREATE INDEX \"log_index2\" ON \"logtable\" USING btree ". + "(\"contestnumber\" int4_ops, \"loguser\" int4_ops, \"sitenumber\" int4_ops)", + "DBCreateLogTable(create log_index2)"); + $r = DBExec($c, "REVOKE ALL ON \"logtable_lognumber_seq\" FROM PUBLIC", "DBCreateLogTable(revoke public seq)"); + $r = DBExec($c, "GRANT ALL ON \"logtable_lognumber_seq\" TO \"".$conf["dbuser"]."\"", "DBCreateLogTable(grant bocauser seq)"); +} + +////////////////////funcoes para logar//////////////////////////////////////////////////////////////// +function DBNewLog($contest, $site, $user, $type, $ip, $data, $status) { + $t = time(); + $data = str_replace("'", "\"", $data); + DBExecNoSQLLog ("insert into logtable (contestnumber, sitenumber, loguser, logdate, logtype, " . + "logip, logdata, logstatus) values ($contest, $site, $user, $t, '$type', '$ip', '$data', '$status')", + "DBNewLog(insert log)"); +} +function DBGetLogs($o, $contest, $site, $user, $type, $ip, $limit) { + $c = DBConnect(); + $where = ""; + if ($site != "") $where .= "sitenumber=$site and "; + if ($user != "") $where .= "loguser=$user and "; + if ($type != "") $where .= "logtype='$type' and "; + if ($ip != "") $where .= "logip='$ip' and "; + $where .= "contestnumber=$contest"; + switch ($o) { + case "user": $order="contestnumber, sitenumber, loguser, logdate desc"; break; + case "type": $order="contestnumber, sitenumber, logtype, logdate desc"; break; + case "ip": $order="contestnumber, sitenumber, logip, logdate desc"; break; + default: $order="contestnumber, sitenumber, logdate desc"; break; + } + $r = DBExec ($c, "select contestnumber as contest, sitenumber as site, loguser as user, logdate as date, " . + "logtype as type, logip as ip, logdata as data, logstatus as status from logtable " . + " where $where order by $order limit $limit", "DBGetLogs(get logs)"); + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) + $a[$i] = DBRow($r,$i); + return $a; +} + +//funcao para fazer o login de um usuario. Vai procurar por um contest ativo, verificar qual o site +//local, e entao procurar pelo usuario no site local do contest ativo. Alem disso, verifica outras +//flags, como logins habilitados, ip correto, se usuario ja esta logado, etc +//$name eh o nome do usuario +//$pass eh o password +function DBLogIn($name,$pass, $msg=true) { + $b = DBGetRow("select * from contesttable where contestnumber=0", 0, null, "DBLogIn(get template contest)"); + if ($b != null) { + $r = DBLogInContest($name, $pass, $b["contestnumber"], false); + if($r !== false) return $r; + } + $b = DBGetRow("select * from contesttable where contestactive=true", 0, null, "DBLogIn(get active contest)"); + if ($b != null) { + $r = DBLogInContest($name, $pass, $b["contestnumber"], $msg); + if ($r !== false) return $r; + } else { + LOGLevel("There is no active or template contest.",0); + MSGError("There is no active or template contest."); + } + return false; +} +function DBLogInContest($name,$pass,$contest,$msg=true) { + $b = DBGetRow("select * from contesttable where contestnumber=$contest", 0, null, "DBLogIn(get active contest)"); + if ($b == null) { + LOGLevel("There is no contest $contest.",0); + if($msg) MSGError("There is no contest $contest, contact an admin."); + return false; + } + $d = DBSiteInfo($b["contestnumber"], $b["contestlocalsite"],null,false); + if ($d == null) { + if($msg) MSGError("There is no active site, contact an admin."); + return false; + } + $a = DBGetRow("select * from usertable where username='$name' and contestnumber=". + $b["contestnumber"]." and " . + "usersitenumber=".$b["contestlocalsite"], 0, null, "DBLogIn(get user)"); + if ($a == null) { + if($msg) { + LOGLevel("User $name tried to log in contest $contest but it does not exist.",2); + MSGError("User does not exist or incorrect password."); + } + return false; + } + $_SESSION['usertable'] = $a; + $p = myhash($a["userpassword"] . session_id()); + $_SESSION['usertable']['userpassword'] = $p; + if ($a["userpassword"] != "" && $p != $pass) { + LOGLevel("User $name tried to log in contest $contest but password was incorrect.",2); + if($msg) MSGError("User does not exist or incorrect password."); + unset($_SESSION["usertable"]); + return false; + } + if ($d["sitepermitlogins"]=="f" && $a["usertype"] != "admin" && $a["usertype"] != "judge") { + LOGLevel("User $name tried to login contest $contest but logins are denied.",2); + if($msg) MSGError("Logins are not allowed."); + unset($_SESSION["usertable"]); + return false; + } + if ($a["userenabled"] != "t") { + LOGLevel("User $name tried to log in contest $contest but it is disabled.",2); + if($msg) MSGError("User disabled."); + unset($_SESSION["usertable"]); + return false; + } + $gip=getIP(); + if ($a["userip"] != $gip && $a["userip"] != "" && $a["usertype"] != "score") { + LOGLevel("User $name is using two different IPs: " . $a["userip"] . + "(" . dateconv($a["userlastlogin"]) .") and " . $gip,1); + if($msg && $a["usertype"] != "admin") MSGError("You are using two distinct IPs. Admin notified."); + } + if ($a["userpermitip"] != "") { + $ips=explode(';',$a["userpermitip"]); + $gips=explode(';',$gip); + if(count($gips) < count($ips)) { + IntrusionNotify("Invalid IP: " . $gip); + ForceLoad("index.php"); + } + for($ipss=0;$ipss<count($ips);$ipss++) { + $gipi=$gips[$ipss]; + $ipi=$ips[$ipss]; + if(!match_network($ipi, $gipi)) { + IntrusionNotify("Invalid IP: " . $gip); + ForceLoad("index.php"); + } + } + } + $c = DBConnect(); + $t = time(); + if($a["usertype"] == "team" && $a["usermultilogin"] != "t" && $a["userpermitip"] == "") { + $r = DBExec($c,"update usertable set userip='" . $gip . "', updatetime=" . time() . ", userpermitip='" . $gip . "'," . + "userlastlogin=$t, usersession='".session_id()."' where username='$name' and contestnumber=". + $b["contestnumber"]." and usersitenumber=".$b["contestlocalsite"], "DBLogIn(update session)"); + } else { + DBExec($c,"begin work"); + $sql = "update usertable set usersessionextra='".session_id()."' where username='$name' and contestnumber=". + $b["contestnumber"]." and usersitenumber=".$b["contestlocalsite"] . + " and (usersessionextra='' or userip != '" . $gip ."' or userlastlogin<=" . ($t-86400) . ")"; + DBExec($c,$sql); + + DBExec($c,"update usertable set userip='" . $gip . "', updatetime=" . time() . ", userlastlogin=$t, ". + "usersession='".session_id()."' where username='$name' and contestnumber=". + $b["contestnumber"]." and usersitenumber=".$b["contestlocalsite"], "DBLogIn(update user)"); + if($name=='admin') { + list($clockstr,$clocktime)=siteclock(); + if($clocktime < -600) + DBExec($c,"update contesttable set contestunlockkey='' where contestnumber=" . $b["contestnumber"], "DBLogInContest(update contest)"); + } + DBExec($c,"commit work"); + } + LOGLevel("User $name authenticated (" . $gip . ")",2); + + return $a; +} +//faz o logout. Note que o timestamp de logout fica sem sentido quando o usuario +//eh do tipo multilogin +function DBLogOut($contest, $site, $user, $isadmin=false) { + $c = DBConnect(); + $r = DBExec($c,"update usertable set usersession='',usersessionextra='', updatetime=".time().", " . + "userlastlogout=".time()." where usernumber=$user and " . + "contestnumber=$contest and usersitenumber=$site", "DBLogOut(update user)"); + if($isadmin) { + list($clockstr,$clocktime)=siteclock(); + if($clocktime < -600) { + DBExec($c,"update contesttable set contestunlockkey='' where contestnumber=$contest", "DBLogOut(update contest)"); + DBExec($c,"update problemtable set problemfullname='', problembasefilename='' where problemfullname !~ '(DEL)' and contestnumber=$contest", "DBLogOut(update problems)"); + + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + $dir=$_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds; + foreach(glob($dir . '*') as $file) { + cleardir($file,false,true); + } + } + } + LOGLevel("User $user (contest=$contest,site=$site) logged out.",2); +} +// eof +?> diff --git a/boca-1.5.0/src/footnote.php b/boca-1.5.0/src/footnote.php new file mode 100644 index 0000000..062dadd --- /dev/null +++ b/boca-1.5.0/src/footnote.php @@ -0,0 +1,26 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +require 'versionnum.php'; + +echo "<br /><hr />\n"; +echo "<font size=\"-5\">Powered by BOCA $BOCAVERSION. Copyright (c) 2003-$YEAR BOCA System (bocasystem@gmail.com). All rights reserved.</font>\n"; +echo "</body></html>"; +exit; +?> diff --git a/boca-1.5.0/src/fproblem.php b/boca-1.5.0/src/fproblem.php new file mode 100644 index 0000000..dc8ed16 --- /dev/null +++ b/boca-1.5.0/src/fproblem.php @@ -0,0 +1,442 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br + +function DBDropProblemTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"problemtable\"", "DBDropProblemTable(drop table)"); +} +function DBCreateProblemTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"problemtable\" ( +\"contestnumber\" int4 NOT NULL, -- (id do concurso) +\"problemnumber\" int4 NOT NULL, -- (id do problema) +\"problemname\" varchar(20) NOT NULL, -- (nome do problema) +\"problemfullname\" varchar(100) DEFAULT '', -- (nome completo do problema) +\"problembasefilename\" varchar(100), -- (nome base dos arquivos do problema) +\"probleminputfilename\" varchar(100) DEFAULT '', -- (nome do arquivo de entrada) +\"probleminputfile\" oid, -- (apontador para o arquivo de entrada) +\"probleminputfilehash\" varchar(50), -- (apontador para o arquivo de entrada) +\"fake\" bool DEFAULT 'f' NOT NULL, -- (indica se o problema eh valido para submissoes. Util para + -- clarification em General, por exemplo) +\"problemcolorname\" varchar(100) DEFAULT '', -- nome da cor do problema +\"problemcolor\" varchar(6) DEFAULT '', -- cor do problema, formato html (RGB hexadecimal) +\"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +-- (tabela com os problemas. Se um problema tiver mais que par de arquivos +-- entrada/solucao, entao colocamos mais que uma linha para ele aqui.) +CONSTRAINT \"problem_pkey\" PRIMARY KEY (\"contestnumber\", \"problemnumber\"), +CONSTRAINT \"contest_fk\" FOREIGN KEY (\"contestnumber\") REFERENCES \"contesttable\" (\"contestnumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateProblemTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"problemtable\" FROM PUBLIC", "DBCreateProblemTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"problemtable\" TO \"".$conf["dbuser"]."\"", "DBCreateProblemTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"problem_index\" ON \"problemtable\" USING btree ". + "(\"contestnumber\" int4_ops, \"problemnumber\" int4_ops)", "DBCreateProblemTable(create problem_index)"); + $r = DBExec($c, "CREATE INDEX \"problem_index2\" ON \"problemtable\" USING btree ". + "(\"contestnumber\" int4_ops, \"problemname\" varchar_ops)", "DBCreateProblemTable(create problem_index2)"); +} + +//////////////////////funcoes de problemas////////////////////////////////////////////////////////////// +//recebe um numero de contest e numero de problema +//devolve todos os dados relativos ao problema em cada linha do array, sendo que cada linha representa o fato +//que existe mais que um arquivo de entrada/sol. Nao retorna dados sobre problemas fake, ja que eles nao devem ter. +function DBGetProblemData($contestnumber, $problemnumber) { + $c = DBConnect(); + $r = DBExec($c, "select p.problemname as problemname, p.problemfullname as fullname, p.problembasefilename " . + "as basefilename, p.problemtimelimit as timelimit, " . + "p.problemcolor as color, p.problemcolorname as colorname, " . + "p.probleminputfilename as inputfilename, p.probleminputfile as inputoid, p.probleminputfilehash as inputhash " . + " from problemtable as p where p.contestnumber=$contestnumber and p.problemnumber=$problemnumber and p.fake!='t'", + "DBGetProblemData(get problem)"); + $n = DBnlines($r); + if ($n == 0) { + LOGError("Unable to find problem data in the database ($contestnumber, $problemnumber)"); + MSGError("Unable to find problem data in the database. Contact an admin now!"); + exit; + } + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + $ptmp = $_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds . "problem" . $a[$i]['number'] . "-contest" . $contestnumber; + if(is_readable($ptmp . ".name")) { + $a[$i]['descfilename']=$ptmp . $ds . file_get_contents($ptmp . ".name"); + $a[$i]['descoid']=-1; + } + } + return $a; +} +function DBGetFullProblemData($contestnumber,$freeproblems=false) { + $c = DBConnect(); + DBExec($c, "begin work", "GetFullProblemData"); + $r = DBExec($c, "select p.problemnumber as number, p.problemname as name, p.problemfullname as fullname, " . + "p.problembasefilename as basefilename, p.fake as fake, p.problemtimelimit as timelimit, " . + "p.problemcolor as color, p.problemcolorname as colorname, " . + "p.probleminputfilename as inputfilename, p.probleminputfile as inputoid, p.probleminputfilehash as inputhash " . + " from problemtable as p " . + "where p.contestnumber=$contestnumber and p.problemfullname !~ '(DEL)' order by p.problemnumber", + "DBGetFullProblemData(get problem)"); + $n = DBnlines($r); + if ($n == 0) { + LOGLevel("No problems defined in the database ($contestnumber)",1); + } + $cf = globalconf(); + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = array_merge(array(),DBRow($r,$i)); + $nn=$a[$i]['number']; + if($freeproblems && $a[$i]['fake'] != 't') { + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + $ptmp = $_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds . "problem" . $nn . "-contest" . $contestnumber; + if(is_readable($ptmp . ".name")) { + $a[$i]['descfilename']=$ptmp . $ds . file_get_contents($ptmp . ".name"); + $a[$i]['descoid']=-1; + } else { + $randnum = session_id() . "_" . rand(); + $dir = $ptmp . '-' . $randnum; + @mkdir($dir,0770,true); + $failed=0; + if(($ret=DB_lo_export($contestnumber, $c, $a[$i]["inputoid"], $dir . $ds . "tmp.zip")) === false) { + LogError("FreeProblems: Unable to read problem package from database (problem=$nn, contest=$contestnumber)"); + $failed=1; + } + if(!$failed) { + $zip = new ZipArchive; + if ($zip->open($dir . $ds . "tmp.zip") === true) { + $zip->extractTo($dir); + $zip->close(); + if(($info=@file($dir . $ds . "description" . $ds . 'problem.info'))===false) { + $failed=2; + } + if(!$failed) { + $descfile=''; + $basename=''; + $fullname=''; + foreach($info as $line) { + $aa=explode('=',$line); + if(trim($aa[0])=='descfile') { + $descfile=trim(sanitizeText($aa[1])); + } + if(trim($aa[0])=='basename') { + $basename=trim(sanitizeText($aa[1])); + } + if(trim($aa[0])=='fullname') { + $fullname=trim(sanitizeText($aa[1])); + } + } + if($descfile=='' || $basename=='' || $fullname=='') + $failed=3; + } + } else $failed=4; + if(!$failed) { + @mkdir($ptmp); + if(file_put_contents($ptmp . $ds . $descfile, encryptData(file_get_contents($dir . $ds . "description" . $ds . $descfile),$cf['key']),LOCK_EX)===FALSE) + $failed=5; + if(!$failed) { + file_put_contents($ptmp . ".name",$descfile); + if(is_readable($ptmp . ".name")) { + $a[$i]['descfilename']=$ptmp . $ds . $descfile; + $a[$i]['descoid']=-1; + } + DBExec($c,"update problemtable set problemfullname='$fullname', problembasefilename='$basename' where problemnumber=$nn and contestnumber=$contestnumber", + "DBGetFullProblemData(free problem)"); + $a[$i]['basefilename']=$basename; + $a[$i]['fullname']=$fullname; + } + } + } + if($failed) { + if($failed!=4) { + LogError("Failed to unzip problem package (failcode=$failed, problem=$nn, contest=$contestnumber)"); + if($failed==1) $a[$i]['fullname']='(ERROR READING FROM DATABASE, OR DIRECTORY PERMISSION PROBLEM)'; + else $a[$i]['fullname']='(PROBLEM PACKAGE SEEMS INVALID)'; + } else { + if($ret==1) $a[$i]['fullname']='(PROBABLY ENCRYPTED FILE)'; + if($ret==2) $a[$i]['fullname']='(FILE IS NOT A ZIP)'; + } + } + cleardir($dir,false,true); + } + } + } + DBExec($c, "commit", "GetFullProblemData"); + return $a; +} +function DBDeleteProblem($contestnumber, $param, $c=null) { + $ac=array('number','inputfilename'); + foreach($ac as $key) { + if(!isset($param[$key])) return false; + $$key = sanitizeText($param[$key]); + } + + $sql = "select * from problemtable where problemnumber=$number and contestnumber=$contestnumber and fake='f'"; + if ($inputfilename != "") + $sql .= " and probleminputfilename='$inputfilename'"; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBDeleteProblem(transaction)"); + } + + $r = DBExec($c, $sql . " for update", "DBDeleteProblem(get for update)"); + if(DBnlines($r)>0) { + $a = DBRow($r,0); + $sql="update problemtable set problemfullname='".$a["problemfullname"] ."(DEL)', updatetime=".time(). + " where contestnumber=$contestnumber and problemnumber=$number "; + if ($inputfilename != "") + $sql .= " and probleminputfilename='$inputfilename'"; + + $r = DBExec($c, $sql, "DBDeleteLanguage(update)"); + $r = DBExec($c,"select runnumber as number, runsitenumber as site from runtable where contestnumber=$contestnumber and runproblem=$number for update"); + $n = DBnlines($r); + for ($i=0;$i<$n;$i++) { + $a = DBRow($r,$i); + DBRunDelete($a["number"],$a["site"],$contestnumber,$_SESSION["usertable"]["usernumber"],$_SESSION["usertable"]["usersitenumber"]); + } + } + if($cw) + DBExec($c, "commit", "DBDeleteProblem(commit)"); + + LOGLevel("Problem $number (inputfile=$inputfilename) deleted (user=". + $_SESSION["usertable"]["username"]."/".$_SESSION["usertable"]["usersitenumber"] . ")",2); + return true; +} +function DBNewProblem($contestnumber, $param, $c=null) { + if(isset($param["action"]) && $param["action"]=="delete") { + return DBDeleteProblem($contestnumber, $param); + } + + $ac=array('number','name'); + $type['number']=1; + $type['updatetime']=1; + $ac1=array('colorname','fake','color','updatetime','fullname', + 'basename','inputfilename','inputfilepath'); + $colorname=''; + $color=''; + $fake='f'; + foreach($ac as $key) { + if(!isset($param[$key])) { + MSGError("DBNewProblem param error: $key is not set"); + return false; + } + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewProblem param error: $key is not numeric"); + return false; + } + $$key = sanitizeText($param[$key]); + } + $basename=''; + $inputfilename=''; + $inputfilepath=''; + $fullname=''; + $updatetime=-1; + foreach($ac1 as $key) { + if(isset($param[$key])) { + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewProblem param error: $key is not numeric"); + return false; + } + $$key = sanitizeText($param[$key]); + } + } + $t = time(); + if($updatetime <= 0) + $updatetime=$t; + $inputhash = ''; + + $sql2 = "select * from problemtable where contestnumber=$contestnumber and problemnumber=$number for update"; +// "select * from problemtable where contestnumber=$contestnumber and problemnumber=$number " . +// "and probleminputfilename='$inputfilename'"; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBNewProblem(transaction)"); + } + $r = DBExec ($c, $sql2, "DBNewProblem(get problem for update)"); + $n = DBnlines($r); + $ret=1; + $oldfullname=''; + $deservesupdatetime=false; + if ($n == 0) { + DBExec ($c, "insert into problemtable (contestnumber, problemnumber, problemname) values " . + "($contestnumber, $number, '$name')", "DBNewProblem(insert problem)"); + $deservesupdatetime=true; + $s = "created"; + } + else { + $lr = DBRow($r,0); + $t = $lr['updatetime']; + $oldfullname=$lr['problemfullname']; + $s = "updated"; + $inputhash = $lr['probleminputfilehash']; + } + if($s=="created" || $updatetime > $t) { + if(substr($inputfilepath,0,7)!="base64:") { + if ($inputfilepath != "") { + $hash = myshorthash(file_get_contents($inputfilepath)); + if($hash != $inputhash) { + $oldoid=''; + if(isset($lr)) + $oldoid = $lr['probleminputfile']; + if (($oid1 = DB_lo_import($c, $inputfilepath)) === false) { + DBExec($c, "rollback work", "DBNewProblem(rollback-input)"); + LOGError("Unable to create a large object for file $inputfilename."); + MSGError("problem importing file to database. See log for details!"); + exit; + } + if($oldoid != '') DB_lo_unlink($c,$oldoid); + $inputhash = DBcrc($contestnumber, $oid1, $c); + } else + $oid1 = $lr['probleminputfile']; + } + } else { + $inputfilepath = base64_decode(substr($inputfilepath,7)); + $hash = myshorthash($inputfilepath); + if($hash != $inputhash) { + $oldoid=''; + if(isset($lr)) + $oldoid = $lr['probleminputfile']; + if (($oid1 = DB_lo_import_text($c, $inputfilepath)) == null) { + DBExec($c, "rollback work", "DBNewProblem(rollback-i-import)"); + LOGError("Unable to import the large object for file $inputfilename."); + MSGError("problem importing file to database. See log for details!"); + exit; + } + if($oldoid != '') DB_lo_unlink($c,$oldoid); + $inputhash = DBcrc($contestnumber, $oid1, $c); + } else + $oid1 = $lr['probleminputfile']; + } + if ($name != "") + DBExec ($c, "update problemtable set problemname='$name' where contestnumber=$contestnumber ". + "and problemnumber=$number", "DBNewProblem(update name)"); + if ($fullname != "" || strpos($oldfullname,'(DEL)')!==false) { + $deservesupdatetime=true; + DBExec ($c, "update problemtable set problemfullname='$fullname' where contestnumber=$contestnumber ". + "and problemnumber=$number", "DBNewProblem(update fullname)"); + } + if ($basename != "") { + $deservesupdatetime=true; + DBExec ($c, "update problemtable set problembasefilename='$basename' where contestnumber=$contestnumber ". + "and problemnumber=$number", "DBNewProblem(update basename)"); + } + if ($colorname != "") + DBExec ($c, "update problemtable set problemcolorname='$colorname' where contestnumber=$contestnumber ". + "and problemnumber=$number", "DBNewProblem(update colorname)"); + if ($color != "") + DBExec ($c, "update problemtable set problemcolor='$color' where contestnumber=$contestnumber ". + "and problemnumber=$number", "DBNewProblem(update color)"); + if ($inputfilename != "") { + $deservesupdatetime=true; + DBExec ($c, "update problemtable set probleminputfilename='$inputfilename' where ". + "contestnumber=$contestnumber and problemnumber=$number ", "DBNewProblem(update inputfilename)"); + } + if ($inputfilepath != "") { + $deservesupdatetime=true; + DBExec ($c, "update problemtable set probleminputfile=$oid1,probleminputfilehash='$inputhash' where contestnumber=$contestnumber and ". + "problemnumber=$number ", "DBNewProblem(update inputfile)"); + } + if ($fake == "t") { + $deservesupdatetime=true; + DBExec ($c, "update problemtable set fake='$fake' where contestnumber=$contestnumber and ". + "problemnumber=$number", "DBNewProblem(update fake)"); + } + + if($deservesupdatetime) { + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + @unlink($_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds . "problem" . $number . "-contest" . $contestnumber . '.name'); + DBExec ($c, "update problemtable set updatetime=" . $updatetime . + " where contestnumber=$contestnumber and problemnumber=$number", "DBNewProblem(time)"); + } + if($cw) + DBExec($c, "commit work", "DBNewProblem(commit)"); + LOGLevel ("Problem $number (inputfile=$inputfilename) $s (user=".$_SESSION["usertable"]["usernumber"]. + ",site=".$_SESSION["usertable"]["usersitenumber"].",contest=$contestnumber)", 2); + $ret=2; + } else { + if($cw) + DBExec($c, "commit work", "DBNewProblem(commit)"); + } + return $ret; +} +//recebe o numero do contest +//devolve um array, onde cada linha tem os atributos number (numero do problema), problem (nome do problema), +//descfilename (nome do arquivo com a descricao do problema) e descoid (large object com a descricao) +function DBGetProblems($contest,$showanyway=false) { + if (($b = DBSiteInfo($contest,$_SESSION["usertable"]["usersitenumber"])) == null) + return array(); + + if ($b["currenttime"] < 0 && !$showanyway) + return array(); + + $c = DBConnect(); + $sql = "select distinct p.problemnumber as number, p.problemname as problem, " . + "p.problemfullname as fullname, p.problembasefilename as basefilename, " . + "p.problemcolor as color, p.problemcolorname as colorname " . + "from problemtable as p where p.fake!='t' and p.contestnumber=$contest and p.problemfullname !~ '(DEL)' order by p.problemnumber"; + $r = DBExec($c, $sql, "DBGetProblems(get problems)"); + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + $ptmp = $_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds . "problem" . $a[$i]['number'] . "-contest" . $contestnumber; + if(is_readable($ptmp . ".name")) { + $a[$i]['descfilename']=$ptmp . $ds . file_get_contents($ptmp . ".name"); + $a[$i]['descoid']=-1; + } + } + return $a; +} +//recebe o numero do contest +//devolve um array, onde cada linha tem os atributos number (numero do problema) e problem (nome do problema) +//para todos os problemas, inclusive os fakes +function DBGetAllProblems($contest) { + if (($b = DBSiteInfo($contest,$_SESSION["usertable"]["usersitenumber"])) == null) + return array(); + + $c = DBConnect(); + $sql = "select distinct p.problemnumber as number, p.problemname as problem, " . + "p.problemcolor as color, p.problemcolorname as colorname " . + "from problemtable as p " . + "where p.contestnumber=$contest and p.problemfullname !~ '(DEL)' "; + if ($b["currenttime"] < 0) $sql .= "and p.fake='t' "; + $sql .= " order by p.problemnumber"; + $r = DBExec($c, $sql, "DBGetAllProblems(get problems)"); + + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) + $a[$i] = DBRow($r,$i); + return $a; +} +// eof +?> diff --git a/boca-1.5.0/src/freport.php b/boca-1.5.0/src/freport.php new file mode 100644 index 0000000..e25bd16 --- /dev/null +++ b/boca-1.5.0/src/freport.php @@ -0,0 +1,133 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +function DBRunReport($contest,$site) { + $c = DBConnect(); + $sql = "select r.runnumber as number, u.usernumber as un, u.username as user, r.rundatediff as timestamp, " . + "p.problemname as problem, l.langname as language, a.runanswer as answer, a.yes as yes " . + "from runtable as r, problemtable as p, langtable as l, answertable as a, usertable as u " . + "where r.contestnumber=$contest and p.contestnumber=r.contestnumber and " . + "r.runproblem=p.problemnumber and l.contestnumber=r.contestnumber and " . + "l.langnumber=r.runlangnumber and a.answernumber=r.runanswer and " . + "a.contestnumber=r.contestnumber and (r.runstatus = 'judged' or r.runstatus = 'judged+') and " . + "u.usernumber=r.usernumber and u.contestnumber=$contest and " . + "u.usersitenumber=r.runsitenumber"; + if($site != "") $sql .= " and r.runsitenumber=$site"; + $xdados = array(); + $xuser = array(); + $xuserfull = array(); + $xuseryes = array(); + $xproblem = array(); + $xproblemyes = array(); + + $xusername = array(); + $r = DBExec($c, "select usernumber as un, username as name, userfullname as fullname ". + "from usertable where contestnumber=$contest ". + "and usersitenumber=$site and ". + "usertype='team' and userlastlogin is not null and userenabled='t'", "DBRunReport(get users)"); + $n = DBnlines($r); + for ($i=0;$i<$n;$i++) { + $a = DBRow($r,$i); + $xusername[$a['un']] = $a['name']; + $xuserfull[$a['name']] = $a['fullname']; + } + ksort($xusername); + + $pr = DBGetProblems($contest); + for($i=0; $i<count($pr); $i++) { + $xproblem[$pr[$i]['problem']]=0; + $xproblemyes[$pr[$i]['problem']]=0; + $xcolor[$pr[$i]['problem']]=$pr[$i]['color']; + } + + $xlanguage = array(); + $xlanguageyes = array(); + $xanswer = array(); + $xtimestamp = array(); + $xtimestampyes = array(); + + $r = DBExec($c, $sql, "DBRunReport(get runs)"); + $n = DBnlines($r); + + for ($i=0;$i<$n;$i++) { + $a = DBRow($r,$i); + $xdados[$i] = $a; + // # of runs by team + $xuser[$a['user']]++; + // # of runs by problem + $xproblem[$a['problem']]++; + if($a['yes'] == 't') { + $xuseryes[$a['user']]++; + $xproblemyes[$a['problem']]++; + } + // # of runs by language + $xlanguage[$a['language']]++; + if($a['yes'] == 't') + $xlanguageyes[$a['language']]++; + // # of runs by answer + $xanswer[$a['answer']]++; + // time of the runs + array_push($xtimestamp, $a['timestamp']); + if($a['yes'] == 't') + array_push($xtimestampyes, $a['timestamp']); + + // # of runs by answer by problem + $xpa[$a['problem']][$a['answer']]++; + // # of runs by language by problem + $xpl[$a['problem']][$a['language']]++; + // # of runs by answer by language + $xla[$a['language']][$a['answer']]++; + // # of runs by problem by user + // negative sign means team got an yes for the problem + if($xup[$a['user']][$a['problem']] < 0) + $xup[$a['user']][$a['problem']]--; + else { + $xup[$a['user']][$a['problem']]++; + if($a['yes'] == 't') $xup[$a['user']][$a['problem']] = - $xup[$a['user']][$a['problem']]; + } + } + ksort($xuser); + ksort($xuseryes); + ksort($xproblem); + ksort($xproblemyes); + ksort($xlanguage); + ksort($xlanguageyes); + ksort($xanswer); + sort($xtimestamp); + sort($xtimestampyes); + $x = array( + 'color' => $xcolor, + 'user' => $xuser, + 'useryes' => $xuseryes, + 'username' => $xusername, + 'userfull' => $xuserfull, + 'problem' => $xproblem, + 'problemyes' => $xproblemyes, + 'language' => $xlanguage, + 'languageyes' => $xlanguageyes, + 'answer' => $xanswer, + 'timestamp' => $xtimestamp, + 'timestampyes' => $xtimestampyes, + 'pa' => $xpa, + 'pl' => $xpl, + 'la' => $xla, + 'up' => $xup); + return $x; +} +?> diff --git a/boca-1.5.0/src/frun.php b/boca-1.5.0/src/frun.php new file mode 100644 index 0000000..fcf05c0 --- /dev/null +++ b/boca-1.5.0/src/frun.php @@ -0,0 +1,949 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br + +function DBDropRunTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"runtable\"", "DBDropRunTable(drop table)"); +} +function DBCreateRunTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"runtable\" ( +\"contestnumber\" int4 NOT NULL, -- (id do concurso) +\"runsitenumber\" int4 NOT NULL, -- (local de origem da submissao) +\"runnumber\" int4 NOT NULL, -- (numero da submissao) +\"usernumber\" int4 NOT NULL, -- (numero do time) +\"rundate\" int4 NOT NULL, -- (dia/hora da submissao no local de origem) +\"rundatediff\" int4 NOT NULL, -- (diferenca entre inicio da competicao e dia/hora da submissao em seg) +\"rundatediffans\" int4 NOT NULL, -- (diferenca entre inicio da competicao e dia/hora da correcao em seg) +\"runproblem\" int4 NOT NULL, -- (id do problema) +\"runfilename\" varchar(200) NOT NULL, -- (nome do arquivo submetido) +\"rundata\" oid NOT NULL, -- (codigo fonte do arquivo submetido) +\"runanswer\" int4 DEFAULT 0 NOT NULL, -- (resposta dada no julgamento) +\"runstatus\" varchar(20) NOT NULL, -- (status da submissao: openrun, judging, judged, deleted, judged+) +\"runjudge\" int4 DEFAULT NULL, -- (juiz que esta julgando) +\"runjudgesite\" int4 DEFAULT NULL, -- (juiz que esta julgando) +\"runanswer1\" int4 DEFAULT 0 NOT NULL, -- (resposta dada no julgamento) +\"runjudge1\" int4 DEFAULT NULL, -- (juiz que esta julgando) +\"runjudgesite1\" int4 DEFAULT NULL, -- (juiz que esta julgando) +\"runanswer2\" int4 DEFAULT 0 NOT NULL, -- (resposta dada no julgamento) +\"runjudge2\" int4 DEFAULT NULL, -- (juiz que esta julgando) +\"runjudgesite2\" int4 DEFAULT NULL, -- (juiz que esta julgando) +\"runlangnumber\" int4 NOT NULL, -- (linguagem do codigo fonte) + +\"autoip\" varchar(20) DEFAULT '', -- os campos auto... sao para a correcao automatica +\"autobegindate\" int4 DEFAULT NULL, +\"autoenddate\" int4 DEFAULT NULL, +\"autoanswer\" text DEFAULT '', +\"autostdout\" oid DEFAULT NULL, +\"autostderr\" oid DEFAULT NULL, + +\"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +CONSTRAINT \"run_pkey\" PRIMARY KEY (\"contestnumber\", \"runsitenumber\", \"runnumber\"), +CONSTRAINT \"user_fk\" FOREIGN KEY (\"contestnumber\", \"runsitenumber\", \"usernumber\") + REFERENCES \"usertable\" (\"contestnumber\", \"usersitenumber\", \"usernumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, +CONSTRAINT \"problem_fk\" FOREIGN KEY (\"contestnumber\", \"runproblem\") + REFERENCES \"problemtable\" (\"contestnumber\", \"problemnumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, +CONSTRAINT \"answer_fk\" FOREIGN KEY (\"contestnumber\", \"runanswer\") + REFERENCES \"answertable\" (\"contestnumber\", \"answernumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE, +CONSTRAINT \"lang_fk\" FOREIGN KEY (\"contestnumber\", \"runlangnumber\") + REFERENCES \"langtable\" (\"contestnumber\", \"langnumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateRunTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"runtable\" FROM PUBLIC", "DBCreateRunTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"runtable\" TO \"".$conf["dbuser"]."\"", "DBCreateRunTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"run_index\" ON \"runtable\" USING btree ". + "(\"contestnumber\" int4_ops, \"runsitenumber\" int4_ops, \"runnumber\" int4_ops)", + "DBCreateRunTable(create run_index)"); + $r = DBExec($c, "CREATE INDEX \"run_index2\" ON \"runtable\" USING btree ". + "(\"contestnumber\" int4_ops, \"runsitenumber\" int4_ops, \"usernumber\" int4_ops)", + "DBCreateRunTable(create run_index2)"); +} + +///////////////////////////////funcoes de runs/////////////////////////////////////////////////////// +//responde uma run. Recebe o numero do contest, site do usuario, num do usuario, site da run, +//numero da run, numero da resposta, (notifyuser e updatescore). +//tenta alterar o status para 'judged'. +function DBChiefUpdateRun($contest, $usersite, $usernumber, $runsite, $runnumber, $answer) { + return DBUpdateRunC($contest, $usersite, $usernumber, $runsite, $runnumber, $answer, 1); +} +function DBUpdateRunO($contest, $usersite, $usernumber, $runsite, $runnumber, $answer, $c) { + return DBUpdateRunC($contest, $usersite, $usernumber, $runsite, $runnumber, $answer, 1, $c); +} +function DBUpdateRun($contest, $usersite, $usernumber, $runsite, $runnumber, $answer) { + return DBUpdateRunC($contest, $usersite, $usernumber, $runsite, $runnumber, $answer, 0); +} +function DBUpdateRunC($contest, $usersite, $usernumber, $runsite, $runnumber, $answer, $chief, $c=null) { + $a = DBGetRow("select * from answertable where answernumber=$answer and contestnumber=$contest",0,null, + "DBUpdateRunC(get answer)"); + if ($a == null) { + MSGError("Problem with the answer table. Contact an admin now!"); + LogLevel("Unable to judge a run because the answer was not found (run=$runnumber, site=$runsite, ". + "contest=$contest, answer=$answer).",0); + return false; + } + if ($a["fake"] == 't') { + MSGError("You must choose a valid answer."); + LogLevel("Unable to judge a run because of the fake answer (run=$runnumber, site=$runsite, ". + "contest=$contest, answer=$answer).",0); + return false; + } + $yes = $a["yes"]; + $b = DBSiteInfo($contest, $runsite); + if ($b == null) { + exit; + } + + $bw = 0; + if($c==null) { + $bw = 1; + $c = DBConnect(); + DBExec($c, "begin work", "DBUpdateRunC(transaction)"); + } + + $sql = "select * from runtable as r where r.contestnumber=$contest and " . + "r.runsitenumber=$runsite and r.runnumber=$runnumber"; + if ($chief != 1) { + $sql .= " and (r.runstatus='judging' or r.runstatus='judged+') and " . + "((r.runjudge1=$usernumber and r.runjudgesite1=$usersite) or " . + " (r.runjudge2=$usernumber and r.runjudgesite2=$usersite))"; + $tx = "Judge"; + } else $tx = "Chief"; + $r = DBExec ($c, $sql . " for update", "DBUpdateRunC(get run for update)"); + $n = DBnlines($r); + if ($n != 1) { + if($bw == 1) { + DBExec($c, "rollback work", "DBUpdateRunC(rollback)"); + LogLevel("Unable to judge a run (maybe it was already judged or catched by a chief) " . + "(run=$runnumber, site=$runsite, contest=$contest).",2); + MSGError("Unable to judge the run (maybe it was already judged or catched by a chief)"); + } + return false; + } + $temp = DBRow($r,0); + $t = $b["currenttime"]; + + $team=$temp["usernumber"]; + if ($temp["runanswer"] != "") + $tinhabalao = DBBalloon($contest, $runsite, $temp["usernumber"], $temp["runproblem"], ($bw==1)); + else $tinhabalao = false; + + if($temp["runjudge1"]==$usernumber && $temp["runjudgesite1"]==$usersite) { + DBExec($c, "update runtable set runanswer1=$answer, updatetime=".time()." " . + "where contestnumber=$contest and runnumber=$runnumber and runsitenumber=$runsite", + "DBUpdateRunC(update run judge1)"); + $outra = $temp["runanswer2"]; + } + if($temp["runjudge2"]==$usernumber && $temp["runjudgesite2"]==$usersite) { + DBExec($c, "update runtable set runanswer2=$answer, updatetime=".time()." " . + "where contestnumber=$contest and runnumber=$runnumber and runsitenumber=$runsite", + "DBUpdateRunC(update run judge2)"); + $outra = $temp["runanswer1"]; + } + $newstatus = 'judging'; + if($chief == 1 || ($outra != 0 && $outra == $answer && $temp["runstatus"] != "judged+") || + ($outra != 0 && $outra == $answer && $temp["runanswer"]==$answer)) { + $newstatus = 'judged'; + DBExec($c, "update runtable set runstatus='judged', " . + "runjudge=$usernumber, runjudgesite=$usersite, " . + "runanswer=$answer, rundatediffans=$t, updatetime=".time()." " . + "where contestnumber=$contest and runnumber=$runnumber and runsitenumber=$runsite", + "DBUpdateRunC(update run)"); + + $tembalao = DBBalloon($contest, $runsite, $temp["usernumber"], $temp["runproblem"], ($bw==1)); + +// if ($runsite==$usersite) { + if (!$tinhabalao && $tembalao) { + if (($b = DBSiteInfo($contest, $runsite)) == null) + return true; + $ta = $b["currenttime"]; + $tf = $b["sitelastmileanswer"]; + if ($ta < $tf) { + $u = DBUserInfo ($contest, $runsite, $team); + if($u['usertype']=='team') { + $p = DBGetProblemData ($contest, $temp["runproblem"]); + DBNewTask_old ($contest, $runsite, $team, + escape_string("\"" . $u["username"] ."\" must have a balloon for problem " . + $p[0]["problemname"] . ": " . $p[0]["fullname"]), + "", "", "t", $p[0]["color"], $p[0]["colorname"], $c); + } + } + } else if ($tinhabalao && !$tembalao) { + $u = DBUserInfo ($contest, $runsite, $team); + if($u['usertype']=='team') { + $p = DBGetProblemData ($contest, $temp["runproblem"]); + DBNewTask_old ($contest, $runsite, $team, escape_string("\"" . + $u["username"] ."\" must have _NO_ balloon for problem " . $p[0]["problemname"] . + ": " . $p[0]["fullname"]). ". Please verify and remove it, if needed.", "", "", + "t", $p[0]["color"], $p[0]["colorname"], $c); + } + } +// } + } + + if($bw == 1) { + DBExec($c, "commit work", "DBUpdateRunC(commit)"); + LOGLevel("Run updated (run=$runnumber,site=$runsite,user=$team,contest=$contest,newstatus=$newstatus,". + "judge=$usernumber(site=$usersite),answer=$answer(".$a["runanswer"].")).", 3); + } + return true; +} +//devolve uma run que estava sendo respondida. Recebe o numero da run, o numero do site da run e o numero do contest. +//tenta alterar o status para 'openrun'. Se nao conseguir retorna false +function DBChiefRunGiveUp($number,$site,$contest) { + return DBRunGiveUp($number,$site,$contest,-1,-1); +} +function DBRunGiveUp($number,$site,$contest,$usernumber,$usersite) { + $c = DBConnect(); + DBExec($c, "begin work", "DBRunGiveUp(transaction)"); + $sql = "select * from runtable as r where r.contestnumber=$contest and " . + "r.runsitenumber=$site and r.runnumber=$number"; + if ($usernumber != 1 && $usersite != -1) { + $sql .= " and (r.runstatus='judging' or r.runstatus='judged+') and " . + "((r.runjudge1=$usernumber and r.runjudgesite1=$usersite) or " . + " (r.runjudge2=$usernumber and r.runjudgesite2=$usersite))"; + $tx = "Judge"; + } else $tx = "Chief"; + $r = DBExec ($c, $sql . " for update", "DBRunGiveUp(get run for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBRunGiveUp(rollback)"); + LogLevel("Unable to return a run (maybe the timeout or a chief returned it first). ". + "(run=$number, site=$site, contest=$contest)",2); + return false; + } + $temp = DBRow($r, 0); + + $tinhabalao = DBBalloon($contest, $site, $temp["usernumber"], $temp["runproblem"]); + + $outra = -1; + if($temp["runjudge1"]==$usernumber && $temp["runjudgesite1"]==$usersite) { + DBExec($c, "update runtable set runjudge1=NULL, runjudgesite1=NULL, runanswer1=0 " . + " where contestnumber=$contest and runnumber=$number and runsitenumber=$site", + "DBRunGiveUp(update run judge1)"); + $outra = $temp['runanswer2']; + } + if($temp["runjudge2"]==$usernumber && $temp["runjudgesite2"]==$usersite) { + DBExec($c, "update runtable set runjudge2=NULL, runjudgesite2=NULL, runanswer2=0 " . + " where contestnumber=$contest and runnumber=$number and runsitenumber=$site", + "DBRunGiveUp(update run judge1)"); + $outra = $temp['runanswer1']; + } + + $newstatus="judging"; + if($temp["runstatus"]=="judged" || $temp["runstatus"]=="judged+") { + DBExec($c, "update runtable set runstatus='judged+', " . + ($tx=="Chief" ? "runanswer1=0, runanswer2=0, runjudge1=NULL, runjudge2=NULL, runjudgesite1=NULL, runjudgesite2=NULL, ": "") . + " updatetime=" . + time()." where contestnumber=$contest and runnumber=$number and runsitenumber=$site", + "DBRunGiveUp(update run)"); + $newstatus='judged+'; + } else { + if($outra == 0 || $tx=="Chief") { + DBExec($c, "update runtable set runstatus='openrun', runanswer=0, runjudge=NULL, runjudgesite=NULL, ". + "runanswer1=0, runanswer2=0, runjudge1=NULL, runjudge2=NULL, runjudgesite1=NULL, runjudgesite2=NULL, ". + "updatetime=" . + time()." where contestnumber=$contest and runnumber=$number and runsitenumber=$site", + "DBRunGiveUp(update run)"); + $newstatus='openrun'; + } + } + $tembalao = DBBalloon($contest, $site, $temp["usernumber"], $temp["runproblem"]); + if ($tinhabalao && !$tembalao) { + $u = DBUserInfo ($contest, $site, $temp["usernumber"]); + if($u['usertype']=='team') { + $p = DBGetProblemData ($contest, $temp["runproblem"]); + DBNewTask_old ($contest, $site, $temp["usernumber"], escape_string("\"" . + $u["username"] ."\" must have _NO_ balloon for problem " . $p[0]["problemname"] . + ": " . $p[0]["fullname"]), "", "", "t", $p[0]["color"], $p[0]["colorname"], $c); + } + } + + DBExec($c, "commit work", "DBRunGiveUp(commit)"); + LOGLevel("Run returned (run=$number, site=$site, contest=$contest, user=$usernumber(site=$usersite)), ". + "newstatus=$newstatus", 3); + return true; +} +function DBRunDelete($number,$site,$contest,$user,$usersite) { + $c = DBConnect(); + DBExec($c, "begin work", "DBRunDelete(transaction)"); + $sql = "select * from runtable as r where r.contestnumber=$contest and " . + "r.runsitenumber=$site and r.runnumber=$number"; + $r = DBExec ($c, $sql . " for update", "DBRunDelete(get run for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBRunDelete(rollback)"); + LogLevel("Unable to delete a run. ". + "(run=$number, site=$site, contest=$contest)",1); + return false; + } + $temp = DBRow($r, 0); + + $tinhabalao = DBBalloon($contest, $site, $temp["usernumber"], $temp["runproblem"]); + + DBExec($c, "update runtable set runstatus='deleted', runjudge=$user, runjudgesite=$usersite, updatetime=" . + time()." where contestnumber=$contest and runnumber=$number and runsitenumber=$site", + "DBRunDelete(update run)"); + + $tembalao = DBBalloon($contest, $site, $temp["usernumber"], $temp["runproblem"]); + if ($tinhabalao && !$tembalao) { + $u = DBUserInfo ($contest, $site, $temp["usernumber"]); + if($u['usertype']=='team') { + $p = DBGetProblemData ($contest, $temp["runproblem"]); + DBNewTask_old ($contest, $site, $temp["usernumber"], escape_string("\"" . + $u["username"] . "\" must have _NO_ balloon for problem " . $p[0]["problemname"] . + ": " . $p[0]["fullname"]), "", "", "t", $p[0]["color"], $p[0]["colorname"], $c); + } + } + + DBExec($c, "commit work", "DBRunDelete(commit)"); + LOGLevel("Run deleted (run=$number, site=$site, contest=$contest, user=$user(site=$usersite)).", 3); + return true; +} + +//pega uma run para julgar. Recebe o numero da run, o numero do site e o numero do contest. +//tenta alterar o status para 'judging' e se conseguir, devolve um array com dados da run. Se nao conseguir, +//retorna false +//Retorna no array: contestnumber, sitenumber, number, timestamp (em segundos), problemname, +// problemnumber, language, sourcename, sourceoid, (langscript, infiles, solfiles) +function DBChiefGetRunToAnswer($number,$site,$contest) { + return DBGetRunToAnswerC($number,$site,$contest,1); +} +function DBGetRunToAnswer($number,$site,$contest) { + return DBGetRunToAnswerC($number,$site,$contest,0); +} +function DBGetRunToAnswerC($number,$site,$contest,$chief) { + $c = DBConnect(); + DBExec($c, "begin work", "DBGetRunToAnswerC(transaction)"); + $sql = "select r.contestnumber as contestnumber, r.runsitenumber as sitenumber, r.runanswer as answer, " . + "r.runanswer1 as answer1, r.runanswer2 as answer2, " . + "r.runjudge as judge, r.runjudgesite as judgesite, " . + "r.runjudge1 as judge1, r.runjudgesite1 as judgesite1, r.runjudge2 as judge2, r.runjudgesite2 as judgesite2, " . + "r.runnumber as number, r.rundatediff as timestamp, r.runstatus as status, " . + "r.rundata as sourceoid, r.runfilename as sourcename, l.langnumber as langnumber, " . + "p.problemname as problemname, p.problemnumber as problemnumber, l.langname as language, l.langextension as extension, " . + "r.autoip as autoip, r.autobegindate as autobegin, r.autoenddate as autoend, r.autoanswer as autoanswer, ". + "r.autostdout as autostdout, r.autostderr as autostderr ". + + "from runtable as r, problemtable as p, langtable as l " . + "where r.contestnumber=$contest and p.contestnumber=r.contestnumber and " . + "r.runproblem=p.problemnumber and r.runsitenumber=$site and " . + "r.runlangnumber=l.langnumber and r.contestnumber=l.contestnumber and " . + "r.runnumber=$number"; + if ($chief != 1) { + $sql .= " and (r.runstatus='openrun' or " . + "(r.runstatus='judged+' and r.runjudge is NULL) or " . + "((r.runstatus='judging' or r.runstatus='judged+') and " . + " (r.runjudge1 is null or r.runjudge2 is null or " . + " ((r.runjudge1=" . $_SESSION["usertable"]["usernumber"] . " and " . + " r.runjudgesite1=" . $_SESSION["usertable"]["usersitenumber"] . ") or " . + " (r.runjudge2=" . $_SESSION["usertable"]["usernumber"] . " and " . + " r.runjudgesite2=" . $_SESSION["usertable"]["usersitenumber"] . ")))))"; + $tx = "Judge"; + } else $tx = "Chief"; + $r = DBExec ($c, $sql . " for update", "DBGetRunToAnswerC(get run/prob/lang for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBGetRunToAnswerC(rollback)"); + LogLevel("Unable to get a run (maybe other judge got it first). (run=$number, site=$site, ". + "contest=$contest)",2); + return false; + } + $a = DBRow($r,0); + + if ($chief != 1) { + $upd=""; + if($a["status"]=="openrun") $upd="runstatus='judging',"; + + if(($a["judge1"]!=$_SESSION["usertable"]["usernumber"] || + $a["judgesite1"]!=$_SESSION["usertable"]["usersitenumber"]) && + ($a["judge2"]!=$_SESSION["usertable"]["usernumber"] || + $a["judgesite2"]!=$_SESSION["usertable"]["usersitenumber"])) { + if($a["judge1"]=='' && $a['judgesite1']=='') { + DBExec($c, "update runtable set runjudge1=" . $_SESSION["usertable"]["usernumber"] . + ",$upd updatetime=".time().", " . + "runjudgesite1=" . $_SESSION["usertable"]["usersitenumber"] . " " . + "where contestnumber=$contest and runnumber=$number and runsitenumber=$site", + "DBGetRunToAnswerC(update run judge1)"); + } else { + DBExec($c, "update runtable set runjudge2=" . $_SESSION["usertable"]["usernumber"] . + ",$upd updatetime=".time().", " . + "runjudgesite2=" . $_SESSION["usertable"]["usersitenumber"] . " " . + "where contestnumber=$contest and runnumber=$number and runsitenumber=$site", + "DBGetRunToAnswerC(update run judge2)"); + } + } + } + + DBExec($c, "commit work", "DBGetRunToAnswerC(commit)"); + LOGLevel("User got a run (run=$number, site=$site, contest=$contest, user=". + $_SESSION["usertable"]["usernumber"]. + "(site=".$_SESSION["usertable"]["usersitenumber"] .")).", 3); + return $a; +} +function DBGetRunToAutojudging($contest, $ip) { + $c = DBConnect(); + DBExec($c, "begin work", "DBGetRunToAnswerC(transaction)"); + $sql = "select r.contestnumber as contest, r.runsitenumber as site, r.runanswer as answer, " . + "r.runanswer1 as answer1, r.runanswer2 as answer2, " . + "r.runnumber as number, r.rundatediff as timestamp, r.runstatus as status, " . + "r.rundata as sourceoid, r.runfilename as sourcename, l.langnumber as langnumber, " . + "p.problemname as problemname, p.problemnumber as problemnumber, l.langextension as extension, l.langname as language, " . + "p.problembasefilename as basename, p.problemtimelimit as timelimit, ". + "p.probleminputfilename as inputname, p.probleminputfile as inputoid, " . + "p.problemsolfilename as solname, p.problemsolfile as soloid, " . + "r.autoip as autoip, r.autobegindate as autobegin, r.autoenddate as autoend, r.autoanswer as autoanswer, ". + "r.autostdout as autostdout, r.autostderr as autostderr ". + "from runtable as r, problemtable as p, langtable as l " . + "where r.contestnumber=$contest and p.contestnumber=r.contestnumber and " . + "r.runproblem=p.problemnumber and r.runlangnumber=l.langnumber and ". + "r.contestnumber=l.contestnumber and " . + "r.autoip='' order by r.runnumber for update limit 1"; + $r = DBExec ($c, $sql, "DBGetRunToAutoJudging(get run/prob/lang for update)"); + $n = DBnlines($r); + if ($n < 1) { + DBExec($c, "rollback work", "DBGetRunToAutoJudging(rollback)"); + return false; + } + $a = DBRow($r,0); + $t = time(); + + DBExec($c, "update runtable set autoip='" . $ip . "', " . + "autobegindate=$t, autoenddate=null, autoanswer=null, autostdout=null, autostderr=null, " . + "updatetime=$t " . + "where contestnumber=${a["contest"]} and runnumber=${a["number"]} and runsitenumber=${a["site"]}", + "DBGetRunToAutojudging(update run)"); + + DBExec($c, "commit work", "DBGetRunToAutojudging(commit)"); + LOGLevel("Autojudging got a run (run=${a["number"]}, site=${a["site"]}, contest=${a["contest"]})", 3); + return $a; +} +function DBUpdateRunAutojudging($contest, $site, $number, $ip, $answer, $stdout, $stderr, $retval=0) { + if($retval=="") $retval=0; + $c = DBConnect(); + DBExec($c, "begin work", "DBUpdateRunAutojudging(transaction)"); + $sql = "select * from runtable as r " . + "where r.contestnumber=$contest and r.runnumber=$number and r.runsitenumber=$site and " . + "r.autoip='$ip'"; + $r = DBExec ($c, $sql . " for update", "DBUpdateRunAutoJudging(get run for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBUpdateRunAutoJudging(rollback)"); + LogLevel("Unable to get a run for autojudging (run=$number, site=$site, contest=$contest)",1); + return false; + } + $a = DBRow($r,0); + $b = DBSiteInfo($contest, $site, $c); + $t = time(); + + if (($oid1 = DB_lo_import($c, $stdout)) === false) { + DBExec($c, "rollback work", "DBUpdateRunAutojudging(rollback-stdout)"); + LOGError("Unable to create a large object for file $stdout."); + return false; + } + + if (($oid2 = DB_lo_import($c, $stderr)) === false) { + DBExec($c, "rollback work", "DBUpdateRunAutojudging(rollback-stderr)"); + LOGError("Unable to create a large object for file $stderr."); + return false; + } + + if($answer=="") $answer="null"; + else $answer="'$answer'"; + DBExec($c, "update runtable set autoenddate=$t, autoanswer=$answer, autostdout=$oid1, autostderr=$oid2, " . + "updatetime=$t " . + "where contestnumber=$contest and runnumber=$number and runsitenumber=$site", + "DBUpdateRunAutojudging(update run)"); + + $b = DBSiteInfo($contest, $site, $c); + + if($b["siteautojudge"]!="t") { + DBExec($c, "commit work", "DBUpdateRunAutojudging(commit)"); + LOGLevel("Autojudging answered a run (run=$number, site=$site, contest=$contest, answer='$answer', retval=$retval)", 3); + return true; + } + + echo "DEBUG: $contest, $site, " .$a["usernumber"].", $site, $number, $retval\n"; + if(DBUpdateRunO($contest, $site, $a["usernumber"], $site, $number, $retval, $c)==false) { + DBExec($c, "rollback work", "DBUpdateRunAutoJudging(rollback)"); + LOGError("Unable to automatically update a run answer (run=$number, site=$site, ". + "contest=$contest, answer='$answer', retval=$retval)"); + return false; + } + DBExec($c, "commit work", "DBUpdateRunAutojudging(commit)"); + LOGLevel("Autojudging automatically answered a run (run=$number, site=$site, contest=$contest, retval=$retval, answer='$answer')", 3); + return true; +} +function DBGiveUpRunAutojudging($contest, $site, $number, $ip="", $ans="") { + $c = DBConnect(); + DBExec($c, "begin work", "DBGiveUpRunAutojudging(transaction)"); + $sql = "select * from runtable as r " . + "where r.contestnumber=$contest and r.runnumber=$number and r.runsitenumber=$site"; + $r = DBExec ($c, $sql . " for update", "DBGiveUpRunAutoJudging(get run for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBGiveUpRunAutoJudging(rollback)"); + LogLevel("Unable to giveup a run from autojudging (run=$number, site=$site, contest=$contest)",1); + return false; + } + $a = DBRow($r,0); + $t = time(); + + if($ip=="") { + DBExec($c, "update runtable set autoenddate=null, autoanswer=null, autostdout=null, autostderr=null, " . + "updatetime=$t, autobegindate=null, autoip='' " . + "where contestnumber=$contest and runnumber=$number and runsitenumber=$site", + "DBGiveUpRunAutojudging(update run)"); + } else { + DBExec($c, "update runtable set autoenddate=$t, autoanswer='$ans', autostdout=null, ". + "autostderr=null, updatetime=$t, autoip='$ip' " . + "where contestnumber=$contest and runnumber=$number and runsitenumber=$site", + "DBGiveUpRunAutojudging(update run-withip)"); + } + DBExec($c, "commit work", "DBGiveUpRunAutojudging(commit)"); + LOGLevel("Run gaveup from Autojudging (run=$number, site=$site, contest=$contest)", 3); + return true; +} +function DBAllRuns($contest) { + return DBOpenRunsSNS($contest,"x",-1); +} +function DBAllRunsInSites($contest,$site,$order='run') { + return DBOpenRunsSNS($contest,$site,-1,$order); +} +//function DBOpenRuns($contest) { +// return DBOpenRunsSNS($contest,"x",1); +//} +function DBOpenRunsInSites($contest,$site) { + return DBOpenRunsSNS($contest,$site,1); +} +function DBOpenRunsSNS($contest,$site,$st,$order='run') { + $c = DBConnect(); + $sql = "select distinct r.runnumber as number, r.rundatediff as timestamp, r.usernumber as user, " . + "p.problemname as problem, r.runstatus as status, l.langname as language, l.langextension as extension, " . + "a.yes as yes, p.problemcolor as color, p.problemcolorname as colorname, " . + "r.runsitenumber as site, r.runjudge as judge, r.runjudgesite as judgesite, " . + "r.runjudge1 as judge1, r.runjudgesite1 as judgesite1, " . + "r.runjudge2 as judge2, r.runjudgesite2 as judgesite2, " . + "a.runanswer as answer, r.runfilename as filename, " . + "r.runanswer1 as answer1, r.runanswer2 as answer2, " . + "r.autobegindate as autobegin, r.autoenddate as autoend, r.autoanswer as autoanswer ". + "from runtable as r, problemtable as p, langtable as l, answertable as a " . + "where r.contestnumber=$contest and p.contestnumber=r.contestnumber and " . + "r.runproblem=p.problemnumber and l.contestnumber=r.contestnumber and " . + "l.langnumber=r.runlangnumber and a.answernumber=r.runanswer and " . + "a.contestnumber=r.contestnumber"; + if ($site != "x") { + $str = explode(",", $site); + $sql .= " and (r.runsitenumber=-1"; + for ($i=0;$i<count($str);$i++) { + if (is_numeric($str[$i])) $sql .= " or r.runsitenumber=".$str[$i]; + } + $sql .= ")"; + } + + if ($st == 1) { + $sql .= " and (not (r.runjudge1=". $_SESSION["usertable"]["usernumber"] . " and " . + "r.runjudgesite1=". $_SESSION["usertable"]["usersitenumber"] . " and r.runanswer1!=0)) and "; + $sql .= " (not (r.runjudge2=". $_SESSION["usertable"]["usernumber"] . " and " . + "r.runjudgesite2=". $_SESSION["usertable"]["usersitenumber"] . " and r.runanswer2!=0)) and " . + + "(not ((r.runjudge1!=". $_SESSION["usertable"]["usernumber"] . " or " . + "r.runjudgesite1!=". $_SESSION["usertable"]["usersitenumber"] . ") and " . + " (r.runjudge2!=". $_SESSION["usertable"]["usernumber"] . " or " . + "r.runjudgesite2!=". $_SESSION["usertable"]["usersitenumber"] . ") and " . + " (not (r.runjudge1 is null)) and (not (r.runjudge2 is null))))"; + $sql .= " and (not r.runstatus = 'judged') " . + " and not r.runstatus ~ 'deleted' order by "; + } else $sql .= " order by "; + + if($order == "site") + $sql .= "r.runsitenumber,"; + else if ($order == "status") + $sql .= "r.runstatus,"; + else if ($order == "judge") + $sql .= "r.runjudge,r.runjudgesite,"; + else if ($order == "problem") + $sql .= "p.problemname,"; + else if ($order == "language") + $sql .= "l.langname,"; + else if ($order == "answer") + $sql .= "a.runanswer,"; + else if ($order == "user") + $sql .= "r.usernumber,r.runsitenumber,"; + + if ($st == 1 || $order == "normal") + $sql .= "r.runnumber"; + else + $sql .= "r.rundatediff desc"; + + $r = DBExec($c, $sql, "DBOpenRunsSNS(get run/prob/lang/ans)"); + + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) + $a[$i] = DBRow($r,$i); + return $a; +} +function DBNewRun($param,$c=null) { + if(isset($param['contestnumber']) && !isset($param['contest'])) $param['contest']=$param['contestnumber']; + if(isset($param['sitenumber']) && !isset($param['site'])) $param['site']=$param['sitenumber']; + if(isset($param['usernumber']) && !isset($param['user'])) $param['user']=$param['usernumber']; + if(isset($param['number']) && !isset($param['runnumber'])) $param['runnumber']=$param['number']; + if(isset($param['runlangnumber']) && !isset($param['lang'])) $param['lang']=$param['runlangnumber']; + if(isset($param['runproblem']) && !isset($param['problem'])) $param['problem']=$param['runproblem']; + + $ac=array('contest','site','user','problem','lang','filename','filepath'); + $ac1=array('runnumber','rundate','rundatediff','rundatediffans','runanswer','runstatus','runjudge','runjudgesite', + 'runjudge1','runjudgesite1','runanswer1','runjudge2','runjudgesite2','runanswer2', + 'autoip','autobegindate','autoenddate','autoanswer','autostdout','autostderr','updatetime'); + $type['contest']=1; + $type['autobegindate']=1; + $type['autoenddate']=1; + $type['problem']=1; + $type['updatetime']=1; + $type['site']=1; + $type['user']=1; + $type['runnumber']=1; + $type['rundatediffans']=1; + $type['rundatediff']=1; + $type['rundate']=1; + $type['runanswer']=1; + $type['runjudge']=1; + $type['runjudgesite']=1; + $type['runjudge1']=1; + $type['runjudgesite1']=1; + $type['runanswer1']=1; + $type['runjudge2']=1; + $type['runjudgesite2']=1; + $type['runanswer2']=1; + foreach($ac as $key) { + if(!isset($param[$key]) || $param[$key]=="") { + MSGError("DBNewRun param error: $key not found"); + return false; + } + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewRun param error: $key is not numeric"); + return false; + } + $$key = sanitizeText($param[$key]); + } + $t = time(); + $autoip=''; + $autobegindate='NULL'; + $autoenddate='NULL'; + $autoanswer=''; + $autostdout=''; + $autostderr=''; + $runjudge='NULL'; + $runjudgesite='NULL'; + $runjudge1='NULL'; + $runjudgesite1='NULL'; + $runanswer1=0; + $runjudge2='NULL'; + $runjudgesite2='NULL'; + $runanswer2=0; + $runnumber=-1; + $updatetime = -1; + $rundatediff = -1; + $rundate = $t; + $runanswer=0; + $rundatediffans = 999999999; + $runstatus='openrun'; + foreach($ac1 as $key) { + if(isset($param[$key])) { + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewRun param error: $key is not numeric"); + return false; + } + } + } + if($updatetime < 0) + $updatetime=$t; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBNewRun(transaction)"); + } + $insert=true; + $oid1 = ''; + $oid2 = ''; + $oldold1=''; + $oldold2=''; + $sql = "select sitenextrun as nextrun from " . + "sitetable where sitenumber=$site and contestnumber=$contest for update"; + $r = DBExec($c, $sql, "DBNewRun(get site for update)"); + if (DBnlines($r) != 1) { + DBExec($c, "rollback work", "DBNewRun(rollback-site)"); + LOGError("Unable to find a unique site/contest in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find a unique site/contest in the database."); + exit; + } + $a = DBRow($r,0); + $n = $a["nextrun"] + 1; + if($runnumber > 0) { + $sql = "select * from runtable as t where t.contestnumber=$contest and " . + "t.runsitenumber=$site and t.runnumber=$runnumber"; + $r = DBExec ($c, $sql . " for update", "DBNewRun(get run for update)"); + $n = DBnlines($r); + if ($n > 0) { + $insert=false; + $lr = DBRow($r,0); + $t = $lr['updatetime']; + if(isset($lr['autostdout'])) + $oid1 = $lr['autostdout']; + if(isset($lr['autostderr'])) + $oid2 = $lr['autostderr']; + } + $n = $runnumber; + } else + $runnumber = $n; + + if($rundatediff < 0) { + $b = DBSiteInfo($contest, $site, $c); + $dif = $b["currenttime"]; + $rundatediff = $dif; + if ($dif < 0) { + DBExec($c, "rollback work", "DBNewRun(rollback-started)"); + LOGError("Tried to submit a run but the contest is not started. SQL=(" . $sql . ")"); + MSGError("The contest is not started yet!"); + return false; + } + if (!$b["siterunning"]) { + DBExec($c, "rollback work", "DBNewRun(rollback-over)"); + LOGError("Tried to submit a run but the contest is over. SQL=(" . $sql . ")"); + MSGError("The contest is over!"); + return false; + } + } else { + $dif = $rundatediff; + } + + if($updatetime > $t || $insert) { + DBExec($c, "update sitetable set sitenextrun=$runnumber, updatetime=".$t. + " where sitenumber=$site and contestnumber=$contest and sitenextrun<$runnumber", "DBNewRun(update site)"); + +// LOGError($autostdout); + if(substr($autostdout,0,7)=="base64:") { + $autostdout = base64_decode(substr($autostdout,7)); + $oldoid1 = $oid1; + if (($oid1 = DB_lo_import_text($c, $autostdout)) == null) { + DBExec($c, "rollback work", "DBNewRun(rollback-import stdout)"); + LOGError("Unable to create a large object for file stdout (run=$runnumber,site=$site,contest=$contest)."); + MSGError("problem importing stdout to database. Contact an admin now!"); + exit; + } + } else { + if($autostdout != '') { + DBExec($c, "rollback work", "DBNewRun(rollback-import stderr)"); + LOGError("Unable to create a large object for file stdout that is not BASE64 (run=$runnumber,site=$site,contest=$contest)."); + MSGError("problem importing stdout (not BASE64) to database. Contact an admin now!"); + exit; + } + $oid1 = 'NULL'; + } + if(substr($autostderr,0,7)=="base64:") { +// LOGError($autostderr); + $autostderr = base64_decode(substr($autostderr,7)); + $oldoid2 = $oid2; + if (($oid2 = DB_lo_import_text($c, $autostderr)) == null) { + DBExec($c, "rollback work", "DBNewRun(rollback-import stderr)"); + LOGError("Unable to create a large object for file stderr (run=$runnumber,site=$site,contest=$contest)."); + MSGError("problem importing stderr to database. Contact an admin now!"); + exit; + } + } else { + if($autostderr != '') { + DBExec($c, "rollback work", "DBNewRun(rollback-import stderr)"); + LOGError("Unable to create a large object for file stderr that is not BASE64 (run=$runnumber,site=$site,contest=$contest)."); + MSGError("problem importing stderr (not BASE64) to database. Contact an admin now!"); + exit; + } + $oid2 = 'NULL'; + } + } + $ret=1; + if($insert) { + if(substr($filepath,0,7)!="base64:") { + if (($oid = DB_lo_import($c, $filepath)) === false) { + DBExec($c, "rollback work", "DBNewRun(rollback-import)"); + LOGError("DBNewRun: Unable to create a large object for file $filepath."); + MSGError("problem importing file $filepath to database. Contact an admin now!"); + exit; + } + } else { + $filepath = base64_decode(substr($filepath,7)); + if (($oid = DB_lo_import_text($c, $filepath)) == null) { + DBExec($c, "rollback work", "DBNewRun(rollback-import)"); + LOGError("DBNewRun: Unable to create a large object for file."); + MSGError("problem importing file to database. Contact an admin now!"); + exit; + } + } + DBExec($c, "INSERT INTO runtable (contestnumber, runsitenumber, runnumber, usernumber, rundate, " . + "rundatediff, rundatediffans, runproblem, runfilename, rundata, runanswer, runstatus, runlangnumber, " . + "runjudge, runjudgesite, runanswer1, runjudge1, runjudgesite1, runanswer2, runjudge2, runjudgesite2, ". + "autoip, autobegindate, autoenddate, autoanswer, autostdout, autostderr, updatetime) " . + "VALUES ($contest, $site, $n, $user, $rundate, $rundatediff, $rundatediffans, $problem, '$filename', $oid, $runanswer, " . + "'$runstatus', $lang, $runjudge, $runjudgesite, $runanswer1, $runjudge1, $runjudgesite1, $runanswer2, $runjudge2, " . + "$runjudgesite2, '$autoip', $autobegindate, $autoenddate, '$autoanswer', $oid1, $oid2, $updatetime)", + "DBNewRun(insert run)"); + if($cw) { + DBExec($c, "commit work", "DBNewRun(commit)"); + LOGLevel("User $user submitted a run (#$n) on site #$site " . + "(problem=$problem,filename=$filename,lang=$lang,contest=$contest,date=$t,datedif=$dif,oid=$oid).",2); + } + $ret=2; + } else { + if($updatetime > $t) { + $ret=2; + DBExec($c, "update runtable set rundate=$rundate, rundatediff=$rundatediff, " . + "rundatediffans=$rundatediffans, runanswer=$runanswer, runanswer1=$runanswer1, runanswer2=$runanswer2, runstatus='$runstatus', ". + "runjudge1=$runjudge1, runjudgesite1=$runjudgesite1, runjudge2=$runjudge2, runjudgesite2=$runjudgesite2, " . + "runjudge=$runjudge, runjudgesite=$runjudgesite, updatetime=$updatetime, ". + "autoip='$autoip', autobegindate=$autobegindate, autoenddate=$autoenddate, autoanswer='$autoanswer', " . + "autostdout=$oid1, autostderr=$oid2 " . + "where runnumber=$runnumber and contestnumber=$contest and runsitenumber=$site", "DBNewRun(update run)"); + + if(is_numeric($oldoid1)) DB_lo_unlink($c,$oldoid1); + if(is_numeric($oldoid2)) DB_lo_unlink($c,$oldoid2); + } + if($cw) DBExec($c, "commit work", "DBNewRun(commit-update)"); + } + return $ret; +/* // isso gera problemas de portabilidade e de seguranca (quando outros usuarios tambem tem shell + // no servidor e podem construir paginas web. Eles podem usar essas paginas para acessar esses arquivos, + // pois os mesmos ficaram com dono apache/www-data/etc) + umask(0077); + @mkdir("/tmp/boca"); + if (!move_uploaded_file ($filepath, + "/tmp/boca/contest${contest}.site${site}.run${n}.user${user}.problem${problem}.time${t}.${filename}")) + LOGLevel("Run not saved as file (run=$n,site=$site,contest=$contest", 1); +*/ +} +//recebe o numero do contest, o numero do site e o numero do usuario +//devolve um array, onde cada linha tem os atributos +// number (numero da run) +// timestamp (hora da criacao da run) +// problem (nome do problema) +// status (situacao da run) +// answer (texto com a resposta) +function DBUserRuns($contest,$site,$user) { + $b = DBSiteInfo($contest, $site); + if ($b == null) { + exit; + } + $t = $b["currenttime"]; + + $c = DBConnect(); + $r = DBExec($c, "select distinct r.runnumber as number, r.rundatediff as timestamp, " . + "r.runfilename as filename, r.rundata as oid, " . + "p.problemcolorname as colorname, p.problemcolor as color, a.yes as yes, " . + "p.problemname as problem, r.runstatus as status, l.langname as language, l.langextension as extension, " . + "a.runanswer as answer, a.fake as ansfake, r.rundatediffans as anstime, " . + "r.runanswer1 as answer1, r.runanswer2 as answer2 " . + "from runtable as r, problemtable as p, answertable as a, langtable as l " . + "where r.contestnumber=$contest and p.contestnumber=r.contestnumber and " . + "l.contestnumber=r.contestnumber and l.langnumber=r.runlangnumber and " . + "r.contestnumber=a.contestnumber and r.runproblem=p.problemnumber and " . + "r.runsitenumber=$site and r.usernumber=$user and not r.runstatus ~ 'deleted' and " . + "(r.rundatediffans<=$t or (r.runstatus != 'judged' and r.rundatediff<=$t)) and " . + "a.answernumber=r.runanswer order by r.runnumber", + "DBUserRuns(get run/prob/ans/lang)"); + $n = DBnlines($r); + + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + if ($a[$i]["timestamp"] >= $b["sitelastmileanswer"]) + $a[$i]["answer"] = ""; + } + return $a; +} +function DBUserRunsYES($contest,$site,$user) { + $b = DBSiteInfo($contest, $site); + if ($b == null) { + exit; + } + $t = $b["currenttime"]; + $c = DBConnect(); + $r = DBExec($c, "select distinct p.problemcolorname as colorname, p.problemcolor as color, " . + "r.rundatediff as timestamp, p.problemnumber as number " . + "from runtable as r, problemtable as p, answertable as a " . + "where r.contestnumber=$contest and p.contestnumber=r.contestnumber and " . + "r.contestnumber=a.contestnumber and r.runproblem=p.problemnumber and " . + "r.runsitenumber=$site and r.usernumber=$user and not r.runstatus ~ 'deleted' and " . + "(r.rundatediffans<=$t or (r.runstatus != 'judged' and r.rundatediff<=$t)) and " . + "a.answernumber=r.runanswer and a.yes='t' order by r.rundatediff", + "DBUserRunsYES(get run/prob/ans/lang)"); + $n = DBnlines($r); + + $a = array(); $j=0; + $p = array(); + for ($i=0;$i<$n;$i++) { + $aa = DBRow($r,$i); + if ($aa["timestamp"] < $b["sitelastmileanswer"]) { + if(!isset($p[$aa["number"]])) { + $p[$aa["number"]] = 1; + $a[$j] = $aa; + $j++; + } + } + } + return $a; +} +//recebe o numero do contest, o numero do site do juiz e o numero do juiz +//devolve um array, onde cada linha tem os atributos +// number (numero da run) +// timestamp (hora da criacao da run) +// problem (nome do problema) +// status (situacao da run) +// answer (texto com a resposta) +function DBJudgedRuns($contest,$site,$user) { + $c = DBConnect(); + $r = DBExec($c, "select distinct r.runsitenumber as site, r.runnumber as number, r.rundatediff as timestamp, " . + "p.problemname as problem, r.runstatus as status, l.langname as language, l.langextension as extension, " . + "a.runanswer as answer, r.updatetime, r.runanswer1 as answer1, r.runanswer2 as answer2 " . + "from runtable as r, problemtable as p, answertable as a, langtable as l " . + "where r.contestnumber=$contest and p.contestnumber=r.contestnumber and " . + "l.contestnumber=r.contestnumber and l.langnumber=r.runlangnumber and " . + "r.contestnumber=a.contestnumber and r.runproblem=p.problemnumber and " . + "a.answernumber=r.runanswer and " . + "((r.runjudgesite=$site and r.runjudge=$user) or ". + " (r.runjudgesite1=$site and r.runjudge1=$user) or ". + " (r.runjudgesite2=$site and r.runjudge2=$user)) ". + " order by r.updatetime", + "DBJudgedRuns(get run/prob/ans/lang)"); + $n = DBnlines($r); + + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + return $a; +} +// eof +?> diff --git a/boca-1.5.0/src/fscore.php b/boca-1.5.0/src/fscore.php new file mode 100644 index 0000000..abbe22f --- /dev/null +++ b/boca-1.5.0/src/fscore.php @@ -0,0 +1,349 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +////////////////////////////funcoes para placar/////////////////////////////////////////////// +function ScoreCMP($a,$b) { + if ($a["totalcount"]=="") $a["totalcount"]=0; + if ($b["totalcount"]=="") $b["totalcount"]=0; + if ($a["totaltime"]=="") $a["totaltime"]=0; + if ($b["totaltime"]=="") $b["totaltime"]=0; + + if ($a["totalcount"]>$b["totalcount"]) return 1; + else if ($a["totalcount"]<$b["totalcount"]) return -1; + else { + if ($a["totaltime"]<$b["totaltime"]) return 1; + else if ($a["totaltime"]>$b["totaltime"]) return -1; + else { + if(isset($a["first"]) && $a["first"] != 0) { + if($a["first"]<$b["first"]) return 1; + else if($a["first"]>$b["first"]) return -1; + } + if ($a["user"]<$b["user"]) return 1; + else if ($a["user"]>$b["user"]) return -1; + else return 0; + } + } +} +function ordena($a) { + $r = array(); + for ($i=0; $i<count($a); $i++) { + $max=null; + reset($a); + while ( list ($e, $c) = each($a) ) { + if ($a[$e]!=null && ($max==null || ScoreCMP($a[$e],$max) > 0)) { + $j=0; + for(;$j<$i;$j++) + if($r[$j]['user']==$a[$e]['user'] && $r[$j]['site']==$a[$e]['site']) break; + if($j>=$i) { + $max = $a[$e]; + $maxe = $e; + } + } + } + if ($max==null) break; + $r[$i] = $max; + $a[$maxe] = null; + } + return $r; +} +function DBScore($contest, $verifylastmile, $hor=-1, $globalsite='0') { + $c = DBConnect(); + $r = DBExec($c, "select sitenumber as number from sitetable where contestnumber=$contest and siteactive='t'", + "DBScore(get site)"); + $n = DBnlines($r); + if ($n == 0) { + LOGError("Unable to get site information. No active sites available (contest=$contest)"); + MSGError("Unable to get site information. No active sites available. Contact an admin now!"); + exit; + } + $a = array(); + $resp = array(); + $whichsites=explode(',',$globalsite); + for ($i=0;$i<$n;$i++) { + $a = DBRow($r,$i); + if(in_array($a["number"], $whichsites) || in_array(0,$whichsites)) { + list($resp1,$data0) = DBScoreSite($contest, $a["number"], $verifylastmile, $hor); + $resp = array_merge($resp, $resp1); + } + } + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + $probs=DBGetProblems($contest); $nprobs=count($probs); + foreach (glob($_SESSION['locr'] . $ds . "private" .$ds . "remotescores" . $ds . "score*.dat") as $fname) { + $fc=file_get_contents($fname); + if(($arr = unserialize(base64_decode($fc)))===false) { + LOGError("File " . sanitizeText($fname) . " is not compatible"); + } else { + if(is_array($arr)) { + if(isset($arr['site'])) { + $site=$arr['site']; + if(!in_array($site, $whichsites) && !in_array(0,$whichsites)) continue; + $fine=1; + reset($resp); + while(list($e, $c) = each($resp)) { + if($resp[$e]['site']==$site) { $fine=0; break; } + } + if($fine) { + list($arr,$data0) = DBScoreSite($contest, $site, $verifylastmile, $hor, $arr); + reset($arr); + while(list($ee,$cc) = each($arr)) { + if($site != $arr[$ee]['site']) { + $arr[$ee]=null; + unset($arr[$ee]); + } else { + // just to make the color of the other site changed to the color of the problem in this site + while(list($e2,$c2) = each($arr[$ee]["problem"])) { + for($prob=0; $prob<$nprobs; $prob++) { + if($probs[$prob]['number']==$e2) { + $arr[$ee]['problem'][$e2]['color'] = $probs[$prob]['color']; + $arr[$ee]['problem'][$e2]['colorname'] = $probs[$prob]['colorname']; + break; + } + } + } + } + } + $resp = array_merge($resp, $arr); + } + } else { +// old version -- just for compatibility --- + while(list($ee,$cc) = each($arr)) { + $fine=1; + reset($resp); + while(list($e, $c) = each($resp)) { + if($resp[$e]['site']==$arr[$ee]['site']) { $fine=0; break; } + } + if($fine==0) $arr[$ee]=null; + else { + // just to make the color of the other site changed to the color of the problem in this site + while(list($e2,$c2) = each($arr[$ee]["problem"])) { + for($prob=0; $prob<$nprobs; $prob++) { + if($probs[$prob]['number']==$e2) { + $arr[$ee]['problem'][$e2]['color'] = $probs[$prob]['color']; + $arr[$ee]['problem'][$e2]['colorname'] = $probs[$prob]['colorname']; + break; + } + } + } + } + } + $resp = array_merge($resp, $arr); +// ---- end of old version --- + } + } +// MSGError("got scores from $fname"); + } + } + if (($result = ordena ($resp)) === false) { + LOGError("Error while sorting scores (contest=$contest)."); + MSGError("Error while sorting scores. Contact an admin now!"); + } + return $result; +} + +function DBBalloon($contest, $site, $user, $problem, $localsite=true) { + if (($b = DBSiteInfo($contest, $site)) == null) + exit; + if ($localsite) { + if (($blocal = DBSiteInfo($contest, $_SESSION["usertable"]["usersitenumber"])) == null) + exit; + } else $blocal = $b; + if (($ct = DBContestInfo($contest)) == null) + exit; + + $t = time(); + $ta = $blocal["currenttime"]; + if ($verifylastmile) + $tf = $b["sitelastmilescore"]; + else { + $tf = $b["siteduration"]; + } + + $c = DBConnect(); + $r = DBExec($c, "select r.rundatediff as time, a.yes as yes from " . + "runtable as r, answertable as a where r.runanswer=a.answernumber and " . + "a.contestnumber=$contest and r.usernumber=$user and r.runproblem=$problem and " . + "r.contestnumber=$contest and r.runsitenumber=$site and (r.runstatus ~ 'judged' or r.runstatus ~ 'judged+') and " . + "r.rundatediff>=0 and r.rundatediff<=$tf and r.rundatediffans<=$ta " . + "order by r.rundatediff", "DBBalloon(get runs)"); + $n = DBnlines($r); + for ($i=0;$i<$n;$i++) { + $a = DBRow($r,$i); + if($a["yes"]=='t') return true; + } + return false; +} +function DBRecentNews($contest, $site, $verifylastmile, $minutes=3) { + if (($b = DBSiteInfo($contest, $site)) == null) + exit; + if (($blocal = DBSiteInfo($contest, $_SESSION["usertable"]["usersitenumber"])) == null) + exit; + if (($ct = DBContestInfo($contest)) == null) + exit; + + $t = time(); + $ta = $blocal["currenttime"]; + $taa = $ta - $minutes*60; + if ($verifylastmile) + $tf = $b["sitelastmilescore"]; + else { + $tf = $b["siteduration"]; + } + + $c = DBConnect(); + $r = DBExec($c, "select a.yes as yes, p.problemcolor as color, p.problemcolorname as colorname, u.userfullname as userfullname, " . + "u.usernumber as usernumber, p.problemnumber as problemnumber, p.problemname, (r.rundatediffans>$ta) as fut, min(r.rundatediff) as time from " . + "runtable as r, answertable as a, problemtable as p, usertable as u where r.runanswer=a.answernumber and " . + "p.contestnumber=$contest and a.contestnumber=$contest and r.usernumber = u.usernumber and u.usertype='team' and " . + "p.problemnumber=r.runproblem and r.contestnumber=$contest and r.runsitenumber=$site and u.userenabled='t' and " . + "r.rundatediff>=$taa and r.rundatediff<=$tf and r.rundatediff<=$ta and u.contestnumber=$contest and u.usersitenumber=$site and " . + "((a.yes='t' and r.rundatediffans<=$ta) or (r.rundatediffans>$ta)) " . + "group by a.yes,p.problemcolor,p.problemcolorname,p.problemname,u.userfullname,u.usernumber,p.problemnumber,fut order by time", "DBRecentNews(get runs)"); + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + if($a[$i]["fut"]=='t' && $a[$i]["yes"]=='t') $a[$i]["yes"]='f'; + } + return $a; +} +function DBScoreSite($contest, $site, $verifylastmile, $hor=-1, $data=null) { + if (($blocal = DBSiteInfo($contest, $_SESSION["usertable"]["usersitenumber"])) == null) + exit; + if (($b = DBSiteInfo($contest, $site, null, false)) == null) + $b=$blocal; + if (($ct = DBContestInfo($contest)) == null) + exit; + + $t = time(); + $ta = $blocal["currenttime"]; + if($hor >= 0) $ta = $hor; + if ($verifylastmile) + $tf = $b["sitelastmilescore"]; + else { + $tf = $b["siteduration"]; + } + if($data != null && is_numeric($data)) { + if($data < $ta) $ta = $data; + $data=null; + } + + $data0=array(); + if($data==null) { + $c = DBConnect(); + $resp = array(); + $r = DBExec($c, "select * from usertable where contestnumber=$contest and usersitenumber=$site and ". + "usertype='team' and userlastlogin is not null and userenabled='t'", "DBScoreSite(get users)"); + $n = DBnlines($r); + for ($i=0;$i<$n;$i++) { + $a = DBRow($r,$i); + $resp[$a["usernumber"]]["user"]=$a["usernumber"]; + $resp[$a["usernumber"]]["site"]=$a["usersitenumber"]; + $resp[$a["usernumber"]]["username"]=$a["username"]; + $resp[$a["usernumber"]]["usertype"]=$a["usertype"]; + $resp[$a["usernumber"]]["userfullname"]=$a["userfullname"]; + $resp[$a["usernumber"]]["totaltime"]=0; + $resp[$a["usernumber"]]["totalcount"]=0; + $resp[$a["usernumber"]]["problem"]=array(); + } + $r = DBExec($c, "select r.usernumber as user, p.problemname as problemname, r.runproblem as problem, ". + "p.problemcolor as color, p.problemcolorname as colorname, " . + "r.rundatediff as time, r.rundatediffans as anstime, a.yes as yes, r.runanswer as answer from " . + "runtable as r, answertable as a, problemtable as p where r.runanswer=a.answernumber and " . + "a.contestnumber=$contest and p.problemnumber=r.runproblem and p.contestnumber=$contest and " . + "r.contestnumber=$contest and r.runsitenumber=$site and (r.runstatus ~ 'judged' or r.runstatus ~ 'judged+') and " . + "r.rundatediff>=0 and r.rundatediff<=$tf and r.rundatediffans<=$ta " . + "order by r.usernumber, r.runproblem, r.rundatediff", "DBScoreSite(get runs)"); + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + $data0['n']=$n; + $data0['resp']=$resp; + $data0['a']=$a; + $data0['site']=$site; + } else { + $resp=$data['resp']; + $n=$data['n']; + $a=$data['a']; + } + + $i=0; + while ($i<$n) { + if($a[$i]["anstime"] > $ta) { $i++; continue; } + $user = $a[$i]["user"]; + $problem = $a[$i]["problem"]; + $time = 0; + $k = 0; + if(!isset($resp[$user])) { $i++; continue; } + $resp[$user]["user"] = $user; + $resp[$user]["site"] = $site; + $resp[$user]["problem"][$problem]["name"] = $a[$i]["problemname"]; + $resp[$user]["problem"][$problem]["color"] = $a[$i]["color"]; + $resp[$user]["problem"][$problem]["colorname"] = $a[$i]["colorname"]; + $resp[$user]["problem"][$problem]["solved"] = false; + $resp[$user]["problem"][$problem]["judging"] = false; + $resp[$user]["problem"][$problem]["time"] = 0; + $resp[$user]["problem"][$problem]["penalty"] = 0; + $resp[$user]["problem"][$problem]["count"] = 0; + + while ($i<$n && $a[$i]["user"]==$user && $a[$i]["problem"]==$problem && $a[$i]["yes"]!='t') { + $time += (int) (($ct["contestpenalty"])/60); + $k++; + $i++; + } + $resp[$user]["problem"][$problem]["count"] = $k; + if ($i>=$n) break; + if($a[$i]["user"]==$user && $a[$i]["problem"]==$problem && $a[$i]["yes"]=='t') { + $timet = (int) (($a[$i]["time"])/60); + if(!isset($resp[$user]["first"]) || $timet < $resp[$user]["first"]) + $resp[$user]["first"] = $timet; + $time += $timet; + $resp[$user]["problem"][$problem]["time"] = $timet; + $resp[$user]["problem"][$problem]["penalty"] = $time; + $resp[$user]["problem"][$problem]["solved"] = true; + $resp[$user]["problem"][$problem]["count"]++; + $resp[$user]["totaltime"] += $time; + $resp[$user]["totalcount"]++; + } + while ($i<$n && $a[$i]["user"]==$user && $a[$i]["problem"]==$problem) { + $i++; + } + } + + if($data==null) { + $aa = DBRecentNews($contest, $site, $verifylastmile, $ta); + $data0['aa']=$aa; + } else $aa=$data['aa']; + + for($i=0; $i<count($aa); $i++) { + if($aa[$i]["fut"]=='t') { + $resp[$aa[$i]["usernumber"]]["problem"][$aa[$i]["problemnumber"]]["judging"] = true; + } + } + + if (($result = ordena ($resp)) === false) { + LOGError("Error while sorting scores (contest=$contest, site=$site)."); + MSGError("Error while sorting scores. Contact an admin now!"); + } + return array($result,$data0); +} +// eof +?> diff --git a/boca-1.5.0/src/ftask.php b/boca-1.5.0/src/ftask.php new file mode 100644 index 0000000..6575210 --- /dev/null +++ b/boca-1.5.0/src/ftask.php @@ -0,0 +1,512 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +function DBDropTaskTable() { + $c = DBConnect(); + $r = DBExec($c, "drop table \"tasktable\"", "DBDropTaskTable(drop table)"); +} +function DBCreateTaskTable() { + $c = DBConnect(); + $conf = globalconf(); + if($conf["dbuser"]=="") $conf["dbuser"]="bocauser"; + $r = DBExec($c, " +CREATE TABLE \"tasktable\" ( +\"contestnumber\" int4 NOT NULL, -- (id do concurso) +\"sitenumber\" int4 NOT NULL, -- (id do site) +\"usernumber\" int4 NOT NULL, -- (id do usuario requisitando a tarefa) +\"tasknumber\" int4 NOT NULL, -- (id do problema) +\"taskstaffnumber\" int4, -- (id do usuario executando a tarefa) +\"taskstaffsite\" int4, -- (id do usuario executando a tarefa) +\"taskdate\" int4 NOT NULL, -- (dia/hora da submissao no local de origem) +\"taskdatediff\" int4 NOT NULL, -- (diferenca entre inicio da competicao e dia/hora da submissao em seg) +\"taskdatediffans\" int4 NOT NULL, -- (diferenca entre inicio da competicao e dia/hora da correcao em seg) +\"taskdesc\" varchar(200), -- (descricao da tarefa) +\"taskfilename\" varchar(100), -- (nome do arquivo) +\"taskdata\" oid, -- (apontador para o arquivo) +\"tasksystem\" bool NOT NULL, -- (tarefa de sistema?) +\"taskstatus\" varchar(20) NOT NULL, -- (status da tarefa: opentask, processing, done) +\"colorname\" varchar(100) DEFAULT '', -- nome da cor do problema +\"color\" varchar(6) DEFAULT '', -- cor do problema, formato html (RGB hexadecimal) +\"updatetime\" int4 DEFAULT EXTRACT(EPOCH FROM now()) NOT NULL, -- (indica a ultima atualizacao no registro) +-- (tabela com tarefas para os staffs. Dentre elas podemos citar baloes e impressoes) +CONSTRAINT \"task_pkey\" PRIMARY KEY (\"contestnumber\", \"sitenumber\", \"tasknumber\"), +CONSTRAINT \"user_fk\" FOREIGN KEY (\"contestnumber\", \"sitenumber\", \"usernumber\") + REFERENCES \"usertable\" (\"contestnumber\", \"usersitenumber\", \"usernumber\") + ON DELETE CASCADE ON UPDATE CASCADE NOT DEFERRABLE INITIALLY IMMEDIATE +)", "DBCreateTaskTable(create table)"); + $r = DBExec($c, "REVOKE ALL ON \"tasktable\" FROM PUBLIC", "DBCreateTaskTable(revoke public)"); + $r = DBExec($c, "GRANT ALL ON \"tasktable\" TO \"".$conf["dbuser"]."\"", "DBCreateTaskTable(grant bocauser)"); + $r = DBExec($c, "CREATE UNIQUE INDEX \"task_index\" ON \"tasktable\" USING btree ". + "(\"contestnumber\" int4_ops, \"sitenumber\" int4_ops, \"tasknumber\" int4_ops)", + "DBCreateTaskTable(create index)"); +} + +function DBChiefUpdateTask($contest, $usersite, $usernumber, $tasksite, $tasknumber, $st) { + return DBUpdateTaskC($contest, $usersite, $usernumber, $tasksite, $tasknumber, $st, 1); +} +function DBUpdateTask($contest, $usersite, $usernumber, $tasksite, $tasknumber, $st) { + return DBUpdateTaskC($contest, $usersite, $usernumber, $tasksite, $tasknumber, $st, 0); +} +function DBUpdateTaskC($contest, $usersite, $usernumber, $tasksite, $tasknumber, $status, $chief) { + $b = DBSiteInfo($contest, $tasksite); + if ($b == null) { + exit; + } + + $c = DBConnect(); + DBExec($c, "begin work", "DBUpdateTaskC(transaction)"); + $sql = "select * from tasktable as t where t.contestnumber=$contest and " . + "t.sitenumber=$tasksite and t.tasknumber=$tasknumber"; + if ($chief != 1) { + $sql .= " and t.taskstatus='processing' and t.taskstaffnumber=$usernumber and t.taskstaffsite=$usersite"; + $tx = "Judge"; + } else $tx = "Chief"; + $r = DBExec ($c, $sql . " for update", "DBUpdateTaskC(get task for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBUpdateTaskC(rollback)"); + LogLevel("Unable to alter the task record (maybe it was already done by a chief) " . + "(task=$tasknumber, site=$tasksite, contest=$contest).",1); + MSGError("Unable to alter the task record (maybe it was already done by a chief)"); + return false; + } + $temp = DBRow($r,0); + $b = DBSiteInfo($contest, $tasksite, $c); + $t = $b["currenttime"]; + + DBExec($c, "update tasktable set taskstatus='$status', taskstaffnumber=$usernumber, taskstaffsite=$usersite, " . + "taskdatediffans=$t, updatetime=".time()." " . + "where contestnumber=$contest and tasknumber=$tasknumber and sitenumber=$tasksite", + "DBUpdateTaskC(update task)"); + + DBExec($c, "commit work", "DBUpdateTaskC(commit)"); + LOGLevel("Task updated (task=$tasknumber, site=$tasksite, contest=$contest, user=$usernumber(site=$usersite), ". + "status=$status).", 3); + return true; +} +//devolve uma task que estava sendo processada. Recebe o numero da task, +//o numero do site da task e o numero do contest. +//tenta alterar o status para 'opentask'. Se nao conseguir retorna false +function DBChiefTaskGiveUp($number,$site,$contest) { + return DBTaskGiveUp($number,$site,$contest,-1,-1); +} +function DBTaskGiveUp($number,$site,$contest,$usernumber,$usersite) { + $c = DBConnect(); + DBExec($c, "begin work", "DBTaskGiveUp(transaction)"); + $sql = "select * from tasktable as t where t.contestnumber=$contest and " . + "t.sitenumber=$site and t.tasknumber=$number"; + if ($usernumber != -1 || $usersite != -1) { + $sql .= " and t.taskstatus='processing' and t.taskstaffnumber=$usernumber and taskstaffsite=$usersite"; + $tx = "Staff"; + } else $tx = "Chief"; + $r = DBExec ($c, $sql . " for update", "DBTaskGiveUp(get task for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBTaskGiveUp(rollback)"); + LogLevel("Unable to return a task (maybe the timeout or a chief returned it first). ". + "(task=$number, site=$site, contest=$contest)",1); + return false; + } + + DBExec($c, "update tasktable set taskstatus='opentask', taskstaffnumber=NULL, taskstaffsite=NULL, ". + "updatetime=" .time(). " ". + "where contestnumber=$contest and tasknumber=$number and sitenumber=$site", + "DBTaskGiveUp(update task)"); + + DBExec($c, "commit work", "DBTaskGiveUp(commit)"); + LOGLevel("Task returned (task=$number, site=$site, contest=$contest, user=$usernumber).", 3); + return true; +} +function DBTaskDelete($number,$site,$contest,$user,$usersite) { + $c = DBConnect(); + DBExec($c, "begin work", "DBTaskDelete(transaction)"); + $sql = "select * from tasktable as t where t.contestnumber=$contest and " . + "t.sitenumber=$site and t.tasknumber=$number"; + $r = DBExec ($c, $sql . " for update", "DBTaskDelete(get task for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBTaskDelete(rollback)"); + LogLevel("Unable to delete a task. ". + "(task=$number, site=$site, contest=$contest)",1); + return false; + } + + DBExec($c, "update tasktable set taskstatus='deleted', taskstaffnumber=$user, taskstaffsite=$usersite, ". + "updatetime=" . time()." ". + "where contestnumber=$contest and tasknumber=$number and sitenumber=$site", + "DBTaskDelete(update task)"); + + DBExec($c, "commit work", "DBTaskDelete(commit)"); + LOGLevel("Task deleted (task=$number, site=$site, contest=$contest, user=$user($usersite)).", 3); + return true; +} + +//pega uma task para processar. Recebe o numero da task, o numero do site e o numero do contest. +//tenta alterar o status para 'processing' e se conseguir, devolve um array com dados da task. +//Se nao conseguir, retorna false +function DBChiefGetTaskToAnswer($number,$site,$contest) { + return DBGetTaskToAnswerC($number,$site,$contest,1); +} +function DBGetTaskToAnswer($number,$site,$contest) { + return DBGetTaskToAnswerC($number,$site,$contest,0); +} +function DBGetTaskToAnswerC($number,$site,$contest,$chief) { + $c = DBConnect(); + DBExec($c, "begin work", "DBGetTaskToAnswerC(transaction)"); + $sql = "select t.contestnumber as contestnumber, t.sitenumber as sitenumber, ". + "t.tasknumber as number ". + "from tasktable as t ". + "where t.contestnumber=$contest and t.sitenumber=$site and " . + "t.tasknumber=$number"; + if ($chief != 1) { + $sql .= " and t.taskstatus='opentask'"; + $tx = "Staff"; + } else $tx = "Chief"; + $r = DBExec ($c, $sql . " for update", "DBGetTaskToAnswerC(get task for update)"); + $n = DBnlines($r); + if ($n != 1) { + DBExec($c, "rollback work", "DBGetTaskToAnswerC(rollback)"); + LogLevel("Unable to get a task (maybe other staff got it first). ". + "(task=$number, site=$site, contest=$contest)",2); + return false; + } + $a = DBRow($r,0); + if ($chief != 1) { + DBExec($c, "update tasktable set taskstaffnumber=" . + $_SESSION["usertable"]["usernumber"] . ", ". + "taskstaffsite=".$_SESSION["usertable"]["usersitenumber"]. + ", taskstatus='processing', updatetime=".time()." " . + "where contestnumber=$contest and tasknumber=$number and ". + "sitenumber=$site", + "DBGetTaskToAnswerC(update task)"); + } + + DBExec($c, "commit work", "DBGetTaskToAnswerC(commit)"); + LOGLevel("User got a task (task=$number, site=$site, contest=$contest, user=". + $_SESSION["usertable"]["usernumber"]."(".$_SESSION["usertable"]["usersitenumber"].")).", 3); + return $a; +} +function DBAllTasks($contest) { + return DBOpenTasksSNS($contest,"x",-1); +} +function DBAllTasksInSites($contest,$site,$order) { + return DBOpenTasksSNS($contest,$site,-1,$order); +} +function DBOpenTasks($contest) { + return DBOpenTasksSNS($contest,"x",1); +} +function DBOpenTasksInSites($contest,$site) { + return DBOpenTasksSNS($contest,$site,1); +} +function DBOpenTasksSNS($contest,$site,$st,$order='task') { + $c = DBConnect(); + $sql = "select distinct t.tasknumber as number, t.taskdatediff as timestamp, t.usernumber as user, ". + "u.username as username, t.color as color, t.colorname as colorname, " . + "t.taskstatus as status, t.sitenumber as site, t.taskstaffnumber as staff, " . + "t.taskstaffsite as staffsite, t.taskdesc as description, tasksystem as system, " . + "t.taskfilename as filename, t.taskdata as oid, uu.username as staffname " . + "from tasktable as t left join usertable as uu on ". + "uu.usernumber=t.taskstaffnumber and uu.usersitenumber=t.taskstaffsite and ". + "uu.contestnumber=t.contestnumber, ". + "usertable as u " . + "where t.contestnumber=$contest and u.contestnumber=t.contestnumber and ". + "u.usernumber=t.usernumber and u.usersitenumber=t.sitenumber"; + if ($site != "x") { + $str = explode(",", $site); + $sql .= " and (t.sitenumber=-1"; + for ($i=0;$i<count($str);$i++) { + if (is_numeric($str[$i])) { + $sql .= " or (t.sitenumber=".$str[$i]; + $b = DBSiteInfo($contest, $str[$i]); + if ($b == null) { + exit; + } + $t = $b["currenttime"]; + $sql .= " and (t.taskdatediffans<=$t or (t.taskstatus != 'done' and t.taskdatediff<=$t))) "; + } + } + $sql .= ")"; + } + + if ($st == 1) + $sql .= " and (t.taskstatus ~ 'opentask' or t.taskstatus ~ 'processing') order by "; + else $sql .= " order by "; + + if($order == "description") + $sql .= "t.taskdesc,"; + else if ($order == "status") + $sql .= "t.taskstatus,"; + else if ($order == "user") + $sql .= "u.username,t.sitenumber,"; + else if ($order == "staff") + $sql .= "t.taskstaffnumber,t.taskstaffsite,"; + + if ($st == 1) + $sql .= "t.tasknumber"; + else + $sql .= "t.taskdatediff desc"; + + $r = DBExec($c, $sql, "DBOpenTasksSNS(get task)"); + + $n = DBnlines($r); + $a = array(); + for ($i=0;$i<$n;$i++) + $a[$i] = DBRow($r,$i); + return $a; +} +function DBNewTask_old ($contest, $site, $user, $desc, $filename, $filepath, $sys, $color='', $colorname='', $c=null) { + $param = array('contest'=>$contest, + 'site'=>$site, + 'user'=>$user, + 'desc'=>$desc, + 'filename'=>$filename, + 'filepath'=>$filepath, + 'color'=>$color, + 'colorname'=>$colorname, + 'sys'=>$sys); + return DBNewTask($param,$c); +} + +function DBNewTask($param, $c=null) { + if(isset($param['contestnumber']) && !isset($param['contest'])) $param['contest']=$param['contestnumber']; + if(isset($param['sitenumber']) && !isset($param['site'])) $param['site']=$param['sitenumber']; + if(isset($param['usernumber']) && !isset($param['user'])) $param['user']=$param['usernumber']; + if(isset($param['number']) && !isset($param['tasknumber'])) $param['tasknumber']=$param['number']; + + $ac=array('contest','site','user','desc'); + $ac1=array('color','colorname','updatetime','filename','filepath','sys','tasknumber','status', + 'taskdate','taskdatediff','taskdatediffans','taskstaffnumber','taskstaffsite'); + $type['contest']=1; + $type['updatetime']=1; + $type['site']=1; + $type['user']=1; + $type['tasknumber']=1; + $type['taskdate']=1; + $type['taskdatediff']=1; + $type['taskdatediffans']=1; + $type['taskstaffnumber']=1; + $type['taskstaffsite']=1; + foreach($ac as $key) { + if(!isset($param[$key]) || $param[$key]=="") { + MSGError("DBNewTask param error: $key not found"); + return false; + } + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewTask param error: $key is not numeric"); + return false; + } + $$key = sanitizeText($param[$key]); + } + $taskstaffnumber=-1; + $taskstaffsite=-1; + $t = time(); + $taskdate=$t; + $sys='f'; + $filename=''; + $filepath=''; + $color=''; + $colorname=''; + $tasknumber=-1; + $taskdatediffans=999999999; + $updatetime=-1; + $status='opentask'; + $taskdatediff=-1; + foreach($ac1 as $key) { + if(isset($param[$key])) { + $$key = sanitizeText($param[$key]); + if(isset($type[$key]) && !is_numeric($param[$key])) { + MSGError("DBNewTask param error: $key is not numeric"); + return false; + } + } + } + if($updatetime <= 0) + $updatetime=$t; + if($sys != 't') $sys='f'; + + $cw = false; + if($c == null) { + $cw = true; + $c = DBConnect(); + DBExec($c, "begin work", "DBNewTask(transaction)"); + } + $insert=true; + if($tasknumber < 0) { + $sql = "select sitenexttask as nexttask, sitemaxtask as maxtask from " . + "sitetable where sitenumber=$site and contestnumber=$contest for update"; + $r = DBExec($c, $sql, "DBNewTask(get site for update)"); + if (DBnlines($r) != 1) { + DBExec($c, "rollback work", "DBNewTask(rollback-site)"); + LOGError("Unable to find a unique site/contest in the database. SQL=(" . $sql . ")"); + MSGError("Unable to find a unique site/contest in the database."); + exit; + } + $a = DBRow($r,0); + $b = DBSiteInfo($contest, $site, $c); + $dif = $b["currenttime"]; + if($taskdatediff < 0) + $taskdatediff = $dif; + if($sys!='t' && DBCountOpenTasks($contest, $site, $user) > $a["maxtask"]) { + DBExec($c, "rollback work", "DBNewTask(rollback-maxtask)"); + LOGError("Too many open tasks for user=$user, site=$site, contest=$contest"); + MSGError("Too many open tasks! Task not included."); + exit; + } + if ($sys != 't' && $dif < 0) { + DBExec($c, "rollback work", "DBNewTask(rollback-started)"); + LOGError("Tried to submit a task but the contest is not started. SQL=(" . $sql . ")"); + MSGError("The contest is not started yet!"); + exit; + } + if ($sys != 't' && !$b["siterunning"]) { + DBExec($c, "rollback work", "DBNewTask(rollback-over)"); + LOGError("Tried to submit a task but the contest is over. SQL=(" . $sql . ")"); + MSGError("The contest is over!"); + exit; + } + $tasknumber = $a["nexttask"] + 1; + } else { + $sql = "select * from tasktable as t where t.contestnumber=$contest and " . + "t.sitenumber=$site and t.tasknumber=$tasknumber"; + $r = DBExec ($c, $sql . " for update", "DBNewTask(get task for update)"); + $n = DBnlines($r); + if ($n > 0) { + $insert=false; + $lr = DBRow($r,0); + $t = $lr['updatetime']; + } + } + DBExec($c, "update sitetable set sitenexttask=$tasknumber, updatetime=".$t. + " where sitenumber=$site and contestnumber=$contest and sitenexttask<$tasknumber", "DBNewTask(update site)"); + $ret=1; + if($insert) { + if($filename!="" && $filepath!="") { + if(substr($filepath,0,7)!="base64:") { + if (($oid = DB_lo_import($c, $filepath)) === false) { + DBExec($c, "rollback work", "DBNewTask(rollback-import)"); + LOGError("DBNewTask: Unable to create a large object for file $filepath."); + MSGError("problem importing file to database. Contact an admin now!"); + exit; + } + } else { + $filepath = base64_decode(substr($filepath,7)); + if (($oid = DB_lo_import_text($c, $filepath)) == null) { + DBExec($c, "rollback work", "DBNewTask(rollback-import)"); + LOGError("DBNewTask: Unable to create a large object for file."); + MSGError("problem importing file to database. Contact an admin now!"); + exit; + } + } + } else $oid="NULL"; + DBExec($c, "INSERT INTO tasktable (contestnumber, sitenumber, tasknumber, usernumber, taskdate, " . + "taskdatediff, taskdatediffans, taskfilename, taskdata, taskstatus, taskdesc, tasksystem, ". + "color, colorname, updatetime) " . + "VALUES ($contest, $site, $tasknumber, $user, $taskdate, $taskdatediff, $taskdatediffans, '$filename', $oid, '$status', " . + "'$desc', '$sys', '$color', '$colorname', $updatetime)", + "DBNewTask(insert task)"); + if($cw) DBExec($c, "commit work", "DBNewTask(commit-insert)"); + if($sys=="t") $u="System"; + else $u = "User $user"; + LOGLevel("$u submitted a task (#$tasknumber) on site #$site " . + "(filename=$filename, contest=$contest).",2); + $ret=2; + } else { + if($updatetime > $t) { + $ret=2; + $sql = "update tasktable set usernumber=$user, taskdesc='$desc', " . + "color='$color',colorname='$colorname',taskstatus='$status',"; + if($taskstaffnumber>0) + $sql .= "taskstaffnumber=$taskstaffnumber, "; + if($taskstaffsite>0) + $sql .= "taskstaffsite=$taskstaffsite, "; + $sql .= "taskdatediffans=$taskdatediffans, updatetime=$updatetime where " . + "contestnumber=$contest and sitenumber=$site and tasknumber=$tasknumber"; + DBExec($c,$sql,"DBNewTask(update task)"); + } + if($cw) DBExec($c, "commit work", "DBNewTask(commit-update)"); + } + return $ret; +} +//recebe o numero do contest, o numero do site e o numero do usuario +//devolve um array, onde cada linha tem os atributos +// number (numero da task) +// timestamp (hora da criacao da task) +// filename (nome do arquivo relacionado) +// status (situacao da task) +// desc (descricao da task) +function DBUserTasks($contest,$site,$user) { + $b = DBSiteInfo($contest, $site); + if ($b == null) { + exit; + } + $t = $b["currenttime"]; + + $c = DBConnect(); + $r = DBExec($c, "select distinct t.sitenumber as site, t.tasknumber as number, ". + "t.taskdatediff as timestamp, t.taskstatus as status, t.taskfilename as filename, " . + "t.taskdesc as description, t.updatetime " . + "from tasktable as t " . + "where t.contestnumber=$contest and t.sitenumber=$site and ". + "(t.taskdatediffans<=$t or (t.taskstatus != 'done' and t.taskdatediff<=$t)) and " . + "t.usernumber=$user and t.taskstatus != 'deleted' and t.tasksystem='f' " . + "order by t.updatetime", + "DBUserTasks(get tasks)"); + $n = DBnlines($r); + + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + return $a; +} +function DBCountOpenTasks($contest,$site,$user) { + $c = DBConnect(); + $r = DBExec($c, "select t.contestnumber, t.sitenumber, t.tasknumber ". + "from tasktable as t " . + "where t.contestnumber=$contest and t.sitenumber=$site and ". + "t.usernumber=$user and t.taskstatus='opentask' and t.tasksystem='f'", + "DBCountOpenTasks(get tasks)"); + $n = DBnlines($r); + return $n; +} +//recebe o numero do contest, o numero do site do juiz e o numero do juiz +//devolve um array, onde cada linha tem os atributos +// number (numero da task) +// timestamp (hora da criacao da task) +// problem (nome do problema) +// status (situacao da task) +// answer (texto com a resposta) +function DBJudgedTasks($contest,$site,$user) { + $c = DBConnect(); + $r = DBExec($c, "select distinct t.sitenumber as site, t.tasknumber as number, ". + "t.taskdatediff as timestamp, t.taskstatus as status, t.taskfilename as filename, " . + "t.taskdesc as description, t.updatetime " . + "from tasktable as t " . + "where t.contestnumber=$contest and t.taskstaffsite=$site and ". + "t.taskstaffnumber=$user order by t.updatetime", + "DBJudgedTasks(get tasks)"); + $n = DBnlines($r); + + $a = array(); + for ($i=0;$i<$n;$i++) { + $a[$i] = DBRow($r,$i); + } + return $a; +} +// eof +?> diff --git a/boca-1.5.0/src/fzip.php b/boca-1.5.0/src/fzip.php new file mode 100644 index 0000000..2a66722 --- /dev/null +++ b/boca-1.5.0/src/fzip.php @@ -0,0 +1,78 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +//Last updated 21/jul/2012 by cassio@ime.usp.br +require_once('hex.php'); + +function create_zip($folder,$files,$destination,$msg=false,$zip=null) { + if(!function_exists('zip_open')) { + MSGError("Zip file error -- zip not installed (" . getFunctionName() .")"); + LogError("Zip file error -- zip not installed (" . getFunctionName() .")"); + } + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + $dest=null; + if($zip == null) { + $zip = new ZipArchive(); + if($zip->open($destination,ZIPARCHIVE::CREATE | ZIPARCHIVE::OVERWRITE) !== true) { + return -1; + } + $dest=$destination; + $destination='.'; + } + foreach($files as $file) { + if($msg) + echo "Packing file " . $file . "\n"; + if(($pos = strrpos($file,$ds))!==false) + $file = substr($file,$pos+1); + if (is_dir($folder . $ds . $file) === true) { + $zip->addEmptyDir($file); + create_zip($folder . $ds . $file, + glob($folder . $ds . $file . $ds . '*'),$file,$msg,$zip); + } + else if (is_file($folder . $ds . $file) === true) { + $zip->addFile($folder . $ds . $file, $destination . $ds . $file); + } + } + if($dest != null) { + $zip->close(); + if(file_exists($dest)) return 1; else return 0; + } else return 1; +} + +function unzipstr($str,$txt='') { + $str = gzuncompress($str); + $pos = strrpos($str,"#"); + $test2 = substr($str,$pos+1); + $str = substr($str,0,$pos); + $test1 = myshorthash($str); + if($test1 != $test2) { + if($txt=='') + MSGError("Decompression error (" . getFunctionName() .")"); + LogError("Decompression error (" . getFunctionName() .",$txt)"); + return ""; + } + return $str; +} +function zipstr($str) { + if(!function_exists('gzcompress')) { + MSGError("Compression error -- zlib not installed (" . getFunctionName() .")"); + LogError("Compression error -- zlib not installed (" . getFunctionName() .")"); + } + return gzcompress($str . '#' . myshorthash($str)); +} +?> diff --git a/boca-1.5.0/src/globals.php b/boca-1.5.0/src/globals.php new file mode 100644 index 0000000..fc83e11 --- /dev/null +++ b/boca-1.5.0/src/globals.php @@ -0,0 +1,327 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +require_once('db.php'); +define("dbcompat_1_4_1",true); + +// sanitization +function sanitizeVariables(&$item, $key) +{ + if (!is_array($item)) + { + // undoing 'magic_quotes_gpc = On' directive + if (get_magic_quotes_gpc()) + $item = stripcslashes($item); + + $item = sanitizeText($item); + } +} + +function filedownload($oid,$fname,$msg='') { + $cf = globalconf(); + $if = rawurlencode(encryptData($fname, session_id() . $cf['key'],false)); + $p = myhash($oid . $fname . $msg . session_id() . $cf["key"]); + $str = "oid=". $oid . "&filename=". $if . "&check=" . $p; + if($msg != '') $str .= "&msg=" . rawurlencode($msg); + return $str; +} + +function cleardir($dir,$cddir=true,$secure=false) { + if(is_dir($dir)) { + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + if($cddir) { + @chdir($dir); + @chdir('..'); + } + $d = @opendir($dir); + while (($file = @readdir($d)) !== false) { + if(!is_dir($dir . $ds . $file)) { + if($secure) + file_put_contents($dir . $ds . $file,str_repeat('XXXXXXXXXX',10000)); + @unlink($dir . $ds . $file); + } + else { + if($file != '.' && $file != '..') { + $cdir1 = $dir . $ds . $file; + $d1 = @opendir($cdir1); + while (($file1 = @readdir($d1)) !== false) + if(!is_dir($cdir1 . $ds . $file1)) { + if($secure) + file_put_contents($cdir1 . $ds . $file1,str_repeat('XXXXXXXXXX',10000)); + @unlink($cdir1 . $ds . $file1); + } + @rmdir($cdir1); + } + } + } + @rmdir($dir); + } else { + if($secure) + file_put_contents($dir,str_repeat('XXXXXXXXXX',10000)); + @unlink($dir); + } +} + +// gen random alphanum string +function randstr($len=8,$from='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') { + $str=''; + $fromlen=strlen($from); + while($len > 0) { + $str .= substr($from,rand(0,$fromlen-1),1); + $len--; + } + return $str; +} + +function myhtmlspecialchars($text) { + return sanitizeText($text,false); +} + +// does the actual 'html' and 'sql' sanitization. +function sanitizeText($text, $doamp=true) +{ + if($doamp) + $text = str_replace("&", "&", $text); + $text = str_replace("<", "<", $text); + $text = str_replace(">", ">", $text); + $text = str_replace("\"", """, $text); + $text = str_replace("'", "'", $text); + $text = str_replace("`", "`", $text); + //$text = escape_string($text); + $text = addslashes($text); + return $text; +} + +array_walk_recursive($_FILES, 'sanitizeVariables'); +array_walk_recursive($_POST, 'sanitizeVariables'); +array_walk_recursive($_GET, 'sanitizeVariables'); +array_walk_recursive($_COOKIE, 'sanitizeVariables'); + +//name of calling function +function getFunctionName($num=2) { + if(strcmp(phpversion(),'5.3.6')<0) { + $backtrace = debug_backtrace(); + } else { + if(strcmp(phpversion(),'5.4.0')<0) + $backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT); + else + $backtrace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT,$num+5); + } + $ret = ''; + for($i=0; $i<$num; $i++) + if(isset($backtrace[$i]) && isset($backtrace[$i]['function'])) + $ret .= " " . $backtrace[$i]['function']; + if($ret =='') $ret='undef'; + return $ret; +} + +function getIP() { + if (getenv("REMOTE_ADDR")) + $ip = getenv("REMOTE_ADDR"); + else + return "UNKNOWN"; + if(defined("dbcompat_1_4_1") && dbcompat_1_4_1==true) return $ip; + + $ip1=''; + if (getenv("HTTP_X_FORWARDED_FOR")) { + $ip1 = getenv("HTTP_X_FORWARDED_FOR"); + $ip1 = strtok ($ip1, ","); + if($ip1 != $ip) $ip .= ';' . $ip1; + } + if (getenv("HTTP_X_CLIENTIP")) { + $ip1a = getenv("HTTP_X_CLIENTIP"); + $ip1a = strtok ($ip1a, ","); + if($ip1a != $ip1 && $ip1a != getenv("REMOTE_ADDR")) $ip .= ';' . $ip1a; + } + if (getenv("HTTP_CLIENT_IP")) { + $ip2 = getenv("HTTP_CLIENT_IP"); + $ip2 = strtok ($ip2, ","); + if($ip2 != $ip1a && $ip1 != $ip2 && $ip2 != getenv("REMOTE_ADDR")) $ip .= ';' . $ip2; + } else { + if (getenv('HTTP_X_FORWARDED')) { + $ip .= ';' . getenv('HTTP_X_FORWARDED'); + } else { + if (getenv('HTTP_FORWARDED')) { + $ip .= ';' . getenv('HTTP_FORWARDED'); + } + } + } + return sanitizeText($ip); +} +//retorna ip e hostname do cliente +function getIPHost() { + $ips = explode(';',getIP()); + $s=''; + for($ipn=0;$ipn<count($ips);$ipn++) { + $ip = $ips[$ipn]; + $host = @gethostbyaddr($ip); + if ($host != $ip && $host != "") + $s .= $ip . "(" . $host . ") "; + else + $s .= $ip . ' '; + } + return $s; +} +//trata o caso de sessao invalida +function InvalidSession($where) { + $msg = "Session expired on $where"; + LOGLevel($msg,3); + unset($_SESSION["usertable"]); + MSGError("Session expired. You must log in again."); +} +//trata o caso de tentativa de burlar as regras +function IntrusionNotify($where) { + $msg = "Security Violation: $where"; + if (isset($_SESSION["usertable"]["username"])) + $msg .= " (" . $_SESSION["usertable"]["username"] . "/" . $_SESSION["usertable"]["usersitenumber"] .")"; + unset($_SESSION["usertable"]); + LOGLevel($msg,1); + MSGError("Violation ($where). Admin warned."); +} +// verifica se a sessao esta aberta e ok +function ValidSession() { + if (!isset($_SESSION["usertable"])) return(FALSE); + $_SESSION["usertable"] = DBUserInfo($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"]); + if ($_SESSION["usertable"]["usersession"] != session_id() && + ($_SESSION["usertable"]["usermultilogin"] != 't' || + $_SESSION["usertable"]["usertype"] != 'score')) + return(FALSE); + return(TRUE); +} +// grava erro no arquivo de log +function LOGError($msg) { + LOGLevel($msg,0); +} +// grava linha no arquivo de log com o nivel especificado +function LOGLevel($msg,$level) { + $msga = sanitizeText(str_replace("\n", " ", $msg)); + $msg = now() . ": "; + define_syslog_variables (); + $prior = LOG_CRIT; + switch ($level) { + case 0: $msg .= "ERROR: "; + $type = "error"; + $prior = LOG_ERR; + break; + case 1: $msg .= "WARN: "; + $type = "warn"; + $prior = LOG_WARNING; + break; + case 2: $msg .= "INFO: "; + $type = "info"; + $prior = LOG_INFO; + break; + case 3: $msg .= "DEBUG: "; + $type = "debug"; + $prior = LOG_DEBUG; + break; + } + $msg .= getIPHost() . ": " . $msga; + + openlog ("BOCA", LOG_ODELAY, LOG_USER); + syslog ($prior, $msg); + closelog(); + if (isset($_SESSION["usertable"])) + DBNewLog($_SESSION["usertable"]["contestnumber"], $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], $type, getIP(), $msga, ""); +} +//retorna data e hora atuais +function now () { + return date('H\:i:s T \- d/M/Y'); +} +//retorna data e hora em seg convertida para padrao +function dateconv ($d) { + return date('H\:i:s T \- d/M/Y', $d); +} +//retorna data e hora em seg convertida para padrao simples +function dateconvsimple ($d) { + return date('H\:i', $d); +} +//transforma segundos para minutos +function dateconvminutes ($d) { + return (int)($d/60); +} +//alerta mensagem via javascript +function MSGError($msg) { + $msg = str_replace("\n", " ", $msg); + echo "<script language=\"JavaScript\">\n"; + echo "alert('". $msg . "');\n"; + echo "</script>\n"; +} +//gera script para voltar aa tela dada +function ForceLoad($where) { + echo "<script language=\"JavaScript\">\n"; + echo "document.location='" . $where . "';\n"; + echo "</script></html>\n"; + exit; +} +function ForceClose() { + echo "<script language=\"JavaScript\">\n"; + echo "window.close;\n"; + echo "</script></html>\n"; + exit; +} + +/** + * Compare an IP address to network(s) + * + * The network(s) argument may be a string or an array. A negative network + * match must start with a "!". Depending on the 3rd parameter, it will + * return true or false on the first match, or any negative rule will have + * absolute priority (default). + * + * Samples: + * match_network ("192.168.1.0/24", "192.168.1.1") -> true + * + * match_network (array ("192.168.1.0/24", "!192.168.1.1"), "192.168.1.1") -> false + * match_network (array ("192.168.1.0/24", "!192.168.1.1"), "192.168.1.1", true) -> true + * match_network (array ("!192.168.1.0/24", "192.168.1.1"), "192.168.1.1") -> false + * match_network (array ("!192.168.1.0/24", "192.168.1.1"), "192.168.1.1", true) -> false + * + * @param mixed Network to match + * @param string IP address + * @param bool true: first match will return / false: priority to negative rules (default) + * @see http://php.benscom.com/manual/en/function.ip2long.php#56373 + */ +function match_network ($nets, $ip) { + if (!is_array ($nets)) $nets = explode(",",$nets); + + foreach ($nets as $net) { + $net = trim($net); + $rev = (preg_match ("/^\!/", $net)) ? true : false; + $net = preg_replace ("/^\!/", "", $net); + + $ip_arr = explode('/', $net); + $net_long = ip2long(trim($ip_arr[0])); + $x = ip2long(trim($ip_arr[1])); + $mask = long2ip($x) == ((int) trim($ip_arr[1])) ? $x : 0xffffffff << (32 - ((int) trim($ip_arr[1]))); + $ip_long = ip2long($ip); + + if ($rev) { + if (($ip_long & $mask) != ($net_long & $mask)) return true; + } else { + if (($ip_long & $mask) == ($net_long & $mask)) return true; + } + } + return false; +} +// eof +?> diff --git a/boca-1.5.0/src/hex.js b/boca-1.5.0/src/hex.js new file mode 100644 index 0000000..9cd3709 --- /dev/null +++ b/boca-1.5.0/src/hex.js @@ -0,0 +1,98 @@ +/*////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +/*hex1 e hex2 sao strings hexa + *devolve a soma das duas + */ +var hexchr="0123456789abcdef"; +function bighexsoma (hex1, hex2){ + if (hex1.length > hex2.length) { + a = hex2; + hex2 = hex1; + hex1 = a; + } + while (hex1.length < hex2.length) + hex1 = '0' + hex1; + + sobra = 0; + resultado = ""; + for(x = hex1.length-1; x>=0; x--) { + if (hex1.charAt(x) > '9') op1 = hex1.charCodeAt(x)-hexchr.charCodeAt(10)+10; + else op1 = hex1.charCodeAt(x)-hexchr.charCodeAt(0); + if (hex2.charAt(x) > '9') op2 = hex2.charCodeAt(x)-hexchr.charCodeAt(10)+10; + else op2 = hex2.charCodeAt(x)-hexchr.charCodeAt(0); + + r = op1 + op2 + sobra; + if (r > 15) { + r -= 16; + sobra = 1; + } else sobra = 0; + + resultado = hexchr.charAt(r) + resultado; + } + if (sobra == 1) + resultado = "1" + resultado; + return resultado; +} +/* + *hex1 e hex2 sao strings hexa + *devolve a string que representa hex2 - hex1 + */ +function bighexsub (hex1, hex2) { + if (hex1.length == hex2.length) { + i=0; + while (hex1.charAt(i) == hex2.charAt(i) && i<hex1.length) i++; + + if (i>=hex1.length) return 0; + if (hex1.charAt(i) > hex2.charAt(i)) { + sinal=""; + a = hex2; + hex2 = hex1; + hex1 = a; + } else sinal = "-"; + } + else { + if (hex1.length < hex2.length) sinal="-"; + else { + sinal=""; + a = hex2; + hex2 = hex1; + hex1 = a; + } + while (hex1.length < hex2.length) + hex1 = "0" + hex1; + } + + sobra = 0; + resultado = ""; + for(x=hex1.length-1; x>=0; x--) { + if (hex1.charAt(x) > '9') op1 = hex1.charCodeAt(x)-hexchr.charCodeAt(10)+10; + else op1 = hex1.charCodeAt(x)-hexchr.charCodeAt(0); + if (hex2.charAt(x) > '9') op2 = hex2.charCodeAt(x)-hexchr.charCodeAt(10)+10; + else op2 = hex2.charCodeAt(x)-hexchr.charCodeAt(0); + + r = op2 - op1 - sobra; + if (r < 0) { + r += 16; + sobra = 1; + } else sobra = 0; + + resultado = hexchr.charAt(r) + resultado; + } + return sinal + resultado; +} diff --git a/boca-1.5.0/src/hex.php b/boca-1.5.0/src/hex.php new file mode 100644 index 0000000..ec80230 --- /dev/null +++ b/boca-1.5.0/src/hex.php @@ -0,0 +1,151 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified: 21/july/2012 by cassio@ime.usp.br +function myshorthash($k) { + return hash('sha1',$k); +} +function myhash($k) { + return hash('sha256',$k); +} +function myhmac($k,$d) { + return hash_hmac('sha256',$k,$d); +} + +function encryptData($text,$key,$compress=true) { + if(!function_exists('mcrypt_get_iv_size')) { + MSGError("Encryption error -- mcrypt not installed -- contact an admin (" . getFunctionName() .")"); + LogError("Encryption error -- mcrypt not installed -- contact an admin (" . getFunctionName() .")"); + return ""; + } + $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); + $iv = mcrypt_create_iv($iv_size, MCRYPT_RAND); + $key = myhash($key . "123456789012345678901234567890"); // . myhash($key); + $grade='##'; + if($compress) { + $text = zipstr($text); + $grade = '@#'; + } + $crypttext = mcrypt_encrypt(MCRYPT_RIJNDAEL_256, substr(pack("H*", $key),0,32), $text . myshorthash($text) . $grade, MCRYPT_MODE_CBC, $iv); + return base64_encode($crypttext . $iv); +} + +function decryptData($crypttext,$key,$txt='') { + $crypttext = base64_decode($crypttext); + $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_256, MCRYPT_MODE_CBC); + $test1=''; + $test2='x'; + $clen = strlen($crypttext); + if($clen > $iv_size) { + $iv = substr($crypttext, $clen-$iv_size, $iv_size); + $crypttext = substr($crypttext, 0, $clen-$iv_size); + $key = myhash($key . "123456789012345678901234567890"); // . myhash($key); + $decrypttext = mcrypt_decrypt(MCRYPT_RIJNDAEL_256, substr(pack("H*", $key),0,32), $crypttext, MCRYPT_MODE_CBC, $iv); + $pos = strrpos($decrypttext,"#"); + $iscompressed=false; + if(substr($decrypttext,$pos-1,1)=='@') $iscompressed=true; + $ll=strlen(myshorthash("x")); + $test2 = substr($decrypttext,$pos-1-$ll, $ll); + $decrypttext = substr($decrypttext,0,$pos-1-$ll); + $test1 = myshorthash($decrypttext); + } + if($test1 != $test2) { + if($txt=='') + MSGError("Decryption error -- contact an admin now (" . getFunctionName() .")"); + LogError("Decryption error -- contact an admin, possibly password wrong (" . getFunctionName() .",$txt)"); + return ""; + } + if($iscompressed) return unzipstr($decrypttext); + return $decrypttext; +} + +//hex1 e hex2 sao strings hexa +//devolve a soma das duas +function bighexsoma ($hex1, $hex2){ + if (strlen($hex1) > strlen($hex2)) { + $a = $hex2; + $hex2 = $hex1; + $hex1 = $a; + } + while (strlen($hex1) < strlen($hex2)) + $hex1 = '0' . $hex1; + + $sobra = 0; + $resultado = ''; + for($x = strlen($hex1)-1; $x>=0; $x--){ + + $op1 = (int) hexdec(substr($hex1,$x,1)); + $op2 = (int) hexdec(substr($hex2,$x,1)); + + $r = $op1 + $op2 + $sobra; + if ($r > 15) { + $r -= 16; + $sobra = 1; + } else $sobra = 0; + + $resultado = dechex($r) . $resultado; + } + if ($sobra == 1) + $resultado = '1' . $resultado; + return $resultado; +} +//hex1 e hex2 sao strings hexa +//devolve a string que representa hex2 - hex1 +function bighexsub ($hex1, $hex2) { + if (strlen($hex1) == strlen($hex2)) { + $i=0; + while ($hex1[$i] == $hex2[$i] && $i<strlen($hex1)) $i++; + + if ($i>=strlen($hex1)) return 0; + if ($hex1[$i] > $hex2[$i]) { + $sinal=''; + $a = $hex2; + $hex2 = $hex1; + $hex1 = $a; + } else $sinal = '-'; + } + else { + if (strlen($hex1) < strlen($hex2)) $sinal='-'; + else { + $sinal=''; + $a = $hex2; + $hex2 = $hex1; + $hex1 = $a; + } + while (strlen($hex1) < strlen($hex2)) + $hex1 = '0' . $hex1; + } + + $sobra = 0; + $resultado = ''; + for($x = strlen($hex1)-1; $x>=0; $x--){ + + $op1 = (int) hexdec(substr($hex1,$x,1)); + $op2 = (int) hexdec(substr($hex2,$x,1)); + + $r = $op2 - $op1 - $sobra; + if ($r < 0) { + $r += 16; + $sobra = 1; + } else $sobra = 0; + + $resultado = dechex($r) . $resultado; + } + return $sinal . $resultado; +} +// eof +?> diff --git a/boca-1.5.0/src/hide.js b/boca-1.5.0/src/hide.js new file mode 100644 index 0000000..beaa84e --- /dev/null +++ b/boca-1.5.0/src/hide.js @@ -0,0 +1,28 @@ +var modifyClassName = function (elem, add, string) { +var s = (elem.className) ? elem.className : ""; +var a = s.split(" "); +if (add) { + for (var i=0; i<a.length; i++) { + if (a[i] == string) { + return; + } + } + s += " " + string; + } +else { + s = ""; + for (var i=0; i<a.length; i++) { + if (a[i] != string) + s += a[i] + " "; + } + } +elem.className = s; +} +function toggleGroup(n) { + //alert(n); + var currentClass = document.getElementById("myscoretable"); + for (var i=1; i<20; i++) { + modifyClassName(currentClass,true,"sitehide"+i); + } + modifyClassName(currentClass,false,"sitehide"+n); +} diff --git a/boca-1.5.0/src/images/12x16.ico b/boca-1.5.0/src/images/12x16.ico Binary files differnew file mode 100644 index 0000000..a64595a --- /dev/null +++ b/boca-1.5.0/src/images/12x16.ico diff --git a/boca-1.5.0/src/images/a.png b/boca-1.5.0/src/images/a.png Binary files differnew file mode 100644 index 0000000..67c7dff --- /dev/null +++ b/boca-1.5.0/src/images/a.png diff --git a/boca-1.5.0/src/images/balloon.jpeg b/boca-1.5.0/src/images/balloon.jpeg Binary files differnew file mode 100644 index 0000000..dca9637 --- /dev/null +++ b/boca-1.5.0/src/images/balloon.jpeg diff --git a/boca-1.5.0/src/images/balloon.png b/boca-1.5.0/src/images/balloon.png Binary files differnew file mode 100644 index 0000000..665573c --- /dev/null +++ b/boca-1.5.0/src/images/balloon.png diff --git a/boca-1.5.0/src/images/balloon1.png b/boca-1.5.0/src/images/balloon1.png Binary files differnew file mode 100644 index 0000000..b20a3e3 --- /dev/null +++ b/boca-1.5.0/src/images/balloon1.png diff --git a/boca-1.5.0/src/images/balloon2.png b/boca-1.5.0/src/images/balloon2.png Binary files differnew file mode 100644 index 0000000..50453c0 --- /dev/null +++ b/boca-1.5.0/src/images/balloon2.png diff --git a/boca-1.5.0/src/images/balloon3.png b/boca-1.5.0/src/images/balloon3.png Binary files differnew file mode 100644 index 0000000..2539db5 --- /dev/null +++ b/boca-1.5.0/src/images/balloon3.png diff --git a/boca-1.5.0/src/images/balloon4.png b/boca-1.5.0/src/images/balloon4.png Binary files differnew file mode 100644 index 0000000..198ee7c --- /dev/null +++ b/boca-1.5.0/src/images/balloon4.png diff --git a/boca-1.5.0/src/images/balloon5.bmp b/boca-1.5.0/src/images/balloon5.bmp Binary files differnew file mode 100644 index 0000000..5ace841 --- /dev/null +++ b/boca-1.5.0/src/images/balloon5.bmp diff --git a/boca-1.5.0/src/images/bigballoon.png b/boca-1.5.0/src/images/bigballoon.png Binary files differnew file mode 100644 index 0000000..b2957ea --- /dev/null +++ b/boca-1.5.0/src/images/bigballoon.png diff --git a/boca-1.5.0/src/images/bigballoon2.png b/boca-1.5.0/src/images/bigballoon2.png Binary files differnew file mode 100644 index 0000000..1726be5 --- /dev/null +++ b/boca-1.5.0/src/images/bigballoon2.png diff --git a/boca-1.5.0/src/images/bigballoonboca.png b/boca-1.5.0/src/images/bigballoonboca.png Binary files differnew file mode 100644 index 0000000..83017c3 --- /dev/null +++ b/boca-1.5.0/src/images/bigballoonboca.png diff --git a/boca-1.5.0/src/images/bigballoonboca1.png b/boca-1.5.0/src/images/bigballoonboca1.png Binary files differnew file mode 100644 index 0000000..c62ae5d --- /dev/null +++ b/boca-1.5.0/src/images/bigballoonboca1.png diff --git a/boca-1.5.0/src/images/bigballoontransp-blink.gif b/boca-1.5.0/src/images/bigballoontransp-blink.gif Binary files differnew file mode 100644 index 0000000..29c73ee --- /dev/null +++ b/boca-1.5.0/src/images/bigballoontransp-blink.gif diff --git a/boca-1.5.0/src/images/bigballoontransp-hash.png b/boca-1.5.0/src/images/bigballoontransp-hash.png Binary files differnew file mode 100644 index 0000000..a03f38d --- /dev/null +++ b/boca-1.5.0/src/images/bigballoontransp-hash.png diff --git a/boca-1.5.0/src/images/bigballoontransp-md5.png b/boca-1.5.0/src/images/bigballoontransp-md5.png Binary files differnew file mode 100644 index 0000000..4f2a2cc --- /dev/null +++ b/boca-1.5.0/src/images/bigballoontransp-md5.png diff --git a/boca-1.5.0/src/images/bigballoontransp-md52.png b/boca-1.5.0/src/images/bigballoontransp-md52.png Binary files differnew file mode 100644 index 0000000..cd285f1 --- /dev/null +++ b/boca-1.5.0/src/images/bigballoontransp-md52.png diff --git a/boca-1.5.0/src/images/bigballoontransp.png b/boca-1.5.0/src/images/bigballoontransp.png Binary files differnew file mode 100644 index 0000000..9879a65 --- /dev/null +++ b/boca-1.5.0/src/images/bigballoontransp.png diff --git a/boca-1.5.0/src/images/poweredbyboca.png b/boca-1.5.0/src/images/poweredbyboca.png Binary files differnew file mode 100644 index 0000000..a74d5cc --- /dev/null +++ b/boca-1.5.0/src/images/poweredbyboca.png diff --git a/boca-1.5.0/src/images/smallballoon.png b/boca-1.5.0/src/images/smallballoon.png Binary files differnew file mode 100644 index 0000000..ba04133 --- /dev/null +++ b/boca-1.5.0/src/images/smallballoon.png diff --git a/boca-1.5.0/src/images/smallballoontransp.png b/boca-1.5.0/src/images/smallballoontransp.png Binary files differnew file mode 100644 index 0000000..4f18618 --- /dev/null +++ b/boca-1.5.0/src/images/smallballoontransp.png diff --git a/boca-1.5.0/src/images/tst.php b/boca-1.5.0/src/images/tst.php new file mode 100644 index 0000000..38f5fd0 --- /dev/null +++ b/boca-1.5.0/src/images/tst.php @@ -0,0 +1,11 @@ +<?php + +header('Content-type: image/png'); + +$smile=imagecreatefrompng("../images/balloon4.png"); +imageSaveAlpha($smile, true); +$kek=imagecolorallocate($smile,0,0,255); +imagefill($smile,12,25,$kek); +imagepng($smile); + +?> diff --git a/boca-1.5.0/src/index.php b/boca-1.5.0/src/index.php new file mode 100644 index 0000000..db904c7 --- /dev/null +++ b/boca-1.5.0/src/index.php @@ -0,0 +1,141 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +header ("Content-Type: text/html; charset=utf-8"); +session_start(); +$_SESSION["loc"] = dirname($_SERVER['PHP_SELF']); +if($_SESSION["loc"]=="/") $_SESSION["loc"] = ""; +$_SESSION["locr"] = dirname(__FILE__); +if($_SESSION["locr"]=="/") $_SESSION["locr"] = ""; + +require_once("globals.php"); +require_once("db.php"); + +if (!isset($_GET["name"])) { + if (ValidSession()) + DBLogOut($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], $_SESSION["usertable"]["usernumber"], + $_SESSION["usertable"]["username"]=='admin'); + session_unset(); + session_destroy(); + session_start(); + $_SESSION["loc"] = dirname($_SERVER['PHP_SELF']); + if($_SESSION["loc"]=="/") $_SESSION["loc"] = ""; + $_SESSION["locr"] = dirname(__FILE__); + if($_SESSION["locr"]=="/") $_SESSION["locr"] = ""; +} +ob_end_flush(); + +require_once('version.php'); + +?> +<title>BOCA Online Contest Administrator <?php echo $BOCAVERSION; ?> - Login</title> +<head> +<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> +<link rel=stylesheet href="Css.php" type="text/css"> +<script language="JavaScript" src="sha256.js"></script> +<script language="JavaScript"> +function computeHASH() +{ + var userHASH, passHASH; + userHASH = document.form1.name.value; + passHASH = js_myhash(js_myhash(document.form1.password.value)+'<?php echo session_id(); ?>'); + document.form1.name.value = ''; + document.form1.password.value = ' '; + document.location = 'index.php?name='+userHASH+'&password='+passHASH; +} +</script> +<?php +if(function_exists("globalconf") && function_exists("sanitizeVariables")) { + if(isset($_GET["name"]) && $_GET["name"] != "" ) { + $name = $_GET["name"]; + $password = $_GET["password"]; + $usertable = DBLogIn($name, $password); + if(!$usertable) { + ForceLoad("index.php"); + } + else { + if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("index.php"); + if($ct["contestlocalsite"]==$ct["contestmainsite"]) $main=true; else $main=false; + if($main && $_SESSION["usertable"]["usertype"] == 'site') { + MSGError('Direct login of this user is not allowed'); + unset($_SESSION["usertable"]); + ForceLoad("index.php"); + exit; + } + echo "<script language=\"JavaScript\">\n"; + echo "document.location='" . $_SESSION["usertable"]["usertype"] . "/index.php';\n"; + echo "</script>\n"; + exit; + } + } +} else { + echo "<script language=\"JavaScript\">\n"; + echo "alert('Unable to load config files. Possible file permission problem in the BOCA directory.');\n"; + echo "</script>\n"; +} +?> +</head> +<body onload="document.form1.name.focus()"> +<table width="100%" height="100%" border="0"> + <tr align="center" valign="middle"> + <td> + <form name="form1" action="javascript:computeHASH()"> + <div align="center"> + <table border="0" align="center"> + <tr> + <td nowrap> + <div align="center"><font face="Verdana, Arial, Helvetica, sans-serif" size="+1"> + BOCA Login</font></div> + </td> + </tr> + <tr> + <td valign="top"> + <table border="0" align="left"> + <tr> + <td><font face="Verdana, Arial, Helvetica, sans-serif" > + Name + </font></td> + <td> + <input type="text" name="name"> + </td> + </tr> + <tr> + <td><font face="Verdana, Arial, Helvetica, sans-serif" >Password</font></td> + <td> + <input type="password" name="password"> + </td> + </tr> + </table> + <input type="submit" name="Submit" value="Login"> + </td> + </tr> + </table> + </div> + </form> + </td> + </tr> +</table> +<?php include('footnote.php'); ?> diff --git a/boca-1.5.0/src/judge/clar.php b/boca-1.5.0/src/judge/clar.php new file mode 100644 index 0000000..a5d56ce --- /dev/null +++ b/boca-1.5.0/src/judge/clar.php @@ -0,0 +1,124 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +if (isset($_POST["message"]) && isset($_POST["problem"]) && isset($_POST["Submit"])) { + if ($_POST["confirmation"] == "confirm") { + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + $param['site']=$_SESSION["usertable"]["usersitenumber"]; + $param['user']= $_SESSION["usertable"]["usernumber"]; + $param['problem'] = htmlspecialchars($_POST["problem"]); + $param['question'] = htmlspecialchars($_POST["message"]); + DBNewClar($param); + } + ForceLoad("clar.php"); +} +?> +<br> +<table width="100%" border=1> + <tr> + <td><b>Clar #</b></td> + <td><b>Site</b></td> + <td><b>Time</b></td> + <td><b>Problem</b></td> + <td><b>Status</b></td> + <td><b>Question</b></td> + </tr> +<?php + +if(($s = DBSiteInfo($_SESSION["usertable"]["contestnumber"], $_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +$clar = DBOpenClarsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"]); + +for ($i=0; $i<count($clar); $i++) { + echo " <tr>\n"; + if (strpos($clar[$i]["status"], "answered") === false) + echo " <td nowrap><a href=\"claredit.php?clarnumber=".$clar[$i]["number"]."&clarsitenumber=".$clar[$i]["site"] . + "\">" . $clar[$i]["number"] . "</td>\n"; + else + echo " <td nowrap>" . $clar[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . $clar[$i]["site"] . "</td>\n"; + echo " <td nowrap>" . dateconvminutes($clar[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $clar[$i]["problem"] . "</td>\n"; + if ($clar[$i]["judge"] == $_SESSION["usertable"]["usernumber"] && + $clar[$i]["judgesite"] == $_SESSION["usertable"]["usersitenumber"]) + $color="ff7777"; + else if ($clar[$i]["status"] == "answering") $color="77ff77"; + else if ($clar[$i]["status"] == "openclar") $color="ffff88"; + else $color="ffffff"; + + echo " <td nowrap bgcolor=\"#$color\">" . $clar[$i]["status"] . "</td>\n"; + + if ($clar[$i]["question"] == "") $clar[$i]["question"] = " "; + + echo " <td>"; +// echo "<pre>" . $clar[$i]["question"] . "</pre>"; +// echo $clar[$i]["question"]; + echo " <textarea name=\"m$i\" cols=\"60\" rows=\"8\" readonly>".$clar[$i]["question"]."</textarea>\n"; + echo "</td>\n"; + + echo " </tr>\n"; +} + +echo "</table>"; +if (count($clar) == 0) echo "<br><center><b><font color=\"#ff0000\">NO CLARIFICATIONS AVAILABLE</font></b></center>"; + +?> +<br><br><br><center><b>To submit a clarification, just fill in the following fields +</b></center> +<form name="form1" method="post" action="clar.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="0"> + <tr> + <td width="13%" align=right>Problem:</td> + <td width="87%"> + <select name="problem"> +<?php +$prob = DBGetAllProblems($_SESSION["usertable"]["contestnumber"]); +for ($i=0;$i<count($prob);$i++) + echo "<option value=\"" . $prob[$i]["number"] . "\">" . $prob[$i]["problem"] . "</option>\n"; +?> + </select> + </td> + </tr> + <tr> + <td width="13%" align=right>Clarification:</td> + <td width="87%"> + <textarea name="message" cols="60" rows="8" maxlength="2000"></textarea> + </td> + </tr> + </table> + </center> + <script language="javascript"> + function conf() { + if (confirm("Confirm clarification?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Send" onClick="conf()"> + <input type="reset" name="Submit2" value="Clear"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/judge/claredit.php b/boca-1.5.0/src/judge/claredit.php new file mode 100644 index 0000000..5408e6b --- /dev/null +++ b/boca-1.5.0/src/judge/claredit.php @@ -0,0 +1,155 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +if (isset($_POST["answer"]) && isset($_POST["giveup"]) && $_POST["giveup"]=="Cancel" && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["number"]) && + is_numeric($_POST["sitenumber"])) { + + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + + DBClarGiveUp($number, $sitenumber, $_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"]); + MSGError("Clarification returned."); + ForceLoad("clar.php"); +} + +if (isset($_POST["answer"]) && isset($_POST["Submit"]) && ($_POST["Submit"]=="Answer" || $_POST["Submit"]=="No response") && + is_numeric($_POST["number"]) && isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["sitenumber"])) { + if ($_POST["confirmation"]=="confirm") { + + $ans = myhtmlspecialchars($_POST["answer"]); + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + + if ($_POST["Submit"]=="No response") + $ans='No response. '.$ans; + + if (trim($ans)=="") { + DBClarGiveUp($number, $sitenumber, $_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"]); + MSGError("Clarification returned."); + } else { + if (isset($_POST["answerall"])) $type='all'; + else if (isset($_POST["answersite"])) $type='site'; + else $type = 'none'; + + DBUpdateClar($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], + $sitenumber, $number, $ans, $type); + } + } + ForceLoad("clar.php"); +} + +if (!isset($_GET["clarnumber"]) || !isset($_GET["clarsitenumber"]) || + !is_numeric($_GET["clarnumber"]) || !is_numeric($_GET["clarsitenumber"])) { + IntrusionNotify("tried to open the judge/claredit.php with wrong parameters."); + ForceLoad("clar.php"); +} + +$clarsitenumber = myhtmlspecialchars($_GET["clarsitenumber"]); +$clarnumber = myhtmlspecialchars($_GET["clarnumber"]); + +if (($a = DBGetClarToAnswer($clarnumber, $clarsitenumber, + $_SESSION["usertable"]["contestnumber"])) === false) { + MSGError("Another judge got it first."); + ForceLoad("clar.php"); +} + +?> +<br><br><center><b>Use the following fields to answer the clarification: +</b></center> +<form name="form1" method="post" action="claredit.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="0"> + <tr> + <td width="20%" align=right><b>Clarification Site:</b></td> + <td width="80%"> + <input type=hidden name="sitenumber" value="<?php echo $a["sitenumber"]; ?>" /> + <?php echo $a["sitenumber"]; ?> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Clarification Number:</b></td> + <td width="80%"> + <input type=hidden name="number" value="<?php echo $a["number"]; ?>" /> + <?php echo $a["number"]; ?> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Clarification Time:</b></td> + <td width="80%"> + <?php echo dateconvminutes($a["timestamp"]); ?> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Problem:</b></td> + <td width="80%"> + <?php echo $a["problemname"]; ?> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Clarification:</b></td> + <td width="80%"> + <textarea name="message" readonly cols="60" rows="8"><?php echo $a["question"]; ?></textarea> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Answer:</b></td> + <td width="80%"> + <textarea name="answer" cols="60" rows="8"><?php echo $a["answer"]; ?></textarea> + </td> + </tr> + <tr> + <td width="20%" align=right><b>Answer to all users in the site</b></td> + <td width="80%"> + <input class=checkbox type=checkbox name="answersite" value="yes"> + </td> + </tr> +<!-- + <tr> + <td width="20%" align=right><b>Answer to all users in all sites</b></td> + <td width="80%"> + <input class=checkbox type=checkbox name="answerall" value="yes"> + </td> + </tr> +--> + </table> + </center> + <script language="javascript"> + function conf() { +// if (confirm("Confirm clarification?")) { + document.form1.confirmation.value='confirm'; +// } + } + </script> + <center> + <input type="submit" name="Submit" value="Answer" onclick="conf()"> + <input type="submit" name="Submit" value="No response" onclick="conf()"> + <input type="submit" name="giveup" value="Cancel"> + <input type="reset" name="Submit2" value="Clear"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/judge/header.php b/boca-1.5.0/src/judge/header.php new file mode 100644 index 0000000..db2136d --- /dev/null +++ b/boca-1.5.0/src/judge/header.php @@ -0,0 +1,98 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +header ("Content-Type: text/html; charset=utf-8"); +session_start(); +ob_end_flush(); +require('../version.php'); +require_once("../globals.php"); +require_once("../db.php"); + +$runteam='team.php'; +$runphp = "runchief.php"; +$runeditphp = "runeditchief.php"; + +echo "<html><head><title>Judge's Page</title>\n"; +echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"; +echo "<link rel=stylesheet href=\"../Css.php\" type=\"text/css\">\n"; + +//temporario!!!! +//echo "<meta http-equiv=\"refresh\" content=\"60\" />"; +if(!ValidSession()) { + InvalidSession("judge/index.php"); + ForceLoad("../index.php"); +} +if($_SESSION["usertable"]["usertype"] != "judge") { + IntrusionNotify("judge/index.php"); + ForceLoad("../index.php"); +} + +if(($s = DBSiteInfo($_SESSION["usertable"]["contestnumber"], $_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +if($s["sitechiefname"]== $_SESSION["usertable"]["username"]) + $cc = "338833"; +else + $cc = "77cc77"; + + +echo "<script language=\"javascript\" src=\"../reload.js\"></script>\n"; +echo "</head><body onload=\"Comecar()\" onunload=\"Parar()\"><table border=1 width=\"100%\">\n"; +echo "<tr><td nowrap bgcolor=\"#$cc\" align=center>"; +echo "<img src=\"../images/smallballoontransp.png\" alt=\"\">"; +echo "<font color=\"#000000\">BOCA</font>"; +echo "</td><td bgcolor=\"#$cc\" width=\"99%\">\n"; +echo "Username: " . $_SESSION["usertable"]["userfullname"] . " (site=".$_SESSION["usertable"]["usersitenumber"].")<br>\n"; +list($clockstr,$clocktype)=siteclock(); +echo "</td><td bgcolor=\"#$cc\" align=center nowrap> ".$clockstr." </td></tr>\n"; +echo "</table>\n"; + +$clar = DBOpenClarsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"]); +$run = DBOpenRunsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"]); +if($s["sitechiefname"]== $_SESSION["usertable"]["username"]) { +$nrchief = 0; +$rrun = DBAllRunsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"]); +for ($i=0; $i<count($rrun); $i++) { + if($rrun[$i]["answer1"] != 0 && $rrun[$i]["answer2"] != 0 && $rrun[$i]["status"] != "judged") + $nrchief++; +} +} +$nr=count($run); +$nc=count($clar); + +echo "<table border=0 width=\"100%\" align=center>\n"; +echo " <tr>\n"; +echo " <td align=center width=\"10%\"><a class=menu style=\"font-weight:bold\" href=run.php>Runs ($nr)</a></td>\n"; +if($s["sitechiefname"]== $_SESSION["usertable"]["username"]) { + echo " <td align=center width=\"10%\"><a class=menu style=\"font-weight:bold\" href=runchief.php>Chief ($nrchief)</a></td>\n"; +} +echo " <td align=center width=\"10%\"><a class=menu style=\"font-weight:bold\" href=score.php>Score</a></td>\n"; +echo " <td align=center width=\"10%\"><a class=menu style=\"font-weight:bold\" href=clar.php>Clarifications ($nc)</a></td>\n"; + +echo " <td align=center width=\"10%\"><a class=menu style=\"font-weight:bold\" href=history.php>History</a></td>\n"; +echo " <td align=center width=\"10%\"><a class=menu style=\"font-weight:bold\" href=team.php>As Team</a></td>\n"; +echo " <td align=center width=\"10%\"><a class=menu style=\"font-weight:bold\" href=option.php>Options</a></td>\n"; +echo " <td align=center width=\"10%\"><a class=menu style=\"font-weight:bold\" href=../index.php>Logout</a></td>\n"; +echo " </tr>\n"; +echo "</table>\n"; +?> diff --git a/boca-1.5.0/src/judge/history.php b/boca-1.5.0/src/judge/history.php new file mode 100644 index 0000000..b612f9a --- /dev/null +++ b/boca-1.5.0/src/judge/history.php @@ -0,0 +1,129 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +// updated 20/oct/08 by cassio@ime.usp.br +// - bugfix of Marcelo Cezar Pinto (mcpinto@unipampa.edu.br) - div by zero at counts +require('header.php'); +?> +<br> +<table width="100%" border=1> + <tr> + <td><b>Clar # (site)</b></td> + <td><b>Time</b></td> + <td><b>Problem</b></td> + <td><b>Status</b></td> + <td><b>Question</b></td> + <td><b>Answer</b></td> + </tr> +<?php +$clar = DBAllClarsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"], "clar"); +//$clar = DBJudgedClars($_SESSION["usertable"]["contestnumber"], +// $_SESSION["usertable"]["usersitenumber"], +// $_SESSION["usertable"]["usernumber"]); +$myclars = 0; +for ($i=0; $i<count($clar); $i++) { + echo " <tr>\n"; + if($clar[$i]["judge"] == $_SESSION["usertable"]["usernumber"] && + $clar[$i]["judgesite"] == $_SESSION["usertable"]["usersitenumber"]) { + echo " <td nowrap bgcolor=\"#b0b0a0\">" . $clar[$i]["number"] . "(" . $clar[$i]["site"] . ")</td>\n"; + $myclars++; + } + else + echo " <td nowrap>" . $clar[$i]["number"] . "(" . $clar[$i]["site"] . ")</td>\n"; + echo " <td nowrap>" . dateconvminutes($clar[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $clar[$i]["problem"] . "</td>\n"; + echo " <td nowrap>" . $clar[$i]["status"] . "</td>\n"; + if ($clar[$i]["question"] == "") $clar[$i]["question"] = " "; + if ($clar[$i]["answer"] == "") $clar[$i]["answer"] = " "; + + echo " <td>"; +// echo "<pre>" . $clar[$i]["question"] . "</pre>"; +// echo $clar[$i]["question"]; + echo " <textarea name=\"m$i\" cols=\"60\" rows=\"8\" readonly>".$clar[$i]["question"]."</textarea>\n"; + echo "</td>\n"; + if (trim($clar[$i]["answer"]) == "") $clar[$i]["answer"] = "Not answered yet"; + echo " <td>"; +// echo " <pre>" . $clar[$i]["answer"] . "</pre>"; +// echo $clar[$i]["answer"]; + echo " <textarea name=\"a$i\" cols=\"60\" rows=\"8\" readonly>".$clar[$i]["answer"]."</textarea>\n"; + echo "</td>\n"; + + echo " </tr>\n"; +} +echo "</table>"; +if (count($clar) == 0) echo "<br><center><b><font color=\"#ff0000\">NO CLARIFICATIONS AVAILABLE</font></b></center>"; +else echo "<br><b><font color=\"#b0b0a0\">* Shadowed clars and runs were judged by this judge</font></b>"; + +?> +<br><br> +<table width="100%" border=1> + <tr> + <td><b>Run #</b></td> + <td><b>Time</b></td> + <td><b>Problem</b></td> + <td><b>Language</b></td> + <td><b>Status</b></td> + <td><b>Answer</b></td> + </tr> +<?php +$run = DBAllRunsInSites($_SESSION["usertable"]["contestnumber"], + $s["sitejudging"], + "run"); +//$run = DBJudgedRuns($_SESSION["usertable"]["contestnumber"], +// $_SESSION["usertable"]["usersitenumber"], +// $_SESSION["usertable"]["usernumber"]); +$yes = 0; +$myyes = 0; +$myruns = 0; +for ($i=0; $i<count($run); $i++) { + echo " <tr>\n"; + if($run[$i]["yes"]=="t") $yes++; + if(($_SESSION["usertable"]["usersitenumber"] == $run[$i]["judgesite1"] && + $_SESSION["usertable"]["usernumber"] == $run[$i]["judge1"]) || + ($_SESSION["usertable"]["usersitenumber"] == $run[$i]["judgesite2"] && + $_SESSION["usertable"]["usernumber"] == $run[$i]["judge2"])) { + echo " <td nowrap bgcolor=\"#b0b0a0\">" . $run[$i]["number"] . "</td>\n"; + if($run[$i]["yes"]=="t") $myyes++; + $myruns++; + } + else + echo " <td nowrap>" . $run[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . dateconvminutes($run[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $run[$i]["problem"] . "</td>\n"; + echo " <td nowrap>" . $run[$i]["language"] . "</td>\n"; + echo " <td nowrap>" . $run[$i]["status"] . "</td>\n"; + if ($run[$i]["answer"] == "") $run[$i]["answer"] = " "; + echo " <td>" . $run[$i]["answer"] . "</td>\n"; + echo " </tr>\n"; +} +echo "</table>"; +if (count($run) == 0) echo "<br><center><b><font color=\"#ff0000\">NO RUNS AVAILABLE</font></b></center>"; + +echo "<br><br>\n"; +echo "My answered clars: " . $myclars . "/" . count($clar) . " ("; +if(count($clar)>0) echo ((int) ($myclars*1000/count($clar)))/10 . "%)<br>\n"; +else echo "0%)<br>\n"; +echo "My judged runs: " . $myruns . "/" . count($run) ." ("; +if(count($run)>0) echo ((int) ($myruns*1000/count($run)))/10 . "%)<br>\n"; +else echo "0%)<br>\n"; +echo "Accepted runs that I've judged: " . $myyes . "/" . $yes . " ("; +if($yes>0) echo ((int) ($myyes*1000/$yes))/10 ."%)<br>\n"; +else echo "0%)<br>\n"; +?> +</body> +</html> diff --git a/boca-1.5.0/src/judge/index.php b/boca-1.5.0/src/judge/index.php new file mode 100644 index 0000000..ec74ce9 --- /dev/null +++ b/boca-1.5.0/src/judge/index.php @@ -0,0 +1,22 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +?> +</body> +</html> diff --git a/boca-1.5.0/src/judge/option.php b/boca-1.5.0/src/judge/option.php new file mode 100644 index 0000000..81e5879 --- /dev/null +++ b/boca-1.5.0/src/judge/option.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +require('../optionlower.php'); +?> diff --git a/boca-1.5.0/src/judge/run.php b/boca-1.5.0/src/judge/run.php new file mode 100644 index 0000000..9f08851 --- /dev/null +++ b/boca-1.5.0/src/judge/run.php @@ -0,0 +1,84 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +require('header.php'); +?> + +<br> +<table width="100%" border=1> + <tr> + <td><b>Run #</b></td> + <td><b>Site</b></td> + <td><b>Time</b></td> + <td><b>Problem</b></td> + <td><b>Language</b></td> +<!-- <td><b>Filename</b></td> --> + <td><b>Status</b></td> + <td><b>AJ</b></td> + <td><b>Answer</b></td> + </tr> +<?php +if (($s=DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +$run = DBOpenRunsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"]); + +for ($i=0; $i<count($run); $i++) { + echo " <tr>\n"; +// if (strpos($run[$i]["status"], "judged") === false || $run[$i]["judge"]=="" || $run[$i]["judge"]==$_SESSION["usertable"]["usernumber"]) + echo " <td nowrap><a href=\"runedit.php?runnumber=".$run[$i]["number"]."&runsitenumber=".$run[$i]["site"] . + "\">" . $run[$i]["number"] . "</td>\n"; +// else +// echo " <td nowrap>" . $run[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . $run[$i]["site"] . "</td>\n"; + echo " <td nowrap>" . dateconvminutes($run[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $run[$i]["problem"] . "</td>\n"; + echo " <td nowrap>" . $run[$i]["language"] . "</td>\n"; +// echo " <td nowrap>" . $run[$i]["filename"] . "</td>\n"; + if ($run[$i]["judge1"] == $_SESSION["usertable"]["usernumber"] && + $run[$i]["judgesite1"] == $_SESSION["usertable"]["usersitenumber"]) + $color="ff7777"; + else if ($run[$i]["judge2"] == $_SESSION["usertable"]["usernumber"] && + $run[$i]["judgesite2"] == $_SESSION["usertable"]["usersitenumber"]) + $color="ff7777"; + else if ($run[$i]["status"] == "judged+") $color="ffff00"; + else if ($run[$i]["status"] == "judged") $color="0000ff"; + else if ($run[$i]["status"] == "judging") $color="77ff77"; + else if ($run[$i]["status"] == "openrun") $color="ffff88"; + else $color="ffffff"; + + echo " <td nowrap bgcolor=\"#$color\">" . $run[$i]["status"] . "</td>\n"; + if ($run[$i]["autoend"] != "") { + $color="bbbbff"; + if ($run[$i]["autoanswer"]=="") $color="ff7777"; + } + else if ($run[$i]["autobegin"]=="") $color="ffff88"; + else $color="77ff77"; + echo "<td bgcolor=\"#$color\"> </td>\n"; + + if ($run[$i]["answer"] == "") $run[$i]["answer"] = " "; + echo " <td>" . $run[$i]["answer"] . "</td>\n"; + echo " </tr>\n"; +} + +echo "</table>"; +if (count($run) == 0) echo "<br><center><b><font color=\"#ff0000\">NO RUNS AVAILABLE</font></b></center>"; + +?> +</body> +</html> diff --git a/boca-1.5.0/src/judge/runchief.php b/boca-1.5.0/src/judge/runchief.php new file mode 100644 index 0000000..a4cd443 --- /dev/null +++ b/boca-1.5.0/src/judge/runchief.php @@ -0,0 +1,187 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require 'header.php'; +if(isset($_GET["order"]) && $_GET["order"] != "") { +$order = myhtmlspecialchars($_GET["order"]); + $_SESSION["runline"] = $order; +} else { + if(isset($_SESSION["runline"])) + $order = $_SESSION["runline"]; + else + $order = ''; +} +?> + +<form name="form1" method="post" action="<?php echo $runphp; ?>"> + <input type=hidden name="confirmation" value="noconfirm" /> +<br> +<table width="100%" border=1> + <tr> + <td><b><a href="<?php echo $runphp; ?>?order=run">Run #</a></b></td> + <td><b><a href="<?php echo $runphp; ?>?order=site">Site</a></b></td> +<?php if($runphp == "run.php") { ?> + <td><b><a href="<?php echo $runphp; ?>?order=user">User</a></b></td> +<?php } ?> + <td><b>Time</b></td> + <td><b><a href="<?php echo $runphp; ?>?order=problem">Problem</a></b></td> + <td><b><a href="<?php echo $runphp; ?>?order=language">Language</a></b></td> +<!-- <td><b>Filename</b></td> --> + <td><b><a href="<?php echo $runphp; ?>?order=status">Status</a></b></td> + <td><b><a href="<?php echo $runphp; ?>?order=judge">Judge (Site)</a></b></td> + <td><b>AJ</b></td> + <td><b><a href="<?php echo $runphp; ?>?order=answer">Answer</a></b></td> + </tr> +<?php +if (($s=DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +// forca aparecer as runs do proprio site +if (trim($s["sitejudging"])!="") $s["sitejudging"].=",".$_SESSION["usertable"]["usersitenumber"]; +else $s["sitejudging"]=$_SESSION["usertable"]["usersitenumber"]; + +$run = DBAllRunsInSites($_SESSION["usertable"]["contestnumber"], $s["sitejudging"], $order); + +if(isset($_POST)) { + $nrenew = 0; + $nreopen = 0; + for ($i=0; $i<count($run); $i++) { + if(isset($_POST["cbox_" . $run[$i]["number"] . "_" . $run[$i]["site"]]) && + $_POST["cbox_" . $run[$i]["number"] . "_" . $run[$i]["site"]] != "") { + if(isset($_POST["auto"]) && $_POST["auto"]=="Re-run autojudge for selected runs") { + if (DBGiveUpRunAutojudging($_SESSION["usertable"]["contestnumber"], + $run[$i]["site"], $run[$i]["number"])) + $nrenew++; + } + if(isset($_POST["open"]) && $_POST["open"]=="Open selected runs for rejudging") { + DBGiveUpRunAutojudging($_SESSION["usertable"]["contestnumber"], + $run[$i]["site"], $run[$i]["number"]); + if (DBChiefRunGiveUp($run[$i]["number"], $run[$i]["site"], + $_SESSION["usertable"]["contestnumber"])) + $nreopen++; + } + } + } + if($nrenew > 0) { + MSGError($nrenew . " runs renewed for autojudging."); + ForceLoad($runphp); + } + if($nreopen > 0) { + MSGError($nreopen . " runs reopened."); + ForceLoad($runphp); + } +} + + +for ($i=0; $i<count($run); $i++) { + if($run[$i]["answer1"] != 0 && $run[$i]["answer2"] != 0 && $run[$i]["status"] != "judged") { + if($runphp == "runchief.php") + echo " <tr bgcolor=\"ff0000\">\n"; + else echo "<tr>\n"; + echo " <td nowrap bgcolor=\"ff0000\">"; + } + else { + echo " <tr><td nowrap>"; + } + echo "<input type=\"checkbox\" name=\"cbox_" . $run[$i]["number"] . "_" . $run[$i]["site"] . "\" />"; + echo " <a href=\"" . $runeditphp . "?runnumber=".$run[$i]["number"]."&runsitenumber=".$run[$i]["site"] . + "\">" . $run[$i]["number"] . "</a></td>\n"; + + echo " <td nowrap>" . $run[$i]["site"] . "</td>\n"; + if($runphp == "run.php") { + if ($run[$i]["user"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["site"], $run[$i]["user"]); + echo " <td nowrap>" . $u["username"] . "</td>\n"; + } + } + echo " <td nowrap>" . dateconvminutes($run[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $run[$i]["problem"] . "</td>\n"; + echo " <td nowrap>" . $run[$i]["language"] . "</td>\n"; +// echo " <td nowrap>" . $run[$i]["filename"] . "</td>\n"; + if ($run[$i]["judge"] == $_SESSION["usertable"]["usernumber"] && + $run[$i]["judgesite"] == $_SESSION["usertable"]["usersitenumber"] && $run[$i]["status"] == "judging") + $color="ff7777"; + else if ($run[$i]["status"]== "judged+" && $run[$i]["judge"]=="") $color="ffff00"; + else if ($run[$i]["status"]== "judged") $color="bbbbff"; + else if ($run[$i]["status"] == "judging" || $run[$i]["status"]== "judged+") $color="77ff77"; + else if ($run[$i]["status"] == "openrun") $color="ffff88"; + else $color="ffffff"; + + echo " <td nowrap bgcolor=\"#$color\">" . $run[$i]["status"] . "</td>\n"; + if ($run[$i]["judge"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["judgesite"], $run[$i]["judge"]); + echo " <td nowrap>" . $u["username"] . " (" . $run[$i]["judgesite"] . ")"; + } else + echo " <td> "; + + if ($run[$i]["judge1"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["judgesite1"], $run[$i]["judge1"]); + echo " [" . $u["username"] . " (" . $run[$i]["judgesite1"] . ")]"; + } + if ($run[$i]["judge2"] != "") { + $u = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $run[$i]["judgesite2"], $run[$i]["judge2"]); + echo " [" . $u["username"] . " (" . $run[$i]["judgesite2"] . ")]"; + } + + echo "</td>\n"; + + if ($run[$i]["autoend"] != "") { + $color="bbbbff"; + if ($run[$i]["autoanswer"]=="") $color="ff7777"; + } + else if ($run[$i]["autobegin"]=="") $color="ffff88"; + else $color="77ff77"; + echo "<td bgcolor=\"#$color\"> </td>\n"; + + if ($run[$i]["answer"] == "") { + echo " <td> </td>\n"; + } else { + echo " <td>" . $run[$i]["answer"]; + if($run[$i]['yes']=='t') { + echo " <img alt=\"".$run[$i]["colorname"]."\" width=\"10\" ". + "src=\"" . balloonurl($run[$i]["color"]) ."\" />"; + } + echo "</td>\n"; + } + echo " </tr>\n"; +} + +echo "</table>"; +if (count($run) == 0) echo "<br><center><b><font color=\"#ff0000\">NO RUNS AVAILABLE</font></b></center>"; +else { +?> + <br> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> +<b>Click on the number of a run to edit it or select them with<br />the checkboxes and use the buttons to work on multiple runs:</b><br /><br /> + <input type="submit" name="auto" value="Re-run autojudge for selected runs" onClick="conf()"> + <input type="submit" name="open" value="Open selected runs for rejudging" onClick="conf()"> +<br><br> + </center> + </form> +<?php +} +?> +</body> +</html> diff --git a/boca-1.5.0/src/judge/runedit.php b/boca-1.5.0/src/judge/runedit.php new file mode 100644 index 0000000..0361d30 --- /dev/null +++ b/boca-1.5.0/src/judge/runedit.php @@ -0,0 +1,271 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +require('header.php'); + +if (isset($_POST["answer"]) && isset($_POST["giveup"]) && $_POST["giveup"]=="Cancel editing" && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["number"]) && + is_numeric($_POST["sitenumber"])) { + + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + + DBRunGiveUp($_POST["number"], + $_POST["sitenumber"], + $_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usernumber"], + $_SESSION["usertable"]["usersitenumber"]); + MSGError("Run returned."); + ForceLoad("run.php"); +} + +if (isset($_POST["answer"]) && isset($_POST["Submit"]) && $_POST["Submit"]=="Judge" && is_numeric($_POST["answer"]) && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["sitenumber"]) && + is_numeric($_POST["number"])) { // && isset($_POST["notifyuser"]) && isset($_POST["updatescore"])) { + + if ($_POST["confirmation"] == "confirm") { + $answer = myhtmlspecialchars($_POST["answer"]); + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); +// $notuser = myhtmlspecialchars($_POST["notifyuser"]); +// $updscore = myhtmlspecialchars($_POST["updatescore"]); + + DBUpdateRun($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], + $sitenumber, $number, $answer); //, $notuser, updscore); + } + ForceLoad("run.php"); +} + +if (!isset($_GET["runnumber"]) || !isset($_GET["runsitenumber"]) || + !is_numeric($_GET["runnumber"]) || !is_numeric($_GET["runsitenumber"])) { + IntrusionNotify("tried to open the judge/runedit.php with wrong parameters."); + ForceLoad("run.php"); +} + +$runsitenumber = myhtmlspecialchars($_GET["runsitenumber"]); +$runnumber = myhtmlspecialchars($_GET["runnumber"]); + +if (($a = DBGetRunToAnswer($runnumber, $runsitenumber, + $_SESSION["usertable"]["contestnumber"])) === false) { + MSGError("Another judge got it first."); + ForceLoad("run.php"); +} + +$b = DBGetProblemData($_SESSION["usertable"]["contestnumber"], $a["problemnumber"]); +$c = DBGetLanguageData($_SESSION["usertable"]["contestnumber"], $a["langnumber"], $a["problemnumber"]); +?> +<br><br><center><b>Use the following fields to judge the run: +</b></center> +<form name="form1" method="post" action="runedit.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="1"> + <tr> + <td width="27%" align=right><b>Site:</b></td> + <td width="83%"> + <input type=hidden name="sitenumber" value="<?php echo $a["sitenumber"]; ?>" /> + <?php echo $a["sitenumber"]; ?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Number:</b></td> + <td width="83%"> + <input type=hidden name="number" value="<?php echo $a["number"]; ?>" /> + <?php echo $a["number"]; ?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Time:</b></td> + <td width="83%"> + <?php echo dateconvminutes($a["timestamp"]); ?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Problem</b><i> <?php echo $a["problemname"]; ?></i>: </td> + <td width="83%"> +<?php +for ($i=0;$i<count($b);$i++) { + $if = rawurlencode($b[$i]["inputfilename"]); + $sf = rawurlencode($b[$i]["solfilename"]); + + echo "<b>Input:</b><a href=\"../filedownload.php?". filedownload($b[$i]["inputoid"],$b[$i]["inputfilename"]) . "\">"; + echo $b[$i]["inputfilename"] . "</a>"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($b[$i]["inputoid"],$b[$i]["inputfilename"]) ."', 'View$i - INPUT','width=680,height=600,scrollbars=yes,". + "resizable=yes')\">view</a> "; + + echo "<b>Sol:</b><a href=\"../filedownload.php?". filedownload($b[$i]["soloid"],$b[$i]["solfilename"]) . "\">"; + echo $b[$i]["solfilename"] . "</a>"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($b[$i]["soloid"],$b[$i]["solfilename"]) . "', 'View$i - CORRECT OUTPUT','width=680,height=600,scrollbars=yes,". + "resizable=yes')\">view</a>"; +} +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Language</b><i> <?php echo $a["language"]; ?></i>:</td> + <td width="83%"> +<?php + if (isset($c["compilation"]) && $c["compilation"]!="") echo "<b>Compilation Line:</b> ".$c["compilation"]. "<br>"; +if (isset($c["execution"]) && $c["execution"]!="") echo "<b>Execution Line:</b> ".$c["execution"]. "<br>"; +if (isset($c["showoutput"]) && $c["showoutput"]!="") echo "<b>Showing Output Line:</b> ". $c["showoutput"]. "<br>"; + + if (isset($c["scriptname"]) && $c["scriptname"]!="") { + echo "<b>Script for judging:</b> <a href=\"../filedownload.php?". filedownload($c["scriptoid"],$c["scriptname"]) ."\">"; + echo $c["scriptname"] . "</a>"; + } +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Source code:</b></td> + <td width="83%"> +<?php +echo "<a href=\"../filedownload.php?". filedownload($a["sourceoid"], $a["sourcename"]) . "\">" . $a["sourcename"] . "</a>\n"; + echo "<a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?" . + filedownload($a["sourceoid"], $a["sourcename"]) . "', 'View - SOURCE CODE', ". + "'width=680,height=600,scrollbars=yes,resizable=yes')\">view</a>\n"; +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Answer:</b></td> + <td width="83%"> + <select name="answer"> +<?php +$ans = DBGetAnswers($_SESSION["usertable"]["contestnumber"]); +for ($i=0;$i<count($ans);$i++) + if ($a["answer"] == $ans[$i]["number"]) + echo "<option selected value=\"" . $ans[$i]["number"] . "\">" . $ans[$i]["desc"] . "</option>\n"; + else + echo "<option value=\"" . $ans[$i]["number"] . "\">" . $ans[$i]["desc"] . "</option>\n"; +?> + </select> + </td> + </tr> +<!-- + <tr> + <td width="27%" align=right><b>Notify user:</b></td> + <td width="83%"> + <input class=checkbox type=checkbox name="notifyuser" value="yes" +<?php +if (($s=DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +if ($a["timestamp"] < $s["sitelastmileanswer"]) echo "checked"; ?>> +(do not change this unless you know exactly what you are doing) + </td> + </tr> + <tr> + <td width="27%" align=right><b>Update score board:</b></td> + <td width="83%"> + <input class=checkbox type=checkbox name="updatescore" value="yes" +<?php if ($a["timestamp"] < $s["sitelastmilescore"]) echo "checked"; ?>> +(do not change this unless you know exactly what you are doing) + </td> + </tr> +--> + </table> + </center> + <br> + <script language="javascript"> + function conf() { +// if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; +// } + } + </script> + <center> + <input type="submit" name="Submit" value="Judge" onClick="conf()"> + <input type="submit" name="giveup" value="Cancel editing"> + <input type="reset" name="Submit2" value="Clear"> + +<br><br> +<!-- +<font color=#ff0000><b> +Remember to not leave the correct output files in a readable directory.<br> +A malicious source code could try to find the correct output file on the disk and copy it. +</b></font> +--> + </center> + + <center> +<br> +<b>Autojudging:</b> +<br><br> + <table border="1"> + <tr> + <td width="27%" align=right><b>Autojudging answer:</b></td> + <td width="83%"> +<?php +if($a["autobegin"]!="" && $a["autoend"]=="") + echo "in progress"; +else if($a["autoend"]!="") { + if($a["autoanswer"]!="") echo $a["autoanswer"]; + else echo "Autojudging error"; +} else + echo "unavailable"; +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Autojudged by:</b></td> +<?php if($a["autobegin"]!="" && $a["autoend"]=="") + echo "<td width=\"83%\">". $a["autoip"] ." since ". dateconvsimple($a["autobegin"]) ."</td>"; +else if($a["autoend"]!="") + echo "<td width=\"83%\">". $a["autoip"] ." from ". dateconvsimple($a["autobegin"]) ." to ". dateconvsimple($a["autoend"]) ."</td>"; +else + echo "<td width=\"83%\">unavailable</td>"; +?> + </tr> + <tr> + <td width="27%" align=right><b>Standard output:</b></td> + <td width="83%"> +<?php +if($a["autostdout"]!="") { + echo "<a href=\"../filedownload.php?". filedownload($a["autostdout"],"stdout") ."\">stdout</a>\n"; + echo "<a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($a["autostdout"],"stdout") ."', 'View - STDOUT','width=680,height=600,scrollbars=yes,". + "resizable=yes')\">view</a>\n"; +} else + echo "unavailable"; +?> +</td> + </tr> +<tr> +<td width="27%" align=right><b>Standard error:</b></td> + <td width="83%"> +<?php +if($a["autostderr"]!="") { + echo "<a href=\"../filedownload.php?". filedownload($a["autostderr"], "stderr") ."\">stderr</a>\n"; + echo "<a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($a["autostderr"], "stderr") ."', 'View - STDERR','width=680,height=600,scrollbars=yes,". + "resizable=yes')\">view</a>\n"; +} else + echo "unavailable"; +?> + </td> + </tr> + </table></center> + +</form> +</body> +</html> diff --git a/boca-1.5.0/src/judge/runeditchief.php b/boca-1.5.0/src/judge/runeditchief.php new file mode 100644 index 0000000..6395650 --- /dev/null +++ b/boca-1.5.0/src/judge/runeditchief.php @@ -0,0 +1,331 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require 'header.php'; + +if (isset($_POST["cancel"]) && $_POST["cancel"]=="Cancel editing") + ForceLoad($runphp); + +if (isset($_POST["giveup"]) && $_POST["giveup"]=="Renew" && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["number"]) && + is_numeric($_POST["sitenumber"])) { + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + if (DBGiveUpRunAutojudging($_SESSION["usertable"]["contestnumber"], $sitenumber, $number)) + MSGError("Run renewed."); + ForceLoad($runphp); +} + +if (isset($_POST["delete"]) && $_POST["delete"]=="Delete" && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["number"]) && + is_numeric($_POST["sitenumber"])) { + if ($_POST["confirmation"]=="confirm") { + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + + if (DBRunDelete($number, $sitenumber, $_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"])) + MSGError("Run deleted."); + } + ForceLoad($runphp); +} + +if (isset($_POST["answer"]) && isset($_POST["open"]) && $_POST["open"]=="Open run for rejudging" && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["number"]) && + is_numeric($_POST["sitenumber"])) { + + if ($_POST["confirmation"] == "confirm") { + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); + + DBGiveUpRunAutojudging($_SESSION["usertable"]["contestnumber"], $sitenumber, $number); + if (DBChiefRunGiveUp($_POST["number"], $_POST["sitenumber"], $_SESSION["usertable"]["contestnumber"])) + MSGError("Run returned."); + ForceLoad($runphp); + } +} + +if (isset($_POST["answer"]) && isset($_POST["Submit"]) && $_POST["Submit"]=="Judge" && is_numeric($_POST["answer"]) && + isset($_POST["sitenumber"]) && isset($_POST["number"]) && is_numeric($_POST["sitenumber"]) && + is_numeric($_POST["number"])) { // && isset($_POST["notifyuser"]) && isset($_POST["updatescore"])) { + + if ($_POST["confirmation"] == "confirm") { + $answer = myhtmlspecialchars($_POST["answer"]); + $sitenumber = myhtmlspecialchars($_POST["sitenumber"]); + $number = myhtmlspecialchars($_POST["number"]); +// $notuser = myhtmlspecialchars($_POST["notifyuser"]); +// $updscore = myhtmlspecialchars($_POST["updatescore"]); + + DBChiefUpdateRun($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], + $sitenumber, $number, $answer); //, $notuser, updscore); + } + ForceLoad($runphp); +} + +if (!isset($_GET["runnumber"]) || !isset($_GET["runsitenumber"]) || + !is_numeric($_GET["runnumber"]) || !is_numeric($_GET["runsitenumber"])) { + IntrusionNotify("tried to open the admin/runedit.php with wrong parameters."); + ForceLoad($runphp); +} + +// ??? +$runsitenumber = myhtmlspecialchars($_GET["runsitenumber"]); +$runnumber = myhtmlspecialchars($_GET["runnumber"]); + +if (($a = DBChiefGetRunToAnswer($runnumber, $runsitenumber, + $_SESSION["usertable"]["contestnumber"])) === false) { + MSGError("Another judge got it first."); + ForceLoad($runphp); +} + +$b = DBGetProblemData($_SESSION["usertable"]["contestnumber"], $a["problemnumber"]); +$c = DBGetLanguageData($_SESSION["usertable"]["contestnumber"], $a["langnumber"], $a["problemnumber"]); +?> +<br><br><center><b>Use the following fields to judge the run: +</b></center> +<form name="form1" method="post" action="<?php echo $runeditphp; ?>"> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="1"> + <tr> + <td width="27%" align=right><b>Site:</b></td> + <td width="83%"> + <input type=hidden name="sitenumber" value="<?php echo $a["sitenumber"]; ?>" /> + <?php echo $a["sitenumber"]; ?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Number:</b></td> + <td width="83%"> + <input type=hidden name="number" value="<?php echo $a["number"]; ?>" /> + <?php echo $a["number"]; ?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Time:</b></td> + <td width="83%"> + <?php echo dateconvminutes($a["timestamp"]); ?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Problem</b><i> <?php echo $a["problemname"]; ?></i>: </td> + <td width="83%"> +<?php +for ($i=0;$i<count($b);$i++) { + echo "<b>Input:</b><a href=\"../filedownload.php?". filedownload($b[$i]["inputoid"], $b[$i]["inputfilename"]) ."\">"; + echo $b[$i]["inputfilename"] . "</a>"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($b[$i]["inputoid"], $b[$i]["inputfilename"]) ."', 'View$i - INPUT','width=680,height=600,scrollbars=yes,resizable=yes')\">view</a> "; + + echo "<b>Sol:</b><a href=\"../filedownload.php?". filedownload($b[$i]["soloid"], $b[$i]["solfilename"]) . "\">"; + echo $b[$i]["solfilename"] . "</a>"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($b[$i]["soloid"], $b[$i]["solfilename"]) ."', 'View$i - CORRECT OUTPUT','width=680,height=600,scrollbars=yes,resizable=yes')\">view</a>"; +} +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Language</b><i> <?php echo $a["language"]; ?></i>:</td> + <td width="83%"> +<?php + if (isset($c["compilation"]) && $c["compilation"]!="") echo "<b>Compilation Line:</b> ".$c["compilation"]. "<br>"; + if (isset($c["execution"]) && $c["execution"]!="") echo "<b>Execution Line:</b> ".$c["execution"]. "<br>"; + if (isset($c["showoutput"]) && $c["showoutput"]!="") echo "<b>Showing Output Line:</b> ". $c["showoutput"]. "<br>"; + + if (isset($c["scriptname"]) && $c["scriptname"]!="") { + echo "<b>Script for judging:</b> <a href=\"../filedownload.php?". filedownload($c["scriptoid"], $c["scriptname"]) ."\">"; + echo $c["scriptname"] . "</a>"; + } +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Source code:</b></td> + <td width="83%"> +<?php + echo "<a href=\"../filedownload.php?". filedownload($a["sourceoid"],$a["sourcename"]) . "\">" . $a["sourcename"] . "</a>\n"; +echo "<a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?" . +filedownload($a["sourceoid"],$a["sourcename"]) ."', 'View - SOURCE', ". +"'width=680,height=600,scrollbars=yes,resizable=yes')\">view</a>\n"; +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Answer:</b></td> + <td width="83%"> + <select name="answer"> +<?php +$ans = DBGetAnswers($_SESSION["usertable"]["contestnumber"]); +//$isfak = true; +for ($i=0;$i<count($ans);$i++) + if ($a["answer"] == $ans[$i]["number"]) { +// if($ans[$i]["fake"] != "t") $isfak = false; + echo "<option selected value=\"" . $ans[$i]["number"] . "\">" . $ans[$i]["desc"] . "</option>\n"; + } else + echo "<option value=\"" . $ans[$i]["number"] . "\">" . $ans[$i]["desc"] . "</option>\n"; + echo "</select>"; +// if(!$isfak) { + if($a["judgesite"] != "" && $a["judge"] != "") { + $uu = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $a["judgesite"], $a["judge"]); + echo " [judge=" . $uu["username"] . " (" . $a["judgesite"] . ")]"; + } +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Answer 1:</b></td> + <td width="83%"> +<?php +$ans = DBGetAnswers($_SESSION["usertable"]["contestnumber"]); +for ($i=0;$i<count($ans);$i++) + if ($a["answer1"] == $ans[$i]["number"]) { +// if($ans[$i]["fake"] != "t") { + if($a["judgesite1"] != "" && $a["judge1"] != "") { + $uu = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $a["judgesite1"], $a["judge1"]); + echo $ans[$i]["desc"] . " [judge=" . $uu["username"] . " (" . $a["judgesite1"] . ")]"; + } else + echo $ans[$i]["desc"]; + } +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Answer 2:</b></td> + <td width="83%"> +<?php +$ans = DBGetAnswers($_SESSION["usertable"]["contestnumber"]); +for ($i=0;$i<count($ans);$i++) + if ($a["answer2"] == $ans[$i]["number"]) { +// if($ans[$i]["fake"] != "t") { + if($a["judgesite2"] != "" && $a["judge2"] != "") { + $uu = DBUserInfo ($_SESSION["usertable"]["contestnumber"], $a["judgesite2"], $a["judge2"]); + echo $ans[$i]["desc"] . " [judge=" . $uu["username"] . " (" . $a["judgesite2"] . ")]"; + } else + echo $ans[$i]["desc"]; + } +?> + </td> + </tr> + +<!-- + <tr> + <td width="27%" align=right><b>Notify user:</b></td> + <td width="83%"> + <input class=checkbox type=checkbox name="notifyuser" value="yes" +<?php +if (($s=DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +if ($a["timestamp"] < $s["sitelastmileanswer"]) echo "checked"; ?>> +(do not change this unless you know exactly what you are doing) + </td> + </tr> + <tr> + <td width="27%" align=right><b>Update score board:</b></td> + <td width="83%"> + <input class=checkbox type=checkbox name="updatescore" value="yes" +<?php if ($a["timestamp"] < $s["sitelastmilescore"]) echo "checked"; ?>> +(do not change this unless you know exactly what you are doing) + </td> + </tr> +--> + </table> + </center> + <br> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Judge" onClick="conf()"> + <input type="submit" name="open" value="Open run for rejudging" onClick="conf()"> + <input type="submit" name="cancel" value="Cancel editing"> + <input type="submit" name="delete" value="Delete" onClick="conf()"> + <input type="reset" name="Submit2" value="Clear"> +<br><br> + </center> + + <center> +<br> +<b>Autojudging:</b> +<input type="submit" name="giveup" value="Renew"> +<br><br> + <table border="1"> + <tr> + <td width="27%" align=right><b>Autojudging answer:</b></td> + <td width="83%"> +<?php +if($a["autobegin"]!="" && $a["autoend"]=="") + echo "in progress"; +else if($a["autoend"]!="") { + if($a["autoanswer"]!="") echo $a["autoanswer"]; + else echo "Autojudging error"; +} else + echo "unavailable"; +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Autojudged by:</b></td> +<?php if($a["autobegin"]!="" && $a["autoend"]=="") + echo "<td width=\"83%\">". $a["autoip"] ." since ". dateconvsimple($a["autobegin"]) ."</td>"; +else if($a["autoend"]!="") + echo "<td width=\"83%\">". $a["autoip"] ." from ". dateconvsimple($a["autobegin"]) ." to ". dateconvsimple($a["autoend"]) ."</td>"; +else + echo "<td width=\"83%\">unavailable</td>"; +?> + </tr> + <tr> + <td width="27%" align=right><b>Standard output:</b></td> + <td width="83%"> +<?php +if($a["autostdout"]!="") { + echo "<a href=\"../filedownload.php?".filedownload($a["autostdout"],"stdout") ."\">stdout</a>\n"; + echo "<a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($a["autostdout"],"stdout") ."', 'View - STDOUT','width=680,height=600,scrollbars=yes,". + "resizable=yes')\">view</a>\n"; +} else + echo "unavailable"; +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Standard error:</b></td> + <td width="83%"> +<?php +if($a["autostderr"]!="") { + echo "<a href=\"../filedownload.php?". filedownload($a["autostderr"],"stderr") . "\">stderr</a>\n"; + echo "<a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($a["autostderr"],"stderr") ."', 'View - STDERR','width=680,height=600,scrollbars=yes,". + "resizable=yes')\">view</a>\n"; +} else + echo "unavailable"; +?> + </td> + </tr> + </table></center> + +</form> +</body> +</html> diff --git a/boca-1.5.0/src/judge/score.php b/boca-1.5.0/src/judge/score.php new file mode 100644 index 0000000..bea0800 --- /dev/null +++ b/boca-1.5.0/src/judge/score.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +require('header.php'); +require('../scorelower.php'); +?> diff --git a/boca-1.5.0/src/judge/team.php b/boca-1.5.0/src/judge/team.php new file mode 100644 index 0000000..f00adac --- /dev/null +++ b/boca-1.5.0/src/judge/team.php @@ -0,0 +1,190 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +require('header.php'); + +if (isset($_FILES["sourcefile"]) && isset($_POST["problem"]) && isset($_POST["Submit"]) && isset($_POST["language"]) && + is_numeric($_POST["problem"]) && is_numeric($_POST["language"]) && $_FILES["sourcefile"]["name"]!="") { + if ($_POST["confirmation"] == "confirm") { + if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); + + $prob = myhtmlspecialchars($_POST["problem"]); + $lang = myhtmlspecialchars($_POST["language"]); + + $type=myhtmlspecialchars($_FILES["sourcefile"]["type"]); + $size=myhtmlspecialchars($_FILES["sourcefile"]["size"]); + $name=myhtmlspecialchars($_FILES["sourcefile"]["name"]); + $temp=myhtmlspecialchars($_FILES["sourcefile"]["tmp_name"]); + + if ($size > $ct["contestmaxfilesize"]) { + LOGLevel("User {$_SESSION["usertable"]["username"]} tried to submit file " . + "$name with $size bytes ({$ct["contestmaxfilesize"]} max allowed).", 1); + MSGError("File size exceeds the limit allowed."); + ForceLoad($runteam); + } + if (!is_uploaded_file($temp) || strlen($name)>100) { + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + + + $ac=array('contest','site','user','problem','lang','filename','filepath'); + $ac1=array('runnumber','rundate','rundatediff','rundatediffans','runanswer','runstatus','runjudge','runjudgesite', + 'runjudge1','runjudgesite1','runanswer1','runjudge2','runjudgesite2','runanswer2', + 'autoip','autobegindate','autoenddate','autoanswer','autostdout','autostderr','updatetime'); + $param = array('contest'=>$_SESSION["usertable"]["contestnumber"], + 'site'=>$_SESSION["usertable"]["usersitenumber"], + 'user'=> $_SESSION["usertable"]["usernumber"], + 'problem'=>$prob, + 'lang'=>$lang, + 'filename'=>$name, + 'filepath'=>$temp); + DBNewRun ($param); + $_SESSION['forceredo']=true; + } + ForceLoad($runteam); +} + +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +$runtmp = $_SESSION["locr"] . $ds . "private" . $ds . "runtmp" . $ds . "run-contest" . $_SESSION["usertable"]["contestnumber"] . + "-site". $_SESSION["usertable"]["usersitenumber"] . "-user" . $_SESSION["usertable"]["usernumber"] . ".php"; +$redo = TRUE; +if(!isset($_SESSION['forceredo']) || $_SESSION['forceredo']==false) { + $actualdelay = 30; + if(file_exists($runtmp)) { + if(isset($strtmp) || (($strtmp = file_get_contents($runtmp,FALSE,NULL,-1,1000000)) !== FALSE)) { + list($d) = sscanf($strtmp,"%*s %d"); + if($d > time() - $actualdelay) { + $conf=globalconf(); + $strtmp = decryptData(substr($strtmp,strpos($strtmp,"\n")+1),$conf["key"],'runtmp'); + if($strtmp !== false) + $redo = FALSE; + } + } + } +} +if($redo) { + $_SESSION['forceredo']=false; + if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + $strtmp="<br>\n<table width=\"100%\" border=1>\n <tr>\n <td><b>Run #</b></td>\n<td><b>Time</b></td>\n". + " <td><b>Problem</b></td>\n <td><b>Language</b></td>\n <td><b>Answer</b></td>\n <td><b>File</b></td>\n </tr>\n"; + $strcolors = "0"; + $run = DBUserRuns($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"]); + for ($i=0; $i<count($run); $i++) { + $strtmp .= " <tr>\n"; + $strtmp .= " <td nowrap>" . $run[$i]["number"] . "</td>\n"; + $strtmp .= " <td nowrap>" . dateconvminutes($run[$i]["timestamp"]) . "</td>\n"; + $strtmp .= " <td nowrap>" . $run[$i]["problem"] . "</td>\n"; + $strtmp .= " <td nowrap>" . $run[$i]["language"] . "</td>\n"; +// $strtmp .= " <td nowrap>" . $run[$i]["status"] . "</td>\n"; + if (trim($run[$i]["answer"]) == "") { + $run[$i]["answer"] = "Not answered yet"; + $strtmp .= " <td>Not answered yet"; + } + else { + $strtmp .= " <td>" . $run[$i]["answer"]; + if($run[$i]['yes']=='t') { + $strtmp .= " <img alt=\"".$run[$i]["colorname"]."\" width=\"15\" ". + "src=\"" . balloonurl($run[$i]["color"]) ."\" />"; + $strcolors .= "\t" . $run[$i]["colorname"] . "\t" . $run[$i]["color"]; + } + } + $strtmp .= "</td>\n"; + $strtmp .= "<td nowrap><a href=\"../filedownload.php?" . filedownload($run[$i]["oid"],$run[$i]["filename"]) . "\">"; + $strtmp .= $run[$i]["filename"] . "</a>"; + + $strtmp .= "</td>\n"; + + $strtmp .= " </tr>\n"; + + if ($run[$i]["anstime"]>$_SESSION["usertable"]["userlastlogin"]-$st["sitestartdate"] && $run[$i]["anstime"] < $st['sitelastmileanswer'] && + $run[$i]["ansfake"]!="t" && !isset($_SESSION["popups"]['run' . $i . '-' . $run[$i]["anstime"]])) { + $_SESSION["popups"]['run' . $i . '-' . $run[$i]["anstime"]] = "Run ".$run[$i]["number"]." result: ".$run[$i]["answer"]. "<br>"; + } + } +$strtmp .= "</table>"; +if (count($run) == 0) $strtmp .= "<br><center><b><font color=\"#ff0000\">NO RUNS AVAILABLE</font></b></center>"; + +$strtmp .= "<br><br><center><b>To submit a program, just fill in the following fields:</b></center>\n". +"<form name=\"form1\" enctype=\"multipart/form-data\" method=\"post\" action=\"". $runteam ."\">\n". +" <input type=hidden name=\"confirmation\" value=\"noconfirm\" />\n". +" <center>\n". +" <table border=\"0\">\n". +" <tr> \n". +" <td width=\"25%\" align=right>Problem:</td>\n". +" <td width=\"75%\">\n". +" <select name=\"problem\" onclick=\"Arquivo()\">\n"; +$prob = DBGetProblems($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usertype"]=='judge'); +for ($i=0;$i<count($prob);$i++) + $strtmp .= "<option value=\"" . $prob[$i]["number"] . "\">" . $prob[$i]["problem"] . "</option>\n"; +$strtmp .= " </select>\n". +" </td>\n". +" </tr>\n". +" <tr> \n". +" <td width=\"25%\" align=right>Language:</td>\n". +" <td width=\"75%\"> \n". +" <select name=\"language\" onclick=\"Arquivo()\">\n"; +$lang = DBGetLanguages($_SESSION["usertable"]["contestnumber"]); +for ($i=0;$i<count($lang);$i++) + $strtmp .= "<option value=\"" . $lang[$i]["number"] . "\">" . $lang[$i]["name"] . "</option>\n"; +$strtmp .= " </select>\n". +" </td>\n". +" </tr>\n". +" <tr> \n". +" <td width=\"25%\" align=right>Source code:</td>\n". +" <td width=\"75%\">\n". +" <input type=\"file\" name=\"sourcefile\" size=\"40\" onclick=\"Arquivo()\">\n". +" </td>\n". +" </tr>\n". +" </table>\n". +" </center>\n". +" <script language=\"javascript\">\n". +" function conf() {\n". +" if (confirm(\"Confirm submission?\")) {\n". +" document.form1.confirmation.value='confirm';\n". +" }\n". +" }\n". +" </script>\n". +" <center>\n". +" <input type=\"submit\" name=\"Submit\" value=\"Send\" onClick=\"conf()\">\n". +" <input type=\"reset\" name=\"Submit2\" value=\"Clear\">\n". +" </center>\n". +"</form>\n"; + $conf=globalconf(); + $strtmp1 = "<!-- " . time() . " --> <?php exit; ?>\t" . encryptData($strcolors,$conf["key"],false) . "\n" . encryptData($strtmp,$conf["key"],false); + $randnum = session_id() . "_" . rand(); + if(file_put_contents($runtmp . "_" . $randnum, $strtmp1,LOCK_EX)===FALSE) { + if(!isset($_SESSION['writewarn'])) { + LOGError("Cannot write to the user-run cache file $runtmp -- performance might be compromised"); + $_SESSION['writewarn']=true; + } + } + @rename($runtmp . "_" . $randnum, $runtmp); +} +echo $strtmp; +?> + + +</body> +</html> diff --git a/boca-1.5.0/src/libchart/COPYING b/boca-1.5.0/src/libchart/COPYING new file mode 100644 index 0000000..2d2d780 --- /dev/null +++ b/boca-1.5.0/src/libchart/COPYING @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + <one line to give the library's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + <signature of Ty Coon>, 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/boca-1.5.0/src/libchart/ChangeLog b/boca-1.5.0/src/libchart/ChangeLog new file mode 100644 index 0000000..fe6e492 --- /dev/null +++ b/boca-1.5.0/src/libchart/ChangeLog @@ -0,0 +1,24 @@ +Libchart ChangeLog +================== +(C) 2005-2006 Jean-Marc Trémeaux + + +VERSION 1.1: (2006-04-02) +========== + CHANGES: + * Added Line Charts + * Bar Chart: default lower bound set to value 0 (seems more intuitive). + Use $chart->setLowerBound(null) if you want to revert to the old behaviour. + + BUGFIXES: + * Removed undefined IMG_ARC_FILL constant + * Added missing default parameter in HorizontalChart::render() + * Fixed decimal values in Bar Charts + * Typo in default logo + * Crashed when no point was defined + * Crashed when all values were set to 0 + +Version 1.0: (2005-09-30) +========== + INITIAL RELEASE + diff --git a/boca-1.5.0/src/libchart/README b/boca-1.5.0/src/libchart/README new file mode 100644 index 0000000..0d9500e --- /dev/null +++ b/boca-1.5.0/src/libchart/README @@ -0,0 +1,45 @@ + + Libchart - Simple PHP chart drawing library +============================================= + +Libchart is a free chart creation PHP library, that is easy to use. + +-------------------------------------------------------------------------------- + + + Features +========== + + * Bar charts (horizontal or vertical). + * Pie charts. + * Compatibility with PHP 4 / PHP 5. + +-------------------------------------------------------------------------------- + + + Dependencies +============== + + * PHP 4 or PHP 5, compiled with: + * GD 2+ + * FreeType 2+ + +-------------------------------------------------------------------------------- + + + Installation +============== + +In order to use Libchart, unpack the archive in you project directory and +include libchart.php. Please have a look at the demo files for more information. +There is also a tutorial available at the project homepage. + + +-------------------------------------------------------------------------------- + + + Contact info +============== + +WWW: http://naku.dohcrew.com/libchart/ +MAIL: jm.tremeaux at gmail dot com diff --git a/boca-1.5.0/src/libchart/classes/Axis.php b/boca-1.5.0/src/libchart/classes/Axis.php new file mode 100644 index 0000000..c80fe97 --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/Axis.php @@ -0,0 +1,167 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /** + * Automatic axis boundaries and ticks calibration + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + */ + + class Axis + { + /** + * Creates a new axis formatter + * + * @access public + * @param integer minimum value on the axis + * @param integer maximum value on the axis + */ + + function Axis($min, $max) + { + $this->min = $min; + $this->max = $max; + + $this->guide = 10; + } + + /** + * Computes value between two ticks + * + * @access private + */ + + function quantizeTics() + { + // Approximate number of decades, in [1..10[ + + $norm = $this->delta / $this->magnitude; + + // Approximate number of tics per decade + + $posns = $this->guide / $norm; + + if ($posns > 20) + $tics = 0.05; // e.g. 0, .05, .10, ... + else + if ($posns > 10) + $tics = 0.2; // e.g. 0, .1, .2, ... + else + if ($posns > 5) + $tics = 0.4; // e.g. 0, 0.2, 0.4, ... + else + if ($posns > 3) + $tics = 0.5; // e.g. 0, 0.5, 1, ... + else + if ($posns > 2) + $tics = 1; // e.g. 0, 1, 2, ... + else + if ($posns > 0.25) + $tics = 2; // e.g. 0, 2, 4, 6 + else + $tics = ceil($norm); + + $this->tics = $tics * $this->magnitude; + } + + /** + * Computes automatic boundaries on the axis + * + * @access public + */ + + function computeBoundaries() + { + // Range + + $this->delta = abs($this->max - $this->min); + + // Check for null distribution + + if($this->delta == 0) + $this->delta = 1; + + // Order of magnitude of range + + $this->magnitude = pow(10, floor(log10($this->delta))); + + $this->quantizeTics(); + + $this->displayMin = floor($this->min / $this->tics) * $this->tics; + $this->displayMax = ceil($this->max / $this->tics) * $this->tics; + $this->displayDelta = $this->displayMax - $this->displayMin; + + // Check for null distribution + + if($this->displayDelta == 0) + $this->displayDelta = 1; + } + + /** + * Set boundaries on the axis. Theses values override the automatic values. + * + * @access public + */ + + function setBoundaries($sampleCount, $yMinValue, $yMaxValue) + { + $this->sampleCount = $sampleCount; + $this->yMinValue = $yMinValue; + $this->yMaxValue = $yMaxValue; + } + + /** + * Get the lower boundary on the axis + * + * @access public + * @return integer lower boundary on the axis + */ + + function getLowerBoundary() + { + return $this->displayMin; + } + + /** + * Get the upper boundary on the axis + * + * @access public + * @return integer upper boundary on the axis + */ + + function getUpperBoundary() + { + return $this->displayMax; + } + + /** + * Get the value between two ticks + * + * @access public + * @return integer value between two ticks + */ + + function getTics() + { + return $this->tics; + } + } +?> diff --git a/boca-1.5.0/src/libchart/classes/BarChart.php b/boca-1.5.0/src/libchart/classes/BarChart.php new file mode 100644 index 0000000..5b658ca --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/BarChart.php @@ -0,0 +1,172 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /** + * Base bar chart class (horizontal or vertical) + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * @abstract + */ + + class BarChart extends Chart + { + /** + * Creates a new bar chart + * + * @access protected + * @param integer width of the image + * @param integer height of the image + */ + + function BarChart($width, $height) + { + parent::Chart($width, $height); + + $this->setMargin(5); + $this->setLowerBound(0); + } + + /** + * Compute the boundaries on the axis + * + * @access protected + */ + + function computeBound() + { + // Compute lower and upper bound on the value axis + + $point = current($this->point); + + // Check if some points were defined + + if(!$point) + { + $yMin = 0; + $yMax = 1; + } + else + { + $yMax = $yMin = $point->getY(); + + foreach($this->point as $point) + { + $y = $point->getY(); + + if($y < $yMin) + $yMin = $y; + + if($y > $yMax) + $yMax = $y; + } + } + + $this->yMinValue = isset($this->lowerBound) ? $this->lowerBound : $yMin; + $this->yMaxValue = isset($this->upperBound) ? $this->upperBound : $yMax; + + // Compute boundaries on the sample axis + + $this->sampleCount = count($this->point); + } + + /** + * Set manually the lower boundary value (overrides the automatic formatting) + * Typical usage is to set the bars starting from zero + * + * @access public + * @param double lower boundary value + */ + + function setLowerBound($lowerBound) + { + $this->lowerBound = $lowerBound; + } + + /** + * Set manually the upper boundary value (overrides the automatic formatting) + * + * @access public + * @param double upper boundary value + */ + + function setUpperBound($upperBound) + { + $this->upperBound = $upperBound; + } + + /** + * Compute the image layout + * + * @access protected + */ + + function computeLabelMargin() + { + $this->axis = new Axis($this->yMinValue, $this->yMaxValue); + $this->axis->computeBoundaries(); + + $this->graphTLX = $this->margin + $this->labelMarginLeft; + $this->graphTLY = $this->margin + $this->labelMarginTop; + $this->graphBRX = $this->width - $this->margin - $this->labelMarginRight; + $this->graphBRY = $this->height - $this->margin - $this->labelMarginBottom; + } + + /** + * Create the image + * + * @access protected + */ + + function createImage() + { + parent::createImage(); + + $this->axisColor1 = new Color(201, 201, 201); + $this->axisColor2 = new Color(158, 158, 158); + + $this->aquaColor1 = new Color(242, 242, 242); + $this->aquaColor2 = new Color(231, 231, 231); + $this->aquaColor3 = new Color(239, 239, 239); + $this->aquaColor4 = new Color(253, 253, 253); + + $this->barColor1 = new Color(42, 71, 181); + $this->barColor2 = new Color(33, 56, 143); + + $this->barColor3 = new Color(172, 172, 210); + $this->barColor4 = new Color(117, 117, 143); + + // Aqua-like background + + $aquaColor = Array($this->aquaColor1, $this->aquaColor2, $this->aquaColor3, $this->aquaColor4); + + for($i = $this->graphTLY; $i < $this->graphBRY; $i++) + { + $color = $aquaColor[($i + 3) % 4]; + $this->primitive->line($this->graphTLX, $i, $this->graphBRX, $i, $color); + } + + // Axis + + imagerectangle($this->img, $this->graphTLX - 1, $this->graphTLY, $this->graphTLX, $this->graphBRY, $this->axisColor1->getColor($this->img)); + imagerectangle($this->img, $this->graphTLX - 1, $this->graphBRY, $this->graphBRX, $this->graphBRY + 1, $this->axisColor1->getColor($this->img)); + } + } +?> diff --git a/boca-1.5.0/src/libchart/classes/Chart.php b/boca-1.5.0/src/libchart/classes/Chart.php new file mode 100644 index 0000000..639eabd --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/Chart.php @@ -0,0 +1,213 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /*! \mainpage Libchart + * + * This is the reference API, automatically compiled by <a href="http://www.stack.nl/~dimitri/doxygen/">Doxygen</a>. + * You can find here information that is not covered by the <a href="../samplecode/">tutorial</a>. + * + */ + + /** + * Base chart class + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * @abstract + */ + + class Chart + { + /** + * Creates a new chart + * + * @access protected + * @param integer width of the image + * @param integer height of the image + */ + + function chart($width, $height) + { + $this->width = $width; + $this->height = $height; + + $this->reset(); + } + + /** + * Initialize the chart + * + * @access private + */ + + function reset() + { + $this->text = new Text(); + $this->point = array(); + + unset($this->lowerBound); + unset($this->upperBound); + + $this->setTitle("Untitled chart"); + $this->setLogo(dirname(__FILE__) . "/../images/PoweredBy.png"); + } + + /** + * Add a new sampling point to the chart + * + * @access public + * @param Point sampling point to add + */ + + function addPoint($point) + { + array_push($this->point, $point); + } + + /** + * Sets the title + * + * @access public + * @param string new title + */ + + function setTitle($title) + { + $this->title = $title; + } + + /** + * Sets the logo image file name + * + * @access public + * @param string new logo image file name + */ + + function setLogo($logoFileName) + { + $this->logoFileName = $logoFileName; + } + + /** + * Print the title to the image + * + * @access private + */ + + function printTitle() + { + $this->text->printCentered($this->img, ($this->labelMarginTop + $this->margin) / 2, $this->textColor, $this->title, $this->text->fontCondensedBold); + } + + /** + * Print the logo image to the image + * + * @access private + */ + + function printLogo() + { + @$logoImage = imageCreateFromPNG($this->logoFileName); + + if($logoImage) + imagecopymerge($this->img, $logoImage, 2*$this->margin, $this->margin, 0, 0, imagesx($logoImage), imagesy($logoImage), 100); + } + + /** + * Set the outer margin + * + * @access public + * @param integer outer margin value in pixels + */ + + function setMargin($margin) + { + $this->margin = $margin; + } + + /** + * Set the label left margin + * + * @access public + * @param integer label left margin value in pixels + */ + + function setLabelMarginLeft($labelMarginLeft) + { + $this->labelMarginLeft = $labelMarginLeft; + } + + /** + * Set the label right margin + * + * @access public + * @param integer label right margin value in pixels + */ + + function setLabelMarginRight($labelMarginRight) + { + $this->labelMarginRight = $labelMarginRight; + } + + /** + * Set the label top margin + * + * @access public + * @param integer label top margin value in pixels + */ + + function setLabelMarginTop($labelMarginTop) + { + $this->labelMarginTop = $labelMarginTop; + } + + /** + * Set the label bottom margin + * + * @access public + * @param integer label bottom margin value in pixels + */ + + function setLabelMarginBottom($labelMarginBottom) + { + $this->labelMarginBottom = $labelMarginBottom; + } + + /** + * Creates and initialize the image + * + * @access protected + */ + + function createImage() + { + $this->img = imagecreatetruecolor($this->width, $this->height); + + $this->primitive = new Primitive($this->img); + + $this->backGroundColor = new Color(255, 255, 255); + $this->textColor = new Color(0, 0, 0); + + // White background + + imagefilledrectangle($this->img, 0, 0, $this->width - 1, $this->height - 1, $this->backGroundColor->getColor($this->img)); + } + } +?> diff --git a/boca-1.5.0/src/libchart/classes/Color.php b/boca-1.5.0/src/libchart/classes/Color.php new file mode 100644 index 0000000..178435b --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/Color.php @@ -0,0 +1,74 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /** + * Color + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + */ + + class Color + { + /** + * Creates a new color + * + * @access public + * @param integer red [0,255] + * @param integer green [0,255] + * @param integer blue [0,255] + * @param integer alpha [0,255] + */ + + function Color($red, $green, $blue, $alpha = 0) + { + $this->red = (int)$red; + $this->green = (int)$green; + $this->blue = (int)$blue; + $this->alpha = (int)round($alpha * 127.0 / 255); + + $this->gdColor = null; + } + + /** + * Get GD color + * + * @access public + * @param $img GD image resource + */ + + function getColor($img) + { + // Checks if color has already been allocated + + if(!$this->gdColor) + { + if($this->alpha == 0 || !function_exists('imagecolorallocatealpha')) + $this->gdColor = imagecolorallocate($img, $this->red, $this->green, $this->blue); + else + $this->gdColor = imagecolorallocatealpha($img, $this->red, $this->green, $this->blue, $this->alpha); + } + + // Returns GD color + + return $this->gdColor; + } + } +?> diff --git a/boca-1.5.0/src/libchart/classes/HorizontalChart.php b/boca-1.5.0/src/libchart/classes/HorizontalChart.php new file mode 100644 index 0000000..4b4e069 --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/HorizontalChart.php @@ -0,0 +1,169 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /** + * Horizontal bar chart + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + */ + + class HorizontalChart extends BarChart + { + /** + * Creates a new horizontal bar chart + * + * @access public + * @param integer width of the image + * @param integer height of the image + */ + + function HorizontalChart($width = 600, $height = 250) + { + parent::BarChart($width, $height); + + $this->setLabelMarginLeft(150); + $this->setLabelMarginRight(30); + $this->setLabelMarginTop(40); + $this->setLabelMarginBottom(30); + } + + /** + * Print the axis + * + * @access private + */ + + function printAxis() + { + // Check if some points were defined + + if(!$this->sampleCount) + return; + + $minValue = $this->axis->getLowerBoundary(); + $maxValue = $this->axis->getUpperBoundary(); + $stepValue = $this->axis->getTics(); + + // Horizontal axis + + for($value = $minValue; $value <= $maxValue; $value += $stepValue) + { + $x = $this->graphTLX + ($value - $minValue) * ($this->graphBRX - $this->graphTLX) / ($this->axis->displayDelta); + + imagerectangle($this->img, $x - 1, $this->graphBRY + 2, $x, $this->graphBRY + 3, $this->axisColor1->getColor($this->img)); + imagerectangle($this->img, $x - 1, $this->graphBRY, $x, $this->graphBRY + 1, $this->axisColor2->getColor($this->img)); + + $this->text->printText($this->img, $x, $this->graphBRY + 5, $this->textColor, $value, $this->text->fontCondensed, $this->text->HORIZONTAL_CENTER_ALIGN); + } + + // Vertical Axis + + $rowHeight = ($this->graphBRY - $this->graphTLY) / $this->sampleCount; + + reset($this->point); + + for($i = 0; $i <= $this->sampleCount; $i++) + { + $y = $this->graphBRY - $i * $rowHeight; + + imagerectangle($this->img, $this->graphTLX - 3, $y, $this->graphTLX - 2, $y + 1, $this->axisColor1->getColor($this->img)); + imagerectangle($this->img, $this->graphTLX - 1, $y, $this->graphTLX, $y + 1, $this->axisColor2->getColor($this->img)); + + if($i < $this->sampleCount) + { + $point = current($this->point); + next($this->point); + + $text = $point->getX(); + + $this->text->printText($this->img, $this->graphTLX - 5, $y - $rowHeight / 2, $this->textColor, $text, $this->text->fontCondensed, $this->text->HORIZONTAL_RIGHT_ALIGN | $this->text->VERTICAL_CENTER_ALIGN); + } + } + } + + /** + * Print the bars + * + * @access private + */ + + function printBar() + { + // Check if some points were defined + + if(!$this->sampleCount) + return; + + reset($this->point); + + $minValue = $this->axis->getLowerBoundary(); + $maxValue = $this->axis->getUpperBoundary(); + $stepValue = $this->axis->getTics(); + + $rowHeight = ($this->graphBRY - $this->graphTLY) / $this->sampleCount; + + for($i = 0; $i < $this->sampleCount; $i++) + { + $y = $this->graphBRY - $i * $rowHeight; + + $point = current($this->point); + next($this->point); + + $value = $point->getY(); + + $xmax = $this->graphTLX + ($value - $minValue) * ($this->graphBRX - $this->graphTLX) / ($this->axis->displayDelta); + + $this->text->printText($this->img, $xmax + 5, $y - $rowHeight / 2, $this->textColor, $value, $this->text->fontCondensed, $this->text->VERTICAL_CENTER_ALIGN); + + // Horizontal bar + + $y1 = $y - $rowHeight * 4 / 5; + $y2 = $y - $rowHeight * 1 / 5; + + imagefilledrectangle($this->img, $this->graphTLX + 1, $y1, $xmax, $y2, $this->barColor2->getColor($this->img)); + imagefilledrectangle($this->img, $this->graphTLX + 2, $y1+1, $xmax - 4, $y2, $this->barColor1->getColor($this->img)); + } + } + + /** + * Render the chart image + * + * @access public + * @param string name of the file to render the image to (optional) + */ + + function render($fileName = null) + { + $this->computeBound(); + $this->computeLabelMargin(); + $this->createImage(); + $this->printLogo(); + $this->printTitle(); + $this->printAxis(); + $this->printBar(); + + if(isset($fileName)) + imagepng($this->img, $fileName); + else + imagepng($this->img); + } + } +?> diff --git a/boca-1.5.0/src/libchart/classes/LineChart.php b/boca-1.5.0/src/libchart/classes/LineChart.php new file mode 100644 index 0000000..9d44eba --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/LineChart.php @@ -0,0 +1,171 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /** + * Line chart + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + */ + + class LineChart extends BarChart + { + /** + * Creates a new line chart + * + * @access public + * @param integer width of the image + * @param integer height of the image + */ + + function LineChart($width = 600, $height = 250) + { + parent::BarChart($width, $height); + + $this->setLabelMarginLeft(50); + $this->setLabelMarginRight(50); + $this->setLabelMarginTop(40); + $this->setLabelMarginBottom(50); + } + + /** + * Print the axis + * + * @access private + */ + + function printAxis() + { + // Check if some points were defined + + if($this->sampleCount < 2) + return; + + $minValue = $this->axis->getLowerBoundary(); + $maxValue = $this->axis->getUpperBoundary(); + $stepValue = $this->axis->getTics(); + + // Line axis + + for($value = $minValue; $value <= $maxValue; $value += $stepValue) + { + $y = $this->graphBRY - ($value - $minValue) * ($this->graphBRY - $this->graphTLY) / ($this->axis->displayDelta); + + imagerectangle($this->img, $this->graphTLX - 3, $y, $this->graphTLX - 2, $y + 1, $this->axisColor1->getColor($this->img)); + imagerectangle($this->img, $this->graphTLX - 1, $y, $this->graphTLX, $y + 1, $this->axisColor2->getColor($this->img)); + + $this->text->printText($this->img, $this->graphTLX - 5, $y, $this->textColor, $value, $this->text->fontCondensed, $this->text->HORIZONTAL_RIGHT_ALIGN | $this->text->VERTICAL_CENTER_ALIGN); + } + + // Horizontal Axis + + $columnWidth = ($this->graphBRX - $this->graphTLX) / ($this->sampleCount - 1); + + reset($this->point); + + for($i = 0; $i < $this->sampleCount; $i++) + { + $x = $this->graphTLX + $i * $columnWidth; + + imagerectangle($this->img, $x - 1, $this->graphBRY + 2, $x, $this->graphBRY + 3, $this->axisColor1->getColor($this->img)); + imagerectangle($this->img, $x - 1, $this->graphBRY, $x, $this->graphBRY + 1, $this->axisColor2->getColor($this->img)); + + $point = current($this->point); + next($this->point); + + $text = $point->getX(); + + $this->text->printDiagonal($this->img, $x - 5, $this->graphBRY + 10, $this->textColor, $text); + } + } + + /** + * Print the lines + * + * @access private + */ + + function printLine() + { + // Check if some points were defined + + if($this->sampleCount < 2) + return; + + reset($this->point); + + $minValue = $this->axis->getLowerBoundary(); + $maxValue = $this->axis->getUpperBoundary(); + + $columnWidth = ($this->graphBRX - $this->graphTLX) / ($this->sampleCount - 1); + + $x1 = null; + $y1 = null; + + for($i = 0; $i < $this->sampleCount; $i++) + { + $x2 = $this->graphTLX + $i * $columnWidth; + + $point = current($this->point); + next($this->point); + + $value = $point->getY(); + + $y2 = $this->graphBRY - ($value - $minValue) * ($this->graphBRY - $this->graphTLY) / ($this->axis->displayDelta); + +// $this->text->printText($this->img, $x2, $y2 - 5, $this->textColor, $value, $this->text->fontCondensed, $this->text->HORIZONTAL_CENTER_ALIGN | $this->text->VERTICAL_BOTTOM_ALIGN); + + // Draw line + + if($x1) + { + $this->primitive->line($x1, $y1, $x2, $y2, $this->barColor4, 4); + $this->primitive->line($x1, $y1 - 1, $x2, $y2 - 1, $this->barColor3, 2); + } + + $x1 = $x2; + $y1 = $y2; + } + } + + /** + * Render the chart image + * + * @access public + * @param string name of the file to render the image to (optional) + */ + + function render($fileName = null) + { + $this->computeBound(); + $this->computeLabelMargin(); + $this->createImage(); + $this->printLogo(); + $this->printTitle(); + $this->printAxis(); + $this->printLine(); + + if(isset($fileName)) + imagepng($this->img, $fileName); + else + imagepng($this->img); + } + } +?> diff --git a/boca-1.5.0/src/libchart/classes/PieChart.php b/boca-1.5.0/src/libchart/classes/PieChart.php new file mode 100644 index 0000000..dacbf2b --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/PieChart.php @@ -0,0 +1,386 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /** + * Pie chart + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + */ + + class PieChart extends Chart + { + /** + * Creates a new pie chart + * + * @access public + * @param integer width of the image + * @param integer height of the image + */ + + function PieChart($width = 600, $height = 250) + { + parent::Chart($width, $height); + + $this->setMargin(5); + $this->setLabelMarginLeft(30); + $this->setLabelMarginRight(30); + $this->setLabelMarginTop(50); + $this->setLabelMarginBottom(30); + $this->setLabelMarginCenter(20); + + $this->setPieRatio(0.55); + + $this->labelBoxWidth = 15; + $this->labelBoxHeight = 15; + } + + /** + * Set the ratio of the pie image over the legend + * + * @access public + * @param double ratio (value between 0 and 1) + */ + + function setPieRatio($pieRatio) + { + $this->pieRatio = $pieRatio; + } + + /** + * Compare two sampling point values, order from biggest to lowest value + * + * @access private + * @param double first value + * @param double second value + * @return integer result of the comparison + */ + + function sortPie($v1, $v2) + { + return $v1[0] == $v2[0] ? 0 : + $v1[0] > $v2[0] ? -1 : + 1; + } + + /** + * Compute pie values in percentage and sort them + * + * @access private + */ + + function computePercent() + { + $this->total = 0; + $this->percent = array(); + + foreach($this->point as $point) + $this->total += $point->getY(); + + foreach($this->point as $point) + { + $percent = $this->total == 0 ? 0 : 100 * $point->getY() / $this->total; + + array_push($this->percent, array($percent, $point)); + } + if($this->order) + usort($this->percent, array("PieChart", "sortPie")); + } + + /** + * Set the margin between the pie image and the legend + * + * @access public + * @param integer margin value in pixels + */ + + function setLabelMarginCenter($labelMarginCenter) + { + $this->labelMarginCenter = $labelMarginCenter; + } + + /** + * Draw a gray box with nice borders + * + * @access private + * @param integer top left coordinate (x) + * @param integer top left coordinate (y) + * @param integer bottom right coordinate (x) + * @param integer bottom right coordinate (y) + */ + + function outlinedBox($x1, $y1, $x2, $y2) + { + imagefilledrectangle($this->img, $x1, $y1, $x2, $y2, $this->axisColor1->getColor($this->img)); + imagerectangle($this->img, $x1, $y1, $x1 + 1, $y1 + 1, $this->axisColor2->getColor($this->img)); + imagerectangle($this->img, $x2 - 1, $y1, $x2, $y1 + 1, $this->axisColor2->getColor($this->img)); + imagerectangle($this->img, $x1, $y2 - 1, $x1 + 1, $y2, $this->axisColor2->getColor($this->img)); + imagerectangle($this->img, $x2 - 1, $y2 - 1, $x2, $y2, $this->axisColor2->getColor($this->img)); + } + + /** + * Compute image layout + * + * @access private + */ + + function computeLabelMargin() + { + $graphWidth = $this->width - $this->margin * 2 - $this->labelMarginLeft - $this->labelMarginCenter - $this->labelMarginRight; + + $this->pieTLX = $this->margin + $this->labelMarginLeft; + $this->pieTLY = $this->margin + $this->labelMarginTop; + $this->pieBRX = $this->pieTLX + $graphWidth * $this->pieRatio; + $this->pieBRY = $this->height - $this->margin - $this->labelMarginBottom; + + $this->pieCenterX = $this->pieTLX + ($this->pieBRX - $this->pieTLX) / 2; + $this->pieCenterY = $this->pieTLY + ($this->pieBRY - $this->pieTLY) / 2; + + $this->pieWidth = round(($this->pieBRX - $this->pieTLX) * 4 / 5); + $this->pieHeight = round(($this->pieBRY - $this->pieTLY) * 3.7 / 5); + $this->pieDepth = round($this->pieWidth * 0.05); + + $this->labelTLX = $this->pieBRX + $this->labelMarginCenter; + $this->labelTLY = $this->pieTLY; + $this->labelBRX = $this->pieTLX + $this->labelMarginCenter + $graphWidth; + $this->labelBRY = $this->pieBRY; + + } + + /** + * Creates the pie chart image + * + * @access private + */ + + function createImage() + { + parent::createImage(); + + $pieColors = array( + array(2, 78, 0), + array(148, 170, 36), + array(233, 191, 49), + array(240, 127, 41), + array(243, 63, 34), + array(190, 71, 47), + array(135, 81, 60), + array(128, 78, 162), + array(121, 75, 255), + array(142, 165, 250), + array(162, 254, 239), + array(137, 240, 166), + array(104, 221, 71), + array(98, 174, 35), + array(93, 129, 1) + ); + + $this->pieColor = array(); + $this->pieShadowColor = array(); + $shadowFactor = 0.5; + + foreach($pieColors as $colorRGB) + { + list($red, $green, $blue) = $colorRGB; + + $color = new Color($red, $green, $blue); + $shadowColor = new Color($red * $shadowFactor, + $green * $shadowFactor, + $blue * $shadowFactor); + + array_push($this->pieColor, $color); + array_push($this->pieShadowColor, $shadowColor); + } + + $this->axisColor1 = new Color(201, 201, 201); + $this->axisColor2 = new Color(158, 158, 158); + + $this->aquaColor1 = new Color(242, 242, 242); + $this->aquaColor2 = new Color(231, 231, 231); + $this->aquaColor3 = new Color(239, 239, 239); + $this->aquaColor4 = new Color(253, 253, 253); + + // Legend box + + $this->outlinedBox($this->pieTLX, $this->pieTLY, $this->pieBRX, $this->pieBRY); + + // Aqua-like background + + $aquaColor = Array($this->aquaColor1, $this->aquaColor2, $this->aquaColor3, $this->aquaColor4); + + for($i = $this->pieTLY + 2; $i < $this->pieBRY - 1; $i++) + { + $color = $aquaColor[($i + 3) % 4]; + $this->primitive->line($this->pieTLX + 2, $i, $this->pieBRX - 2, $i, $color); + } + } + + /** + * Print legend + * + * @access private + */ + + function printLabel() + { + $i = 0; + + $boxX1 = $this->labelTLX + $this->margin; + $boxX2 = $boxX1 + $this->labelBoxWidth; + + foreach($this->percent as $a) + { + list($percent, $point) = $a; + $legend = $point->getX(); + + if($point->getColor() != null) + $color = $point->getColor(); + else + $color = $this->pieColor[$i % count($this->pieColor)]; + + $boxY1 = $this->labelTLY + $this->margin + $i * ($this->labelBoxHeight + $this->margin); + $boxY2 = $boxY1 + $this->labelBoxHeight; + + $this->outlinedBox($boxX1, $boxY1, $boxX2, $boxY2); + imagefilledrectangle($this->img, $boxX1 + 2, $boxY1 + 2, $boxX2 - 2, $boxY2 - 2, $color->getColor($this->img)); + + $this->text->printText($this->img, $boxX2 + $this->margin, $boxY1 + $this->labelBoxHeight / 2, $this->textColor, $legend, $this->text->fontCondensed, $this->text->VERTICAL_CENTER_ALIGN); + + $i++; + } + } + + /** + * Draw a 2D disc + * + * @access private + * @param integer center coordinate (y) + * @param array colors for each portion + * @param bitfield drawing mode + */ + + function drawDisc($cy, $colorArray, $mode, $shad=false) + { + $i = 0; + $angle1 = 0; + $percentTotal = 0; + + foreach($this->percent as $a) + { + list($percent, $point) = $a; + + if($point->getColor() != null) + $color = $shad ? $point->getShadowColor() : $point->getColor(); + else + $color = $colorArray[$i % count($colorArray)]; + + $percentTotal += $percent; + $angle2 = $percentTotal * 360 / 100; + + imagefilledarc($this->img, $this->pieCenterX, $cy, $this->pieWidth, $this->pieHeight, $angle1, $angle2, $color->getColor($this->img), $mode); + + $angle1 = $angle2; + + $i++; + } + } + + /** + * Print the percentage text + * + * @access private + */ + + function drawPercent() + { + $angle1 = 0; + $percentTotal = 0; + + foreach($this->percent as $a) + { + list($percent, $point) = $a; + + // If value is null, don't print percentage + + if($percent <= 0) + continue; + + $percentTotal += $percent; + $angle2 = $percentTotal * 2 * M_PI / 100; + + $angle = $angle1 + ($angle2 - $angle1) / 2; + $text = number_format($percent) . "%"; + + $x = cos($angle) * ($this->pieWidth + 35) / 2 + $this->pieCenterX; + $y = sin($angle) * ($this->pieHeight + 35) / 2 + $this->pieCenterY; + + $this->text->printText($this->img, $x, $y, $this->textColor, $text, $this->text->fontCondensed, $this->text->HORIZONTAL_CENTER_ALIGN | $this->text->VERTICAL_CENTER_ALIGN); + + $angle1 = $angle2; + } + } + + /** + * Print the pie chart + * + * @access private + */ + + function printPie() + { + // Silhouette + + for ($cy = $this->pieCenterY + $this->pieDepth / 2; $cy >= $this->pieCenterY - $this->pieDepth / 2; $cy--) + $this->drawDisc($cy, $this->pieShadowColor, IMG_ARC_EDGED, true); + + + // Top + + $this->drawDisc($this->pieCenterY - $this->pieDepth / 2, $this->pieColor, IMG_ARC_PIE); + + // Top Outline + + $this->drawPercent(); + } + + /** + * Render the chart image + * + * @access public + * @param string name of the file to render the image to (optional) + */ + + function render($fileName = null) + { + $this->computeLabelMargin(); + $this->computePercent(); + $this->createImage(); + $this->printLogo(); + $this->printTitle(); + $this->printPie(); + $this->printLabel(); + + if(isset($fileName)) + imagepng($this->img, $fileName); + else + imagepng($this->img); + } + } +?> diff --git a/boca-1.5.0/src/libchart/classes/Point.php b/boca-1.5.0/src/libchart/classes/Point.php new file mode 100644 index 0000000..5c0d9ec --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/Point.php @@ -0,0 +1,83 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /** + * Sampling point + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + */ + + class Point + { + /** + * Creates a new sampling point of coordinates (x, y) + * + * @access public + * @param integer x coordinate (label) + * @param integer y coordinate (value) + * @param array color R,G,B + */ + + function Point($x, $y, $c=null) + { + $this->x = $x; + $this->y = $y; + if($c != null) { + list($r,$g,$b) = $c; + $this->color = new Color($r,$g,$b); + $shadowFactor = 0.5; + $this->shadowColor = new Color($r * $shadowFactor, + $g * $shadowFactor, + $b * $shadowFactor); + } else { + $this->color = null; + $this->shadowColor = null; + } + } + + /** + * Gets the x coordinate (label) + * + * @access public + * @return integer x coordinate (label) + */ + + function getX() + { + return $this->x; + } + + /** + * Gets the y coordinate (value) + * + * @access public + * @return integer y coordinate (value) + */ + + function getY() + { + return $this->y; + } + + function getColor() { return $this->color; } + function getShadowColor() { return $this->shadowColor; } + } +?> diff --git a/boca-1.5.0/src/libchart/classes/Primitive.php b/boca-1.5.0/src/libchart/classes/Primitive.php new file mode 100644 index 0000000..9e5a896 --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/Primitive.php @@ -0,0 +1,59 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /** + * Graphic primitives, extends GD with chart related primitives + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + */ + + class Primitive + { + /** + * Creates a new primitive object + * + * @access public + * @param resource GD image resource + */ + + function Primitive($img) + { + $this->img = $img; + } + + /** + * Draws a straight line + * + * @access public + * @param integer line start (X) + * @param integer line start (Y) + * @param integer line end (X) + * @param integer line end (Y) + * @param Color line color + */ + + function line($x1, $y1, $x2, $y2, $color, $width = 1) + { + imagefilledpolygon($this->img, array($x1, $y1 - $width / 2, $x1, $y1 + $width / 2, $x2, $y2 + $width / 2, $x2, $y2 - $width / 2), 4, $color->getColor($this->img)); +// imageline($this->img, $x1, $y1, $x2, $y2, $color->getColor($this->img)); + } + } +?> diff --git a/boca-1.5.0/src/libchart/classes/Text.php b/boca-1.5.0/src/libchart/classes/Text.php new file mode 100644 index 0000000..7f7177c --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/Text.php @@ -0,0 +1,139 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /** + * Text drawing helper + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + */ + + class Text + { + var $HORIZONTAL_LEFT_ALIGN = 1; // PHP4 doesn't support class constants + var $HORIZONTAL_CENTER_ALIGN = 2; + var $HORIZONTAL_RIGHT_ALIGN = 4; + var $VERTICAL_TOP_ALIGN = 8; + var $VERTICAL_CENTER_ALIGN = 16; + var $VERTICAL_BOTTOM_ALIGN = 32; + + /** + * Creates a new text drawing helper + * + * @access public + */ + + function Text() + { + // Free low-res fonts based on Bitstream Vera <http://dejavu.sourceforge.net/wiki/> + + $this->fontCondensed = dirname(__FILE__) . "/../fonts/DejaVuSansCondensed.ttf"; + $this->fontCondensedBold = dirname(__FILE__) . "/../fonts/DejaVuSansCondensed-Bold.ttf"; + } + + /** + * Print text + * + * @access public + * @param Image GD image + * @param integer text coordinate (x) + * @param integer text coordinate (y) + * @param Color text color + * @param string text value + * @param string font file name + * @param bitfield text alignment + */ + + function printText($img, $px, $py, $color, $text, $fontFileName, $align = 0) + { + if(!($align & $this->HORIZONTAL_CENTER_ALIGN) && !($align & $this->HORIZONTAL_RIGHT_ALIGN)) + $align |= $this->HORIZONTAL_LEFT_ALIGN; + + if(!($align & $this->VERTICAL_CENTER_ALIGN) && !($align & $this->VERTICAL_BOTTOM_ALIGN)) + $align |= $this->VERTICAL_TOP_ALIGN; + + $fontSize = 8; + $lineSpacing = 1; + + list($llx, $lly, $lrx, $lry, $urx, $ury, $ulx, $uly) = imageftbbox($fontSize, 0, $fontFileName, $text, array("linespacing" => $lineSpacing)); + + $textWidth = $lrx - $llx; + $textHeight = $lry - $ury; + + $angle = 0; + + if($align & $this->HORIZONTAL_CENTER_ALIGN) + $px -= $textWidth / 2; + + if($align & $this->HORIZONTAL_RIGHT_ALIGN) + $px -= $textWidth; + + if($align & $this->VERTICAL_CENTER_ALIGN) + $py += $textHeight / 2; + + if($align & $this->VERTICAL_TOP_ALIGN) + $py += $textHeight; + + imagettftext($img, $fontSize, $angle, $px, $py, $color->getColor($img), $fontFileName, $text); + } + + /** + * Print text centered horizontally on the image + * + * @access public + * @param Image GD image + * @param integer text coordinate (y) + * @param Color text color + * @param string text value + * @param string font file name + */ + + function printCentered($img, $py, $color, $text, $fontFileName) + { + $this->printText($img, imagesx($img) / 2, $py, $color, $text, $fontFileName, $this->HORIZONTAL_CENTER_ALIGN | $this->VERTICAL_CENTER_ALIGN); + } + + /** + * Print text in diagonal + * + * @access public + * @param Image GD image + * @param integer text coordinate (x) + * @param integer text coordinate (y) + * @param Color text color + * @param string text value + */ + + function printDiagonal($img, $px, $py, $color, $text) + { + $fontSize = 8; + $fontFileName = $this->fontCondensed; + + $lineSpacing = 1; + + list($lx, $ly, $rx, $ry) = imageftbbox($fontSize, 0, $fontFileName, $text, array("linespacing" => $lineSpacing)); + $textWidth = $rx - $lx; + + $angle = -45; + + imagettftext($img, $fontSize, $angle, $px, $py, $color->getColor($img), $fontFileName, $text); + } + } +?> diff --git a/boca-1.5.0/src/libchart/classes/VerticalChart.php b/boca-1.5.0/src/libchart/classes/VerticalChart.php new file mode 100644 index 0000000..cdb4117 --- /dev/null +++ b/boca-1.5.0/src/libchart/classes/VerticalChart.php @@ -0,0 +1,169 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + /** + * Vertical bar chart + * + * @author Jean-Marc Trémeaux (jm.tremeaux at gmail.com) + */ + + class VerticalChart extends BarChart + { + /** + * Creates a new vertical bar chart + * + * @access public + * @param integer width of the image + * @param integer height of the image + */ + + function VerticalChart($width = 600, $height = 250) + { + parent::BarChart($width, $height); + + $this->setLabelMarginLeft(50); + $this->setLabelMarginRight(30); + $this->setLabelMarginTop(40); + $this->setLabelMarginBottom(50); + } + + /** + * Print the axis + * + * @access private + */ + + function printAxis() + { + // Check if some points were defined + + if(!$this->sampleCount) + return; + + $minValue = $this->axis->getLowerBoundary(); + $maxValue = $this->axis->getUpperBoundary(); + $stepValue = $this->axis->getTics(); + + // Vertical axis + + for($value = $minValue; $value <= $maxValue; $value += $stepValue) + { + $y = $this->graphBRY - ($value - $minValue) * ($this->graphBRY - $this->graphTLY) / ($this->axis->displayDelta); + + imagerectangle($this->img, $this->graphTLX - 3, $y, $this->graphTLX - 2, $y + 1, $this->axisColor1->getColor($this->img)); + imagerectangle($this->img, $this->graphTLX - 1, $y, $this->graphTLX, $y + 1, $this->axisColor2->getColor($this->img)); + + $this->text->printText($this->img, $this->graphTLX - 5, $y, $this->textColor, $value, $this->text->fontCondensed, $this->text->HORIZONTAL_RIGHT_ALIGN | $this->text->VERTICAL_CENTER_ALIGN); + } + + // Horizontal Axis + + $columnWidth = ($this->graphBRX - $this->graphTLX) / $this->sampleCount; + + reset($this->point); + + for($i = 0; $i <= $this->sampleCount; $i++) + { + $x = $this->graphTLX + $i * $columnWidth; + + imagerectangle($this->img, $x - 1, $this->graphBRY + 2, $x, $this->graphBRY + 3, $this->axisColor1->getColor($this->img)); + imagerectangle($this->img, $x - 1, $this->graphBRY, $x, $this->graphBRY + 1, $this->axisColor2->getColor($this->img)); + + if($i < $this->sampleCount) + { + $point = current($this->point); + next($this->point); + + $text = $point->getX(); + + $this->text->printDiagonal($this->img, $x + $columnWidth * 1 / 3, $this->graphBRY + 10, $this->textColor, $text); + } + } + } + + /** + * Print the bars + * + * @access private + */ + + function printBar() + { + // Check if some points were defined + + if(!$this->sampleCount) + return; + + reset($this->point); + + $minValue = $this->axis->getLowerBoundary(); + $maxValue = $this->axis->getUpperBoundary(); + $stepValue = $this->axis->getTics(); + + $columnWidth = ($this->graphBRX - $this->graphTLX) / $this->sampleCount; + + for($i = 0; $i < $this->sampleCount; $i++) + { + $x = $this->graphTLX + $i * ($this->graphBRX - $this->graphTLX) / $this->sampleCount; + + $point = current($this->point); + next($this->point); + + $value = $point->getY(); + + $ymin = $this->graphBRY - ($value - $minValue) * ($this->graphBRY - $this->graphTLY) / ($this->axis->displayDelta); + + $this->text->printText($this->img, $x + $columnWidth / 2, $ymin - 5, $this->textColor, $value, $this->text->fontCondensed, $this->text->HORIZONTAL_CENTER_ALIGN | $this->text->VERTICAL_BOTTOM_ALIGN); + + // Vertical bar + + $x1 = $x + $columnWidth * 1 / 5; + $x2 = $x + $columnWidth * 4 / 5; + + imagefilledrectangle($this->img, $x1, $ymin, $x2, $this->graphBRY - 1, $this->barColor2->getColor($this->img)); + imagefilledrectangle($this->img, $x1 + 1, $ymin + 1, $x2 - 4, $this->graphBRY - 1, $this->barColor1->getColor($this->img)); + } + } + + /** + * Render the chart image + * + * @access public + * @param string name of the file to render the image to (optional) + */ + + function render($fileName = null) + { + $this->computeBound(); + $this->computeLabelMargin(); + $this->createImage(); + $this->printLogo(); + $this->printTitle(); + $this->printAxis(); + $this->printBar(); + + if(isset($fileName)) + imagepng($this->img, $fileName); + else + imagepng($this->img); + } + } +?> diff --git a/boca-1.5.0/src/libchart/fonts/DejaVuSansCondensed-Bold.ttf b/boca-1.5.0/src/libchart/fonts/DejaVuSansCondensed-Bold.ttf Binary files differnew file mode 100644 index 0000000..6f4e42e --- /dev/null +++ b/boca-1.5.0/src/libchart/fonts/DejaVuSansCondensed-Bold.ttf diff --git a/boca-1.5.0/src/libchart/fonts/DejaVuSansCondensed.ttf b/boca-1.5.0/src/libchart/fonts/DejaVuSansCondensed.ttf Binary files differnew file mode 100644 index 0000000..12af357 --- /dev/null +++ b/boca-1.5.0/src/libchart/fonts/DejaVuSansCondensed.ttf diff --git a/boca-1.5.0/src/libchart/images/PoweredBy.png b/boca-1.5.0/src/libchart/images/PoweredBy.png Binary files differnew file mode 100644 index 0000000..6c5290c --- /dev/null +++ b/boca-1.5.0/src/libchart/images/PoweredBy.png diff --git a/boca-1.5.0/src/libchart/libchart.php b/boca-1.5.0/src/libchart/libchart.php new file mode 100644 index 0000000..4f359cb --- /dev/null +++ b/boca-1.5.0/src/libchart/libchart.php @@ -0,0 +1,33 @@ +<?php + /** Libchart - PHP chart library + * + * Copyright (C) 2005-2006 Jean Marc Trémeaux (jm.tremeaux at gmail.com) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + + require_once 'classes/Point.php'; + require_once 'classes/Axis.php'; + require_once 'classes/Color.php'; + require_once 'classes/Primitive.php'; + require_once 'classes/Text.php'; + require_once 'classes/Chart.php'; + require_once 'classes/PieChart.php'; + require_once 'classes/BarChart.php'; + require_once 'classes/LineChart.php'; + require_once 'classes/VerticalChart.php'; + require_once 'classes/HorizontalChart.php'; +?> diff --git a/boca-1.5.0/src/optionlower.php b/boca-1.5.0/src/optionlower.php new file mode 100644 index 0000000..b2eb5d4 --- /dev/null +++ b/boca-1.5.0/src/optionlower.php @@ -0,0 +1,121 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +//optionlower.php: parte de baixo da tela de option.php, que eh igual para +// todos os usuarios +require_once("globals.php"); + +if(!ValidSession()) { + InvalidSession("scoretable.php"); + ForceLoad("index.php"); +} +$loc = $_SESSION['loc']; + +if (isset($_GET["username"]) && isset($_GET["userfullname"]) && isset($_GET["userdesc"]) && + isset($_GET["passwordo"]) && isset($_GET["passwordn"])) { + $username = myhtmlspecialchars($_GET["username"]); + $userfullname = myhtmlspecialchars($_GET["userfullname"]); + $userdesc = myhtmlspecialchars($_GET["userdesc"]); + $passwordo = myhtmlspecialchars($_GET["passwordo"]); + $passwordn = myhtmlspecialchars($_GET["passwordn"]); + DBUserUpdate($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], + $username, + $userfullname, + $userdesc, + $passwordo, + $passwordn); + ForceLoad("option.php"); +} + +$a = DBUserInfo($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"]); + +?> + +<script language="JavaScript" src="<?php echo $loc; ?>/sha256.js"></script> +<script language="JavaScript" src="<?php echo $loc; ?>/hex.js"></script> +<script language="JavaScript"> +function computeHASH() +{ + var username, userdesc, userfull, passHASHo, passHASHn1, passHASHn2; + if (document.form1.passwordn1.value != document.form1.passwordn2.value) return; + username = document.form1.username.value; + userdesc = document.form1.userdesc.value; + userfull = document.form1.userfull.value; + passMDo = js_myhash(js_myhash(document.form1.passwordo.value)+'<?php echo session_id(); ?>'); + passMDn = bighexsoma(js_myhash(document.form1.passwordn2.value),js_myhash(document.form1.passwordo.value)); + document.form1.passwordo.value = ''; + document.form1.passwordn1.value = ''; + document.form1.passwordn2.value = ''; + document.location='option.php?username='+username+'&userdesc='+userdesc+'&userfullname='+userfull+'&passwordo='+passMDo+'&passwordn='+passMDn; +} +</script> + +<br><br> +<form name="form1" action="javascript:computeHASH()"> + <center> + <table border="0"> + <tr> + <td width="35%" align=right>Username:</td> + <td width="65%"> + <input type="text" readonly name="username" value="<?php echo $a["username"]; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>User Full Name:</td> + <td width="65%"> + <input type="text" readonly name="userfull" value="<?php echo $a["userfullname"]; ?>" size="50" maxlength="50" /> + </td> + </tr> + <tr> + <td width="35%" align=right>User Description:</td> + <td width="65%"> + <input type="text" name="userdesc" value="<?php echo $a["userdesc"]; ?>" size="50" maxlength="250" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Old Password:</td> + <td width="65%"> + <input type="password" name="passwordo" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>New Password:</td> + <td width="65%"> + <input type="password" name="passwordn1" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Retype New Password:</td> + <td width="65%"> + <input type="password" name="passwordn2" size="20" maxlength="20" /> + </td> + </tr> + </table> + </center> + <center> + <input type="submit" name="Submit" value="Send"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/php.php b/boca-1.5.0/src/php.php new file mode 100644 index 0000000..147cebc --- /dev/null +++ b/boca-1.5.0/src/php.php @@ -0,0 +1 @@ +<?php phpinfo(); ?> diff --git a/boca-1.5.0/src/private/.htaccess b/boca-1.5.0/src/private/.htaccess new file mode 100644 index 0000000..3a42882 --- /dev/null +++ b/boca-1.5.0/src/private/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/boca-1.5.0/src/private/autojudging.php b/boca-1.5.0/src/private/autojudging.php new file mode 100755 index 0000000..3685254 --- /dev/null +++ b/boca-1.5.0/src/private/autojudging.php @@ -0,0 +1,529 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; +if(is_readable(getcwd() . $ds . '..' .$ds . 'db.php')) { + require_once(getcwd() . $ds . '..' .$ds . 'db.php'); + require_once(getcwd() . $ds . '..' .$ds . 'version.php'); +} else { + if(is_readable(getcwd() . $ds . 'db.php')) { + require_once(getcwd() . $ds . 'db.php'); + require_once(getcwd() . $ds . 'version.php'); + } else { + echo "unable to find db.php"; + exit; + } +} +if (getIP()!="UNKNOWN" || php_sapi_name()!=="cli") exit; +if(system('test "`id -u`" -eq "0"',$retval)===false || $retval!=0) { + echo "Must be run as root\n"; + exit; +} + +ini_set('memory_limit','600M'); +ini_set('output_buffering','off'); +ini_set('implicit_flush','on'); +@ob_end_flush(); +echo "max memory set to " . ini_get('memory_limit'). "\n"; + +$tmpdir = getenv("TMP"); +if($tmpdir=="") $tmpdir = getenv("TMPDIR"); +if($tmpdir[0] != '/') $tmdir = "/tmp"; +if($tmpdir=="") $tmpdir = "/tmp"; + +$basdir=$ds; +if(file_exists($ds . 'bocajail' . $tmpdir)) { + $tmpdir=$ds . 'bocajail' . $tmpdir; + $basdir=$ds . 'bocajail' . $ds; + echo "bocajail environment seems to exist - trying to use it\n"; +} else { + echo "bocajail not found - trying to proceed without using it\n"; +} + +if($ds=='/') { + system("find $basdir -user bocajail -delete >/dev/null 2>/dev/null"); + system("find $basdir -user nobody -delete >/dev/null 2>/dev/null"); + system("find $basdir -group users -exec chgrp root '{}' \\; 2>/dev/null"); + system("find $basdir -perm /1002 -type d > /tmp/boca.writabledirs.tmp 2>/dev/null"); + system('chmod 400 /tmp/boca.writabledirs.tmp 2>/dev/null'); +} +umask(0022); + +$cache = $tmpdir . $ds . "bocacache.d"; +cleardir($cache); +@mkdir($cache); +$key=md5(mt_rand() . rand() . mt_rand()); + +$cf = globalconf(); +$ip = $cf["ip"]; +$activecontest=DBGetActiveContest(); +$prevsleep=0; +while(42) { +if(($run = DBGetRunToAutojudging($activecontest["contestnumber"], $ip)) === false) { + if($prevsleep==0) + echo "Nothing to do. Sleeping..."; + else + echo "."; + flush(); + sleep(10); + $prevsleep=1; + continue; +} +echo "\n"; +flush(); +$prevsleep=0; + +$number=$run["number"]; +$site=$run["site"]; +$contest=$run["contest"]; + +echo "Removing possible files from previous runs\n"; +$dirs=file('/tmp/boca.writabledirs.tmp'); +for($dir=0;$dir<count($dirs);$dir++) { + $dirn=trim($dirs[$dir]) . $ds; + if($dirn[0] != '/') continue; + system("find \"$dirn\" -user bocajail -delete >/dev/null 2>/dev/null"); + system("find \"$dirn\" -user nobody -delete >/dev/null 2>/dev/null"); +} + +echo "Entering directory $tmpdir (contest=$contest, site=$site, run=$number)\n"; +chdir($tmpdir); +for($i=0; $i<5; $i++) { + $name = tempnam($tmpdir, "boca"); + $dir = $name . ".d"; + if(@mkdir($dir, 0755)) break; + @unlink($name); + @rmdir($dir); +} +if($i>=5) { + echo "It was not possible to create a unique temporary directory\n"; + LogLevel("Autojuging: Unable to create temp directory (run=$number, site=$site, contest=$contest)",1); + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem creating temp directory"); + continue; +} +chdir($dir); + +echo "Using directory $dir (contest=$contest, site=$site, run=$number)\n"; + +/* +if($run["scriptoid"]=="" || $run["scriptname"]=="") { + LogLevel("Autojuging: Script file not defined (run=$number, site=$site, contest=$contest)",1); + echo "Compiling/running script file not defined (contest=$contest, site=$site, run=$number)\n"; + cleardir($dir); + unlink($name); + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: compiling/running script not defined"); + continue; +} +if($run["compscriptoid"]=="" || $run["compscriptname"]=="") { + LogLevel("Autojuging: Comparing script file not defined (run=$number, site=$site, contest=$contest)",1); + echo "Comparing script file not defined (contest=$contest, site=$site, run=$number)\n"; + cleardir($dir); + unlink($name); + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: comparing script not defined"); + continue; +} +*/ +if($run["sourceoid"]=="" || $run["sourcename"]=="") { + LogLevel("Autojuging: Source file not defined (run=$number, site=$site, contest=$contest)",1); + echo "Source file not defined (contest=$contest, site=$site, run=$number)\n"; + cleardir($dir); + unlink($name); + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: source file not defined"); + continue; +} +if($run["inputoid"]=="" || $run["inputname"]=="") { + LogLevel("Autojuging: problem package not defined (run=$number, site=$site, contest=$contest)",1); + echo "Package file not defined (contest=$contest, site=$site, run=$number)\n"; + cleardir($dir); + unlink($name); + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file not defined"); + continue; +} +/* +if($run["soloid"]=="" || $run["solname"]=="") { + LogLevel("Autojuging: sol file not defined (run=$number, site=$site, contest=$contest)",1); + echo "solfile not defined (contest=$contest, site=$site, run=$number)\n"; + cleardir($dir); + unlink($name); + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: correct output file not defined"); + continue; +} +*/ +$c = DBConnect(); +DBExec($c, "begin work", "Autojudging(exporttransaction)"); +/* +if(DB_lo_export($c, $run["scriptoid"], $dir . $ds . $run["scriptname"]) === false) { + DBExec($c, "rollback work", "Autojudging(rollback-script)"); + LogLevel("Autojuging: Unable to export script file (run=$number, site=$site, contest=$contest)",1); + echo "Error exporting compiling/running script file ${run["scriptname"]} (contest=$contest, site=$site, run=$number)\n"; + cleardir($dir); + unlink($name); + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: unable to export compiling/running script"); + continue; +} +*/ +if(DB_lo_export($c, $run["sourceoid"], $dir . $ds . $run["sourcename"]) === false) { + DBExec($c, "rollback work", "Autojudging(rollback-source)"); + LogLevel("Autojudging: Unable to export source file (run=$number, site=$site, contest=$contest)",1); + echo "Error exporting source file ${run["sourcename"]} (contest=$contest, site=$site, run=$number)\n"; + cleardir($dir); + unlink($name); + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: unable to export source file"); + DBExec($c, "commit", "Autojudging(exportcommit)"); + continue; +} +if(is_readable($cache . $ds . $run["inputoid"] . "." . $run["inputname"])) { + DBExec($c, "commit", "Autojudging(exportcommit)"); + echo "Getting problem package file from local cache\n"; + $s = file_get_contents($cache . $ds . $run["inputoid"] . "." . $run["inputname"]); + file_put_contents($dir . $ds . $run["inputname"], decryptData($s,$key)); +} else { + echo "Downloading problem package file from db\n"; + if(DB_lo_export($c, $run["inputoid"], $dir . $ds . $run["inputname"]) === false) { + DBExec($c, "rollback work", "Autojudging(rollback-input)"); + LogLevel("Autojudging: Unable to export problem package file (run=$number, site=$site, contest=$contest)",1); + echo "Error exporting problem package file ${run["inputname"]} (contest=$contest, site=$site, run=$number)\n"; + cleardir($dir); + unlink($name); + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: unable to export problem package file"); + DBExec($c, "commit", "Autojudging(exportcommit)"); + continue; + } + DBExec($c, "commit", "Autojudging(exportcommit)"); + + echo "Problem package downloaded -- running init scripts to obtain limits and other information\n"; + $zip = new ZipArchive; + if ($zip->open($dir . $ds . $run["inputname"]) === true) { + $zip->extractTo($dir . $ds . "problemdata"); + $zip->close(); + } else { + echo 'Failed to unzip the file -- please check the problem package\n'; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid"); + continue; + } + if(($info=file($dir . $ds . "problemdata" . $ds . "description" . $ds . 'problem.info'))===false) { + echo 'Problem content missing (description/problem.info) -- please check the problem package\n'; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid"); + continue; + } + $basename=''; + foreach($info as $line) { + $a=explode('=',$line); + if(trim($a[0])=='basename') { + $basename=trim($a[1]); + break; + } + } + if($basename=='') { + echo 'Problem content missing (description/problem.info) -- please check the problem package\n'; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid"); + continue; + } + if(!is_dir($dir . $ds . "problemdata" . $ds . "limits")) { + echo 'Problem content missing (limits) -- please check the problem package\n'; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid"); + continue; + } + chdir($dir . $ds . "problemdata" . $ds . "limits"); + foreach(glob($dir . $ds . "problemdata" . $ds . "limits" .$ds . '*') as $file) { + chmod($file,0700); + $ex = escapeshellcmd($file); + $ex .= " >stdout 2>stderr"; + echo "Executing INIT SCRIPT " . $ex . "\n"; + if(system($ex, $retval)===false) $retval=-1; + if($retval != 0) { + echo 'Error running script -- please check the problem package\n'; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid"); + continue; + } + $limits[$basename] = file('stdout'); + } + + foreach(glob($dir . $ds . "problemdata" . $ds . "tests" .$ds . '*') as $file) { + chdir($dir . $ds . "problemdata" . $ds . "tests"); + chmod($file,0700); + $ex = escapeshellcmd($file); + $ex .= " >stdout 2>stderr"; + echo "Executing TEST SCRIPT " . $ex . "\n"; + if(system($ex, $retval)===false) $retval=-1; + if($retval != 0) { + echo 'Error running test script -- please check the problem package\n'; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: internal test script failed"); + continue; + } + } + cleardir($dir . $ds . "problemdata"); + $s = file_get_contents($dir . $ds . $run["inputname"]); + file_put_contents($cache . $ds . $run["inputoid"] . "." . $run["inputname"], encryptData($s,$key)); +} + +function exitmsg($retval) { +/* FROM SAFEEXEC +# 0 ok +# 1 compile error +# 2 runtime error +# 3 timelimit exceeded +# 4 internal error +# 5 parameter error +# 6 internal error +# 7 memory limit exceeded +# 8 security threat +# 9 runtime error +*/ +/* + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 0, 'Not answered yet', 'f', 't')", "DBNewContest(insert fake answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 1, 'YES', 't', 'f')", "DBNewContest(insert YES answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 2, 'NO - Compilation error', 'f', 'f')", "DBNewContest(insert CE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 3, 'NO - Runtime error', 'f', 'f')", "DBNewContest(insert RE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 4, 'NO - Time limit exceeded', 'f', 'f')", "DBNewContest(insert TLE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 5, 'NO - Presentation error', 'f', 'f')", "DBNewContest(insert PE answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 6, 'NO - Wrong answer', 'f', 'f')", "DBNewContest(insert WA answer)"); + DBExec($c, "insert into answertable (contestnumber, answernumber, runanswer, yes, fake) values ". + "($n, 7, 'NO - Contact staff', 'f', 'f')", "DBNewContest(insert CS answer)"); +*/ + if($retval==-1) { + $answer="Internal error while executing run command"; + $retval = 7; // contact staff + } + else if($retval==1) { + $answer="Compilation error"; + $retval = 2; // compilation error + } + else if($retval==2) { + $answer="Runtime error"; + $retval = 3; // runtime error + } + else if($retval==3) { + $answer="Time limit exceeded"; + $retval = 4; // timelimit exceeded + } + else if($retval==4) { + $answer="safeexec internal error (4)"; + $retval = 7; // contact staff + } + else if($retval==5) { + $answer="safeexec error: parameter problem"; + $retval = 7; // contact staff + } + else if($retval==6) { + $answer="safeexec internal error (6)"; + $retval = 7; // contact staff + } + else if($retval==7) { + $answer="Runtime error (memory-limit)"; + $retval = 3; // runtime error + } + else if($retval==8) { + $answer="Code generates security threat"; + $retval = 3; // runtime error + } + else if($retval==9) { + $answer="Runtime error"; + $retval = 3; // runtime error + } + return array($retval,$answer); +} + +// COMPILATION +//# parameters are: +//# $1 source_file +//# $2 exe_file (default ../run.exe) +//# $3 timelimit (optional, limit to run all the repetitions, by default only one repetition) +//# $4 maximum allowed memory (in MBytes) + +$zip = new ZipArchive; +if ($zip->open($dir . $ds . $run["inputname"]) === true) { + $zip->extractTo($dir, "compile" . $ds . $run["extension"]); + $zip->close(); +} else { + echo 'Failed to unzip the file -- please check the problem package\n'; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid"); + continue; +} + +$script = $dir . $ds . 'compile' . $ds . $run["extension"]; +if(!is_file($script)) { + echo 'Error (not found) compile script for '.$run["extension"].' -- please check the problem package\n'; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: compile script failed (".$run["extension"].")"); + continue; +} + +chmod($script, 0700); +$ex = escapeshellcmd($script) ." ". + escapeshellarg($run["sourcename"])." ". + "run.exe ". + escapeshellarg(trim($limits[$run["extension"]][0]))." ". + escapeshellarg(trim($limits[$run["extension"]][2])); +$ex .= " >stdout 2>stderr"; +echo "Executing " . $ex . "\n"; +if(system($ex, $retval)===false) $retval=-1; + +if($retval != 0) { + list($retval,$answer) = exitmsg($retval); + $answer = "(WHILE COMPILING) " . $answer; +} else { +//# parameters are: +//# $1 exe_file +//# $2 input_file +//# $3 timelimit (limit to run all the repetitions, by default only one repetition) +//# $4 number_of_repetitions_to_run (optional, can be used for better tuning the timelimit) +//# $5 maximum allowed memory (in KBytes) + + $zip = new ZipArchive; + if ($zip->open($dir . $ds . $run["inputname"]) === true) { + $zip->extractTo($dir, array("run" . $ds . $run["extension"],"input" . $ds . '*')); + $zip->close(); + } else { + echo 'Failed to unzip the file (inputs) -- please check the problem package\n'; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid"); + continue; + } + chdir($dir); + @unlink('allout'); + @unlink('allerr'); + $retval = 0; + $script = $dir . $ds . 'run' . $ds . $run["extension"]; + chmod($script, 0700); + mkdir('team', 0755); + $d = opendir($dir . $ds . "input"); + while (($file = readdir($d)) !== false) { + if(is_file($dir . $ds . "input" . $ds . $file)) { + $ex = escapeshellcmd($script) ." ". + "run.exe ". + escapeshellarg($dir . $ds . "input" . $ds . $file)." ". + escapeshellarg(trim($limit[0]))." ". + escapeshellarg(trim($limit[1]))." ". + escapeshellarg(trim($limit[2])); + $ex .= " >stdout 2>stderr"; + echo "Executing " . $ex . " for input " . $file . "\n"; + if(system($ex, $retval)===false) $retval=-1; + foreach (glob($dir . $ds . '*') as $fne) { + @chown($fne,"nobody"); + @chmod($fne,0755); + } + if(is_readable('stderr0')) + system('cat stderr0 >> stderr'); + system('echo ##### STDERR FOR FILE ' . escapeshellarg($file) . ' >> allerr'); + system('cat stderr >> allerr'); + system('cat stdout > team' . $ds . escapeshellarg($file)); + system('echo ##### STDOUT FOR FILE ' . escapeshellarg($file) . ' >> allout'); + system('cat stdout >> allout'); + if($retval != 0) { + list($retval,$answer) = exitmsg($retval); + $answer = "(WHILE RUNNING) " . $answer; + break; + } + } + } + if($retval==0) { + echo "Processing results\n"; + $zip = new ZipArchive; + if ($zip->open($dir . $ds . $run["inputname"]) === true) { + $zip->extractTo($dir, array("compare" . $ds . $run["extension"],"output" . $ds . '*')); + $zip->close(); + } else { + echo 'Failed to unzip the file (outputs) -- please check the problem package\n'; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid"); + continue; + } + $script = $dir . $ds . 'compare' . $ds . $run["extension"]; + $retval = 0; + chmod($script, 0700); + $d = opendir($dir . $ds . "output"); + while (($file = readdir($d)) !== false) { + if(is_file($dir . $ds . "output" . $ds . $file)) { + $ex = escapeshellcmd($script) ." ". + escapeshellarg("team" . $ds . $file)." ". + escapeshellarg("output" . $ds . $file)." ". + escapeshellarg("input" . $ds . $file) . " >compout"; + echo "Executing " . $ex . "\n"; + $answer = system($ex, $localretval); + + $fp = fopen($dir . $ds . "allerr", "a+"); + fwrite($fp, "\n\n===OUTPUT OF COMPARING SCRIPT FOLLOWS FOR FILE " .$file ." (EMPTY MEANS NO DIFF)===\n"); + $dif = file($dir . $ds . "compout"); + $difi = 0; + for(; $difi < count($dif)-1 && $difi < 5000; $difi++) + fwrite($fp, $dif[$difi]); + if($difi >= 5000) fwrite($fp, "===OUTPUT OF COMPARING SCRIPT TOO LONG - TRUNCATED===\n"); + else fwrite($fp, "===OUTPUT OF COMPARING SCRIPT ENDS HERE===\n"); + $answer = trim($dif[count($dif)-1]); + fclose($fp); + foreach (glob($dir . $ds . '*') as $fne) { + @chown($fne,"nobody"); + @chmod($fne,0755); + } + // retval 5 (presentation) and retval 6 (wronganswer) are already compatible with the compare script + if($localretval < 4 || $localretval > 6) { + // contact staff + $retval = 7; + $answer='Contact staff'; + } + else if($retval==0) { + if($localretval==4) { + // YES! + $answer='YES'; + $retval = 1; + } else $retval=$localretval; + } + else if($retval==1) { + if($localretval!=4) { + $retval=$localretval; + $answer='Presentation error'; + } + } + } + } + } +} +if($retval > 9) { + $ans = file("allout"); + $anstmp = trim(escape_string($ans[count($ans)-1])); + unset($ans); + LogLevel("Autojudging: Script returned unusual code: $retval ($anstmp)". + "(run=$number, site=$site, contest=$contest)",1); + echo "Autojudging script returned unusual code $retval ($anstmp)". + "(contest=$contest, site=$site, run=$number)\n"; +// cleardir($dir); +// unlink($name); +// DBGiveUpRunAutojudging($contest, $site, $number, $ip, "(unusual code: $retval) " . $anstmp); +// continue; + $answer = "(check output files - unusual code: $retval) " . $anstmp; + + // contact staff + $retval = 7; +} + +echo "Sending results to server\n"; +DBUpdateRunAutojudging($contest, $site, $number, $ip, $answer, $dir.$ds.'allout', $dir.$ds.'allerr', $retval); +LogLevel("Autojudging: answered '$answer' (run=$number, site=$site, contest=$contest)",3); +echo "Autojudging answered '$answer' (contest=$contest, site=$site, run=$number)\n"; +if(!isset($dodebug)) { + cleardir($dir); + unlink($name); +} +} +?> diff --git a/boca-1.5.0/src/private/conf.php b/boca-1.5.0/src/private/conf.php new file mode 100644 index 0000000..9ad1a80 --- /dev/null +++ b/boca-1.5.0/src/private/conf.php @@ -0,0 +1,60 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +function globalconf() { + $conf["dbencoding"]="UTF8"; + $conf["dbclientenc"]="UTF8"; + + $conf["dblocal"]="false"; // use unix socket to connect? +$conf["dbhost"]="localhost"; +$conf["dbport"]="5432"; + + $conf["dbname"]="bocadb"; // name of the boca database + + $conf["dbuser"]="bocauser"; // unprivileged boca user +$conf["dbpass"]="dAm0HAiC"; + + $conf["dbsuperuser"]="bocauser"; // privileged boca user +$conf["dbsuperpass"]="dAm0HAiC"; + + // note that it is fine to use the same user + + // initial password that is used for the user admin -- set it + // to something hard to guess if the server is available + // online even in the moment you are creating the contest + // In this way, the new accounts for system and admin that are + // eventually created come already with the password set to this + // value. It is your task later to update these passwords to + // some other values within the BOCA web interface. + $conf["basepass"]="boca"; + + // secret key to be used in HTTP headers + // you MUST set it with any random large enough sequence +$conf["key"]="GG56KFJtNDBGjJprR6ex"; + + + // the following field is used by the autojudging script + // set it with the ip of the computer running the script + // The real purpose of it is only to differentiate between + // autojudges when multiple computers are used as autojudges + $conf["ip"]='local'; + + return $conf; +} +?> diff --git a/boca-1.5.0/src/private/createdb.php b/boca-1.5.0/src/private/createdb.php new file mode 100644 index 0000000..e06682d --- /dev/null +++ b/boca-1.5.0/src/private/createdb.php @@ -0,0 +1,70 @@ +#!/usr/bin/php +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +//Last updated 21/jul/2012 by cassio@ime.usp.br +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +if(is_readable(getcwd() . $ds . '..' .$ds . 'db.php')) { + require_once(getcwd() . $ds . '..' .$ds . 'db.php'); + @include_once(getcwd() . $ds . '..' .$ds . 'version.php'); +} else { + if(is_readable(getcwd() . $ds . 'db.php')) { + require_once(getcwd() . $ds . 'db.php'); + @include_once(getcwd() . $ds . 'version.php'); + } else { + echo "unable to find db.php"; + exit; + } +} +if (getIP()!="UNKNOWN" || php_sapi_name()!=="cli") exit; +ini_set('memory_limit','600M'); +ini_set('output_buffering','off'); +ini_set('implicit_flush','on'); +@ob_end_flush(); + +if(system('test "`id -u`" -eq "0"',$retval)===false || $retval!=0) { + echo "Must be run as root\n"; + exit; +} +echo "\nThis will erase all the data in your bocadb database."; +echo "\n***** YOU WILL LOSE WHATEVER YOU HAVE THERE!!! *****"; +echo "\nType YES and press return to continue or anything else will abort it: "; +$resp = strtoupper(trim(fgets(STDIN))); +if($resp != 'YES') exit; + +echo "\ndropping database\n"; +DBDropDatabase(); +echo "creating database\n"; +DBCreateDatabase(); +echo "creating tables\n"; +DBCreateContestTable(); +DBCreateSiteTable(); +DBCreateSiteTimeTable(); +DBCreateUserTable(); +DBCreateLogTable(); +DBCreateProblemTable(); +DBCreateAnswerTable(); +DBCreateTaskTable(); +DBCreateLangTable(); +DBCreateRunTable(); +DBCreateClarTable(); +DBCreateBkpTable(); +echo "creating initial fake contest\n"; +DBFakeContest(); +?> diff --git a/boca-1.5.0/src/private/createproblemzip.php b/boca-1.5.0/src/private/createproblemzip.php new file mode 100755 index 0000000..1b3b3cc --- /dev/null +++ b/boca-1.5.0/src/private/createproblemzip.php @@ -0,0 +1,93 @@ +#!/usr/bin/php +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +//Last updated 21/jul/2012 by cassio@ime.usp.br +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +if(is_readable(getcwd() . $ds . '..' .$ds . 'db.php')) { + require_once(getcwd() . $ds . '..' .$ds . 'db.php'); + @include_once(getcwd() . $ds . '..' .$ds . 'version.php'); +} else { + if(is_readable(getcwd() . $ds . 'db.php')) { + require_once(getcwd() . $ds . 'db.php'); + @include_once(getcwd() . $ds . 'version.php'); + } else { + echo "unable to find db.php"; + exit; + } +} +if (getIP()!="UNKNOWN" || php_sapi_name()!=="cli") exit; +ini_set('memory_limit','600M'); +ini_set('output_buffering','off'); +ini_set('implicit_flush','on'); +@ob_end_flush(); + +if(system('test "`id -u`" -eq "0"',$retval)===false || $retval!=0) { + echo "Must be run as root\n"; + exit; +} +if(count($argv) < 3 || !is_readable($argv[1])) { + echo "Usage: createproblemzip.php <problem_directory> <problem_zipfile> [<password>]\n"; + exit; +} +if(count($argv) >= 4) + $password2 = trim($argv[3]); +else { + echo "\nWe use a two password system: The following password is\nused to unlock the true password that encrypts the zip file.\n"; + echo "It should be kept secret during all the time.\n"; + echo "Please type the password to unlock the zip file password: "; +// ONLY WORKS IN LINUX!!! + system('stty -echo'); + $password2 = trim(fgets(STDIN)); + system('stty echo'); + + echo "\nPlease retype the password: "; +// ONLY WORKS IN LINUX!!! + system('stty -echo'); + $password3 = trim(fgets(STDIN)); + system('stty echo'); + if($password3 != $password2) { + echo "\nPasswords mismatch - aborting\n"; + exit; + } +} +if(strlen($password2) < 12) + echo "\n\n#\n##\n###\n####\n#####\n###### WARNING: the main password should be really secure - consider using a longer and complicated password\n"; + +$password1 = randstr(16); +if(is_dir(trim($argv[1]))) { + echo "Creating file " . $argv[2] . " from directory/file " . $argv[1] . "\n"; + if(($ret=create_zip(trim($argv[1]),glob(trim($argv[1]) . $ds . '*'),trim($argv[2]),true)) > 0) + echo "ZIP Success\n"; + else + echo "ZIP Error $ret\n"; + $encdata=encryptData(file_get_contents(trim($argv[2])),'#####'.$password1,false); +} else + $encdata=encryptData(file_get_contents(trim($argv[1])),'#####'.$password1,true); + +file_put_contents(trim($argv[2]),$encdata); +echo "Output file generated in " . $argv[2] . "\n"; + +echo "\n\nThe following line is a key that should be appended to a text file with one key per line.\n\n"; +echo substr($encdata,0,10) . '#####' . encryptData('#####'.$password1,$password2,false) . "\n\n"; + +echo "Later on, in the admin web interface of BOCA tab Contest, item Contest keys, please select the file with\nall these lines click on update.\n\n"; + +exit; +?> diff --git a/boca-1.5.0/src/private/index.html b/boca-1.5.0/src/private/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/boca-1.5.0/src/private/index.html diff --git a/boca-1.5.0/src/private/insertlanguages.php b/boca-1.5.0/src/private/insertlanguages.php new file mode 100644 index 0000000..c6b150a --- /dev/null +++ b/boca-1.5.0/src/private/insertlanguages.php @@ -0,0 +1,49 @@ +#!/usr/bin/php +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +//Last updated 21/jul/2012 by cassio@ime.usp.br +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; +if(is_readable(getcwd() . $ds . '..' .$ds . 'db.php')) { + require_once(getcwd() . $ds . '..' .$ds . 'db.php'); + require_once(getcwd() . $ds . '..' .$ds . 'version.php'); +} else { + if(is_readable(getcwd() . $ds . 'db.php')) { + require_once(getcwd() . $ds . 'db.php'); + require_once(getcwd() . $ds . 'version.php'); + } else { + echo "unable to find db.php"; + exit; + } +} +if (getIP()!="UNKNOWN" || php_sapi_name()!=="cli") exit; +ini_set('memory_limit','600M'); +ini_set('output_buffering','off'); +ini_set('implicit_flush','on'); +@ob_end_flush(); + +if(system('test "`id -u`" -eq "0"',$retval)===false || $retval!=0) { + echo "Must be run as root\n"; + exit; +} + +echo "\nType the contest number to re-insert the languages: "; +$resp = strtoupper(trim(fgets(STDIN))); +if(is_numeric($resp)) + insertlanguages($resp, null); +exit; diff --git a/boca-1.5.0/src/private/problemtmp/.htaccess b/boca-1.5.0/src/private/problemtmp/.htaccess new file mode 100644 index 0000000..3a42882 --- /dev/null +++ b/boca-1.5.0/src/private/problemtmp/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/boca-1.5.0/src/private/remotescores/otherservers b/boca-1.5.0/src/private/remotescores/otherservers new file mode 100644 index 0000000..9db80da --- /dev/null +++ b/boca-1.5.0/src/private/remotescores/otherservers @@ -0,0 +1,4 @@ +#http://189.154.245.253/boca score score +#200.3.153.44 score score +#http://boca.uci.cu/boca score score + diff --git a/boca-1.5.0/src/private/runtmp/index.html b/boca-1.5.0/src/private/runtmp/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/boca-1.5.0/src/private/runtmp/index.html diff --git a/boca-1.5.0/src/private/score.sep b/boca-1.5.0/src/private/score.sep new file mode 100644 index 0000000..a61b979 --- /dev/null +++ b/boca-1.5.0/src/private/score.sep @@ -0,0 +1,22 @@ +General 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 100 +Site_1 1 +Site_2 2 +Site_3 3 +Site_4 4 +Site_5 5 +Site_6 6 +Site_7 7 +Site_8 8 +Site_9 9 +Site_10 10 +Site_11 11 +Site_12 12 +Site_13 13 +Site_14 14 +Site_15 15 +Site_16 16 +Site_17 17 +Site_18 18 +Site_19 19 +Site_20 20 +Site_100 100 diff --git a/boca-1.5.0/src/private/scoretmp/index.html b/boca-1.5.0/src/private/scoretmp/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/boca-1.5.0/src/private/scoretmp/index.html diff --git a/boca-1.5.0/src/reload.js b/boca-1.5.0/src/reload.js new file mode 100644 index 0000000..a6eb426 --- /dev/null +++ b/boca-1.5.0/src/reload.js @@ -0,0 +1,57 @@ +/*///////////////////////////////////////////////////////////////////////////////////////// +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +*/ +var msg = 0; +var rld = 0; +var selecionando = 0; +var seg = 120; +function recarregar() { + if (rld) { + clearTimeout(rld); + rld = 0; + } + if ((document.form1 && document.form1.message && document.form1.message.value) || + (document.form1 && document.form1.sourcefile && document.form1.sourcefile.value) || + (document.form1 && document.form1.answer && document.form1.answer.value) || + (document.form2 && document.form2.answer && document.form2.answer.value) || + (document.form2 && document.form2.message && document.form2.message.value) || + (document.form2 && document.form2.sourcefile && document.form2.sourcefile.value) || + selecionando == 1) { + if (msg<5) { + msg++; + } + else { + alert("This page tried to reload, but it seems that you are filling\nthe form. To update, click on Reload button in your\nbrowser. This message will not be displayed again."); + } + } else + document.location.reload(); + rld = setTimeout("recarregar()", seg * 1000); +} +function Comecar() { + rld = setTimeout("recarregar()", seg * 1000); +} +function Parar() { + if (rld) { + clearTimeout(rld); + rld = 0; + } +} +function Arquivo() { + selecionando = 1; +} diff --git a/boca-1.5.0/src/score/header.php b/boca-1.5.0/src/score/header.php new file mode 100644 index 0000000..69cf6e5 --- /dev/null +++ b/boca-1.5.0/src/score/header.php @@ -0,0 +1,72 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +header ("Content-Type: text/html; charset=utf-8"); +session_start(); +ob_end_flush(); +require_once('../version.php'); + +require_once("../globals.php"); +require_once("../db.php"); + +echo "<html><head><title>Score Board Page</title>\n"; +echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"; +echo "<link rel=stylesheet href=\"../Css.php\" type=\"text/css\">\n"; +echo "<meta http-equiv=\"refresh\" content=\"60\" />"; + +$ret=1; +if (!isset($_SESSION["usertable"])) $ret=0; +else { + $_SESSION["usertable"] = DBUserInfo($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], $_SESSION["usertable"]["usernumber"]); + if ($_SESSION["usertable"]["usersession"] != session_id() && $_SESSION["usertable"]["usermultilogin"]!="t") + $ret=0; +} + +if($ret==0) { + InvalidSession("score/index.php"); + ForceLoad("../index.php"); +} +if($_SESSION["usertable"]["usertype"] != "score") { + IntrusionNotify("score/index.php"); + ForceLoad("../index.php"); +} + +echo "</head><body><table border=1 width=\"100%\">\n"; +echo "<tr><td nowrap bgcolor=\"#cc9966\" align=center>"; +echo "<img src=\"../images/smallballoontransp.png\" alt=\"\">"; +echo "<font color=\"#000000\">BOCA</font>"; +echo "</td><td bgcolor=\"#cc9966\" width=\"99%\">\n"; +echo "Username: " . $_SESSION["usertable"]["userfullname"] . " (site=".$_SESSION["usertable"]["usersitenumber"].")<br>\n"; +list($clockstr,$clocktype)=siteclock(); +echo "</td><td bgcolor=\"#cc9966\" align=center nowrap> ".$clockstr." </td></tr>\n"; +echo "</table>\n"; +if(!isset($_SESSION["scorenomenu"]) || !$_SESSION["scorenomenu"]) { + echo "<table border=0 width=\"100%\" align=center>\n"; + echo " <tr>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=index.php>Score</a></td>\n"; + echo " <td align=center><a class=menu style=\"font-weight:bold\" href=../index.php>Logout</a></td>\n"; + echo " </tr>\n"; + echo "</table>\n"; +} +?> diff --git a/boca-1.5.0/src/score/index.php b/boca-1.5.0/src/score/index.php new file mode 100644 index 0000000..ef9675d --- /dev/null +++ b/boca-1.5.0/src/score/index.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +require('../scorelower.php'); +?> diff --git a/boca-1.5.0/src/score/score.php b/boca-1.5.0/src/score/score.php new file mode 100644 index 0000000..ef9675d --- /dev/null +++ b/boca-1.5.0/src/score/score.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +require('../scorelower.php'); +?> diff --git a/boca-1.5.0/src/scorelower.php b/boca-1.5.0/src/scorelower.php new file mode 100644 index 0000000..7ee78e8 --- /dev/null +++ b/boca-1.5.0/src/scorelower.php @@ -0,0 +1,45 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require_once("globals.php"); + +if(!ValidSession()) { + InvalidSession("scorelower.php"); + ForceLoad("index.php"); +} + +if (($s = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +if ($_SESSION["usertable"]["usertype"]!="judge" && + $_SESSION["usertable"]["usertype"]!="admin") $ver=true; +else $ver=false; +if($_SESSION["usertable"]["usertype"]=="score") $des=false; +else $des=true; + +// temp do carlinhos (placar de judge == placar de time) +//if ($_SESSION["usertable"]["usertype"]=="judge") $ver = true; + +if ($s["currenttime"] >= $s["sitelastmilescore"] && $ver) + echo "<br><center>Scoreboard frozen</center>"; + +require('scoretable.php'); +?> + +</body> +</html> diff --git a/boca-1.5.0/src/scoretable.php b/boca-1.5.0/src/scoretable.php new file mode 100644 index 0000000..05b9280 --- /dev/null +++ b/boca-1.5.0/src/scoretable.php @@ -0,0 +1,355 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA System (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +//Last updated 10/jul/2012 by cassio@ime.usp.br +require_once("db.php"); + +$locr=$_SESSION["locr"]; + +if(isset($_GET["clock"]) && $_GET["clock"]==1) { + ob_start(); + header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Cache-Control: no-cache, must-revalidate"); + header ("Pragma: no-cache"); + header ("Content-Type: text/html; charset=utf-8"); + session_start(); + ob_end_flush(); + + if(!isset($contest) || !isset($localsite)) { + $ct=DBGetActiveContest(); + $contest=$ct['contestnumber']; + $localsite=$ct['contestlocalsite']; + } + if (($blocal = DBSiteInfo($contest, $localsite)) == null) { + echo "0"; + exit; + } + if(isset($blocal['currenttime'])) + echo $blocal["currenttime"]; + else echo "0"; + exit; +} +if(isset($_GET['remote']) && is_numeric($_GET['remote'])) { + ob_start(); + header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); + header ("Cache-Control: no-cache, must-revalidate"); + header ("Pragma: no-cache"); + header ("Content-Type: text/html; charset=utf-8"); + session_start(); + ob_end_flush(); + + if (isset($_SESSION["usertable"])) { + $_SESSION["usertable"] = DBUserInfo($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], $_SESSION["usertable"]["usernumber"]); + } else { + IntrusionNotify("scoretable1"); + ForceLoad("index.php"); + } + if(!isset($_SESSION['usertable']['usertype']) || $_SESSION["usertable"]["usertype"] != "score") { + IntrusionNotify("scoretable2"); + ForceLoad("index.php"); + } +} + +if(!ValidSession()) { + InvalidSession("scoretable.php"); + ForceLoad("index.php"); +} +$loc = $_SESSION["loc"]; +if(!isset($detail)) $detail=true; +if(!isset($final)) $final=false; +$scoredelay["admin"] = 1; +$scoredelay["score"] = 30; +$scoredelay["team"] = 30; +$scoredelay["judge"] = 10; +$scoredelay["staff"] = 60; +$actualdelay = 60; +if(isset($scoredelay[$_SESSION["usertable"]["usertype"]])) $actualdelay = $scoredelay[$_SESSION["usertable"]["usertype"]]; +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +$scoretmp = $_SESSION["locr"] . $ds . "private" . $ds . "scoretmp" . $ds . $_SESSION["usertable"]["usertype"] . ".php"; +$redo = TRUE; +if(file_exists($scoretmp)) { + if(($strtmp = file_get_contents($scoretmp,FALSE,NULL,-1,100000)) !== FALSE) { + list($d) = sscanf($strtmp,"%*s %d"); + if($d > time() - $actualdelay) { + $redo = FALSE; + } + } +} + +if(isset($_GET["remote"])) { + if(is_numeric($_GET["remote"])) { + if($_GET["remote"]==-42) { + $remotedir = $_SESSION['locr'] . $ds . "private" . $ds . "remotescores"; + $destination = $remotedir . $ds ."scores.zip"; + if($redo || !is_readable($destination)) { + if (($s = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("index.php"); + + $level=$s["sitescorelevel"]; + $data0 = array(); + if($level>0) { + list($score,$data0) = DBScoreSite($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], 1, -1); + } + $ct=DBGetActiveContest(); + $localsite=$ct['contestlocalsite']; + $fname = $remotedir . $ds . "score_site" . $localsite . "_" . md5($_SERVER['HTTP_HOST']); + file_put_contents($fname . ".tmp",base64_encode(serialize($data0))); + rename($fname . ".tmp",$fname . ".dat"); + + if(create_zip($remotedir,glob($remotedir . '/*.dat'),$destination)!==true) { + LOGError("Cannot create score zip file"); + } else { + create_zip($remotedir,array(),$destination); + } + } + echo file_get_contents($destination); + } else { + if (($s = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("index.php"); + + $level=$s["sitescorelevel"]; + $score = array(); + if($level>0) { + list($score,$data0) = DBScoreSite($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], 1, -1, $_GET["remote"]); + } + echo base64_encode(serialize($score)); + } + } else { + echo base64_encode(serialize(array())); + } + exit; +} + +if(!$redo) { + $conf=globalconf(); + $strtmp = decryptData(substr($strtmp,strpos($strtmp,"\n")),$conf["key"],'score'); + if($strtmp=="") $redo=TRUE; +} +if($redo) { + $strtmp = "<script language=\"JavaScript\" src=\"" . $loc . "/hide.js\"></script>\n"; + $pr = DBGetProblems($_SESSION["usertable"]["contestnumber"]); + + $ct=DBGetActiveContest(); + $contest=$ct['contestnumber']; + $duration=$ct['contestduration']; + + if(!isset($hor)) $hor = -1; + if($hor>$duration) $hor=$duration; + + $level=$s["sitescorelevel"]; + if($level<=0) $level=-$level; + else { + $des=true; + } + + if (($s = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("index.php"); + $score = DBScore($_SESSION["usertable"]["contestnumber"], $ver, $hor*60, $s["siteglobalscore"]); + + if ($_SESSION["usertable"]["usertype"]!="score" && $_SESSION["usertable"]["usertype"]!="admin" && $level>3) $level=3; + + $minu = 3; + $rn = DBRecentNews($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], $ver, $minu); + if(count($rn)>0 && $level>3) { + $strtmp .= "<table border=0><tr>"; + $strtmp .= "<td>News (last ${minu}'): </td>\n"; + for($i=0; $i<count($rn); $i++) { + $strtmp .= "<td width=200>"; + if($rn[$i]["yes"]=='t') { + $strtmp .= "<img alt=\"".$rn[$i]["colorname"].":\" width=\"28\" ". + "src=\"" . balloonurl($rn[$i]["color"]) ."\" />"; + } + else + $strtmp .= "<img alt=\"\" width=\"22\" ". + "src=\"$loc/images/bigballoontransp-blink.gif\" />\n"; + $strtmp .= $rn[$i]["problemname"] . ": " . $rn[$i]["userfullname"] . " (" . ((int) ($rn[$i]["time"]/60)) . "')"; + $strtmp .= "</td>\n"; + } + $strtmp .= "</tr></table>"; + } + if($hor>=0) { + $strtmp .= "<center>As of $hor minutes. Next: "; + for($h=-30; $h<40; $h+=10) { + if($hor+$h>=0 && $h!=0) { + $strtmp .= "<a href=\"$loc/admin/report/score.php?p=0&hor=" . ($hor+$h) . "\">"; + if($h>0) $strtmp .= "+"; + $strtmp .= "$h</a> "; + } + } + $strtmp .= "</center><br>"; + } + if(is_readable($_SESSION["locr"] . $ds . 'private' . $ds . 'score.sep')) { + $rf=file($_SESSION["locr"] . $ds . 'private' . $ds . 'score.sep'); + $strtmp .= "<br><img src=\"$loc/images/smallballoontransp.png\" alt=\"\" onload=\"javascript:toggleGroup(1)\"> <b>Available scores:</b> \n"; + for($rfi=1;$rfi<=count($rf);$rfi++) { + $lin = explode('#',trim($rf[$rfi-1])); + if(isset($lin[1]) && $_SESSION["usertable"]["usertype"]!='admin') { + $arr=explode(' ',trim($lin[1])); + for($arri=0;$arri<count($arr);$arri++) + if(preg_match($arr[$arri],$_SESSION["usertable"]["username"])) break; + if($arri>=count($arr)) continue; + } + $lin = trim($lin[0]); + if($lin=='') continue; + $grname=explode(' ',$lin); + $class=1; + reset($score); + while(list($e,$c) = each($score)) { + if(!isset($score[$e]['classingroup'])) $score[$e]['classingroup']=array(); + for($k=1;$k<count($grname);$k++) { + if($score[$e]['site']==$grname[$k]) { + $score[$e]['classingroup'][$rfi]=$class; + $class++; + } + } + } + if($class>1) + $strtmp .= "<a href=\"#\" onclick=\"javascript:toggleGroup($rfi)\">" . $grname[0] . "</a> "; + } + $strtmp .= "<br>\n"; + } else { + reset($score); + $class = 1; + while(list($e,$c) = each($score)) { + $score[$e]['classingroup'][1]=$class; + $class++; + } + } + + $strtmp .= "<br>\n<table id=\"myscoretable\" width=\"100%\" border=1>\n <tr>\n <td><b>#</b></td>\n <td><b>User</b></td>\n <td><b>Name</b></td>\n"; + if(!$des) { + if($level>0) + $strtmp .= "<td><b>Problems</b></td>"; + } else if($detail) { + for($i=0;$i<count($pr);$i++) + $strtmp .= "<td nowrap><b>" . $pr[$i]["problem"] . " </b></td>"; + } + $strtmp .= "<td><b>Total</b></td>\n"; + $strtmp .= "</tr>\n"; + $n=0; + reset($score); + while(list($e, $c) = each($score)) { + reset($score[$e]['classingroup']); + while(list($cg1,$cg2) = each($score[$e]['classingroup'])) { + $strtmp .= " <tr class=\""; + $strtmp .= "sitegroup" . $cg1 . "\">"; + $strtmp .= "<td>" . $cg2 . "</td>\n"; +/* + if($level>3 && !$final && $score[$e]["site"]==$ct['contestlocalsite'] && + ((isset($_SESSION["scorepos"][$score[$e]["username"]."-".$score[$e]["site"]]) && + $_SESSION["scorepos"][$score[$e]["username"]."-".$score[$e]["site"]] > $cg2) || + (isset($_SESSION["scoreblink"][$score[$e]["username"]."-".$score[$e]["site"]]) && + $_SESSION["scoreblink"][$score[$e]["username"]."-".$score[$e]["site"]]>time()))) { + $strtmp .= " <td nowrap bgcolor=\"#b0b0a0\">" . $score[$e]["username"]."/".$score[$e]["site"]; + $strtmp .= "<td bgcolor=\"#b0b0a0\">" . $score[$e]["userfullname"]; + if(!isset($_SESSION["scoreblink"][$score[$e]["username"]."-".$score[$e]["site"]]) || + $_SESSION["scoreblink"][$score[$e]["username"]."-".$score[$e]["site"]]==0) { + $_SESSION["scoreblink"][$score[$e]["username"]."-".$score[$e]["site"]] = time()+1; + } + } + else { +*/ + $_SESSION["scoreblink"][$score[$e]["username"]."-".$score[$e]["site"]]=0; + $strtmp .= " <td nowrap>" . $score[$e]["username"]."/".$score[$e]["site"] . " "; + $strtmp .= "<td>" . $score[$e]["userfullname"]; +// } + $_SESSION["scorepos"][$score[$e]["username"]."-".$score[$e]["site"]] = $cg2; + +// $strtmp .= "(" . $score[$e]["site"] . ")"; +// $strtmp .= "</td>\n"; +// if(!$detail && $score[$e]["userdesc"]!="") +// $strtmp .= "(" . $score[$e]["userdesc"] . ")"; + $strtmp .= "</td>"; + if($level > 0) { + if(!$des) $strtmp .= "<td>"; + for($h=0;$h<count($pr);$h++) { + $ee = $pr[$h]["number"]; + if($detail) { + if($des) { + $strtmp .= "<td nowrap>"; +// $name=$score[$e]["problem"][$ee]["name"]; + if(isset($score[$e]["problem"][$ee]["solved"]) && $score[$e]["problem"][$ee]["solved"]) { + $strtmp .= "<img alt=\"".$score[$e]["problem"][$ee]["colorname"].":\" width=\"18\" ". + "src=\"" . balloonurl($score[$e]["problem"][$ee]["color"]) ."\" />"; + } + else { + if($level>3 && isset($score[$e]["problem"][$ee]["judging"]) && $score[$e]["problem"][$ee]["judging"]) + $strtmp .= "<img alt=\"\" width=\"18\" ". + "src=\"$loc/images/bigballoontransp-blink.gif\" />\n"; + else + $strtmp .= " "; + } + } + if ($ver && $level<3) { + if(isset($score[$e]["problem"][$ee]["solved"]) && $score[$e]["problem"][$ee]["solved"]) { + if ($level==1) { + $strtmp .= "/". $score[$e]["problem"][$ee]["time"] . "\n"; + } + else + $strtmp .= $score[$e]["problem"][$ee]["count"] . "/" . + $score[$e]["problem"][$ee]["time"] . "\n"; + } else if($des) $strtmp .= " "; + } + else { + if (isset($score[$e]["problem"][$ee]['count']) && $score[$e]["problem"][$ee]["count"]!=0) { + $tn = $score[$e]["problem"][$ee]["count"]; + if (isset($score[$e]["problem"][$ee]["solved"]) && $score[$e]["problem"][$ee]["solved"]) $t = $score[$e]["problem"][$ee]["time"]; + else $t = "-"; + $strtmp .= "<font size=\"-2\">" . $tn . "/${t}" . "</font>\n"; + } else if($des) $strtmp .= " "; + } + if($des) + $strtmp .= "</td>"; + } + } + if(!$des) $strtmp .= " </td>\n"; + } + $strtmp .= " <td nowrap>" . + $score[$e]["totalcount"] . " (" . $score[$e]["totaltime"] . ")</td>\n"; + $strtmp .= " </tr>\n"; + $n++; + } + } + $strtmp .= "</table>"; + if ($n == 0) $strtmp .= "<br><center><b><font color=\"#ff0000\">SCOREBOARD IS EMPTY</font></b></center>"; + else { + if(!$des) + if($level>0) $strtmp .= "<br><font color=\"#ff0000\">P.S. Problem names are hidden.</font>"; + else $strtmp .= "<br><font color=\"#ff0000\">P.S. Problem data are hidden.</font>"; + } + + $conf=globalconf(); + $strtmp = "<!-- " . time() . " --> <?php exit; ?>\n" . encryptData($strtmp,$conf["key"],false); + if(file_put_contents($scoretmp, $strtmp,LOCK_EX)===FALSE) { + if($_SESSION["usertable"]["usertype"] == 'admin') { + MSGError("Cannot write to the score cache file -- performance might be compromised"); + } + LOGError("Cannot write to the ".$_SESSION["usertable"]["usertype"]."-score cache file -- performance might be compromised"); + } + $conf=globalconf(); + $strtmp = decryptData(substr($strtmp,strpos($strtmp,"\n")),$conf["key"]); +} +echo $strtmp; +?> diff --git a/boca-1.5.0/src/sha256.js b/boca-1.5.0/src/sha256.js new file mode 100644 index 0000000..1c6b7e7 --- /dev/null +++ b/boca-1.5.0/src/sha256.js @@ -0,0 +1,339 @@ +/* + * A JavaScript implementation of the Secure Hash Algorithm, SHA-256, as defined + * in FIPS 180-2 + * Version 2.2 Copyright Angel Marin, Paul Johnston 2000 - 2009. + * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet + * Distributed under the BSD License + * See http://pajhome.org.uk/crypt/md5 for details. + * Also http://anmar.eu.org/projects/jssha2/ + */ + +function js_myhash(s) { return hex_sha256(s); } + +/* + * Configurable variables. You may need to tweak these to be compatible with + * the server-side, but the defaults work in most cases. + */ +var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */ +var b64pad = ""; /* base-64 pad character. "=" for strict RFC compliance */ + +/* + * These are the functions you'll usually want to call + * They take string arguments and return either hex or base-64 encoded strings + */ +function hex_sha256(s) { return rstr2hex(rstr_sha256(str2rstr_utf8(s))); } +function b64_sha256(s) { return rstr2b64(rstr_sha256(str2rstr_utf8(s))); } +function any_sha256(s, e) { return rstr2any(rstr_sha256(str2rstr_utf8(s)), e); } +function hex_hmac_sha256(k, d) + { return rstr2hex(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); } +function b64_hmac_sha256(k, d) + { return rstr2b64(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d))); } +function any_hmac_sha256(k, d, e) + { return rstr2any(rstr_hmac_sha256(str2rstr_utf8(k), str2rstr_utf8(d)), e); } + +/* + * Perform a simple self-test to see if the VM is working + */ +function sha256_vm_test() +{ + return hex_sha256("abc").toLowerCase() == + "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"; +} + +/* + * Calculate the sha256 of a raw string + */ +function rstr_sha256(s) +{ + return binb2rstr(binb_sha256(rstr2binb(s), s.length * 8)); +} + +/* + * Calculate the HMAC-sha256 of a key and some data (raw strings) + */ +function rstr_hmac_sha256(key, data) +{ + var bkey = rstr2binb(key); + if(bkey.length > 16) bkey = binb_sha256(bkey, key.length * 8); + + var ipad = Array(16), opad = Array(16); + for(var i = 0; i < 16; i++) + { + ipad[i] = bkey[i] ^ 0x36363636; + opad[i] = bkey[i] ^ 0x5C5C5C5C; + } + + var hash = binb_sha256(ipad.concat(rstr2binb(data)), 512 + data.length * 8); + return binb2rstr(binb_sha256(opad.concat(hash), 512 + 256)); +} + +/* + * Convert a raw string to a hex string + */ +function rstr2hex(input) +{ + try { hexcase } catch(e) { hexcase=0; } + var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef"; + var output = ""; + var x; + for(var i = 0; i < input.length; i++) + { + x = input.charCodeAt(i); + output += hex_tab.charAt((x >>> 4) & 0x0F) + + hex_tab.charAt( x & 0x0F); + } + return output; +} + +/* + * Convert a raw string to a base-64 string + */ +function rstr2b64(input) +{ + try { b64pad } catch(e) { b64pad=''; } + var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + var output = ""; + var len = input.length; + for(var i = 0; i < len; i += 3) + { + var triplet = (input.charCodeAt(i) << 16) + | (i + 1 < len ? input.charCodeAt(i+1) << 8 : 0) + | (i + 2 < len ? input.charCodeAt(i+2) : 0); + for(var j = 0; j < 4; j++) + { + if(i * 8 + j * 6 > input.length * 8) output += b64pad; + else output += tab.charAt((triplet >>> 6*(3-j)) & 0x3F); + } + } + return output; +} + +/* + * Convert a raw string to an arbitrary string encoding + */ +function rstr2any(input, encoding) +{ + var divisor = encoding.length; + var remainders = Array(); + var i, q, x, quotient; + + /* Convert to an array of 16-bit big-endian values, forming the dividend */ + var dividend = Array(Math.ceil(input.length / 2)); + for(i = 0; i < dividend.length; i++) + { + dividend[i] = (input.charCodeAt(i * 2) << 8) | input.charCodeAt(i * 2 + 1); + } + + /* + * Repeatedly perform a long division. The binary array forms the dividend, + * the length of the encoding is the divisor. Once computed, the quotient + * forms the dividend for the next step. We stop when the dividend is zero. + * All remainders are stored for later use. + */ + while(dividend.length > 0) + { + quotient = Array(); + x = 0; + for(i = 0; i < dividend.length; i++) + { + x = (x << 16) + dividend[i]; + q = Math.floor(x / divisor); + x -= q * divisor; + if(quotient.length > 0 || q > 0) + quotient[quotient.length] = q; + } + remainders[remainders.length] = x; + dividend = quotient; + } + + /* Convert the remainders to the output string */ + var output = ""; + for(i = remainders.length - 1; i >= 0; i--) + output += encoding.charAt(remainders[i]); + + /* Append leading zero equivalents */ + var full_length = Math.ceil(input.length * 8 / + (Math.log(encoding.length) / Math.log(2))) + for(i = output.length; i < full_length; i++) + output = encoding[0] + output; + + return output; +} + +/* + * Encode a string as utf-8. + * For efficiency, this assumes the input is valid utf-16. + */ +function str2rstr_utf8(input) +{ + var output = ""; + var i = -1; + var x, y; + + while(++i < input.length) + { + /* Decode utf-16 surrogate pairs */ + x = input.charCodeAt(i); + y = i + 1 < input.length ? input.charCodeAt(i + 1) : 0; + if(0xD800 <= x && x <= 0xDBFF && 0xDC00 <= y && y <= 0xDFFF) + { + x = 0x10000 + ((x & 0x03FF) << 10) + (y & 0x03FF); + i++; + } + + /* Encode output as utf-8 */ + if(x <= 0x7F) + output += String.fromCharCode(x); + else if(x <= 0x7FF) + output += String.fromCharCode(0xC0 | ((x >>> 6 ) & 0x1F), + 0x80 | ( x & 0x3F)); + else if(x <= 0xFFFF) + output += String.fromCharCode(0xE0 | ((x >>> 12) & 0x0F), + 0x80 | ((x >>> 6 ) & 0x3F), + 0x80 | ( x & 0x3F)); + else if(x <= 0x1FFFFF) + output += String.fromCharCode(0xF0 | ((x >>> 18) & 0x07), + 0x80 | ((x >>> 12) & 0x3F), + 0x80 | ((x >>> 6 ) & 0x3F), + 0x80 | ( x & 0x3F)); + } + return output; +} + +/* + * Encode a string as utf-16 + */ +function str2rstr_utf16le(input) +{ + var output = ""; + for(var i = 0; i < input.length; i++) + output += String.fromCharCode( input.charCodeAt(i) & 0xFF, + (input.charCodeAt(i) >>> 8) & 0xFF); + return output; +} + +function str2rstr_utf16be(input) +{ + var output = ""; + for(var i = 0; i < input.length; i++) + output += String.fromCharCode((input.charCodeAt(i) >>> 8) & 0xFF, + input.charCodeAt(i) & 0xFF); + return output; +} + +/* + * Convert a raw string to an array of big-endian words + * Characters >255 have their high-byte silently ignored. + */ +function rstr2binb(input) +{ + var output = Array(input.length >> 2); + for(var i = 0; i < output.length; i++) + output[i] = 0; + for(var i = 0; i < input.length * 8; i += 8) + output[i>>5] |= (input.charCodeAt(i / 8) & 0xFF) << (24 - i % 32); + return output; +} + +/* + * Convert an array of big-endian words to a string + */ +function binb2rstr(input) +{ + var output = ""; + for(var i = 0; i < input.length * 32; i += 8) + output += String.fromCharCode((input[i>>5] >>> (24 - i % 32)) & 0xFF); + return output; +} + +/* + * Main sha256 function, with its support functions + */ +function sha256_S (X, n) {return ( X >>> n ) | (X << (32 - n));} +function sha256_R (X, n) {return ( X >>> n );} +function sha256_Ch(x, y, z) {return ((x & y) ^ ((~x) & z));} +function sha256_Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));} +function sha256_Sigma0256(x) {return (sha256_S(x, 2) ^ sha256_S(x, 13) ^ sha256_S(x, 22));} +function sha256_Sigma1256(x) {return (sha256_S(x, 6) ^ sha256_S(x, 11) ^ sha256_S(x, 25));} +function sha256_Gamma0256(x) {return (sha256_S(x, 7) ^ sha256_S(x, 18) ^ sha256_R(x, 3));} +function sha256_Gamma1256(x) {return (sha256_S(x, 17) ^ sha256_S(x, 19) ^ sha256_R(x, 10));} +function sha256_Sigma0512(x) {return (sha256_S(x, 28) ^ sha256_S(x, 34) ^ sha256_S(x, 39));} +function sha256_Sigma1512(x) {return (sha256_S(x, 14) ^ sha256_S(x, 18) ^ sha256_S(x, 41));} +function sha256_Gamma0512(x) {return (sha256_S(x, 1) ^ sha256_S(x, 8) ^ sha256_R(x, 7));} +function sha256_Gamma1512(x) {return (sha256_S(x, 19) ^ sha256_S(x, 61) ^ sha256_R(x, 6));} + +var sha256_K = new Array +( + 1116352408, 1899447441, -1245643825, -373957723, 961987163, 1508970993, + -1841331548, -1424204075, -670586216, 310598401, 607225278, 1426881987, + 1925078388, -2132889090, -1680079193, -1046744716, -459576895, -272742522, + 264347078, 604807628, 770255983, 1249150122, 1555081692, 1996064986, + -1740746414, -1473132947, -1341970488, -1084653625, -958395405, -710438585, + 113926993, 338241895, 666307205, 773529912, 1294757372, 1396182291, + 1695183700, 1986661051, -2117940946, -1838011259, -1564481375, -1474664885, + -1035236496, -949202525, -778901479, -694614492, -200395387, 275423344, + 430227734, 506948616, 659060556, 883997877, 958139571, 1322822218, + 1537002063, 1747873779, 1955562222, 2024104815, -2067236844, -1933114872, + -1866530822, -1538233109, -1090935817, -965641998 +); + +function binb_sha256(m, l) +{ + var HASH = new Array(1779033703, -1150833019, 1013904242, -1521486534, + 1359893119, -1694144372, 528734635, 1541459225); + var W = new Array(64); + var a, b, c, d, e, f, g, h; + var i, j, T1, T2; + + /* append padding */ + m[l >> 5] |= 0x80 << (24 - l % 32); + m[((l + 64 >> 9) << 4) + 15] = l; + + for(i = 0; i < m.length; i += 16) + { + a = HASH[0]; + b = HASH[1]; + c = HASH[2]; + d = HASH[3]; + e = HASH[4]; + f = HASH[5]; + g = HASH[6]; + h = HASH[7]; + + for(j = 0; j < 64; j++) + { + if (j < 16) W[j] = m[j + i]; + else W[j] = safe_add(safe_add(safe_add(sha256_Gamma1256(W[j - 2]), W[j - 7]), + sha256_Gamma0256(W[j - 15])), W[j - 16]); + + T1 = safe_add(safe_add(safe_add(safe_add(h, sha256_Sigma1256(e)), sha256_Ch(e, f, g)), + sha256_K[j]), W[j]); + T2 = safe_add(sha256_Sigma0256(a), sha256_Maj(a, b, c)); + h = g; + g = f; + f = e; + e = safe_add(d, T1); + d = c; + c = b; + b = a; + a = safe_add(T1, T2); + } + + HASH[0] = safe_add(a, HASH[0]); + HASH[1] = safe_add(b, HASH[1]); + HASH[2] = safe_add(c, HASH[2]); + HASH[3] = safe_add(d, HASH[3]); + HASH[4] = safe_add(e, HASH[4]); + HASH[5] = safe_add(f, HASH[5]); + HASH[6] = safe_add(g, HASH[6]); + HASH[7] = safe_add(h, HASH[7]); + } + return HASH; +} + +function safe_add (x, y) +{ + var lsw = (x & 0xFFFF) + (y & 0xFFFF); + var msw = (x >> 16) + (y >> 16) + (lsw >> 16); + return (msw << 16) | (lsw & 0xFFFF); +} diff --git a/boca-1.5.0/src/site/get.php b/boca-1.5.0/src/site/get.php new file mode 100644 index 0000000..81ede0d --- /dev/null +++ b/boca-1.5.0/src/site/get.php @@ -0,0 +1,167 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +header ("Content-transfer-encoding: binary\n"); +ob_end_flush(); + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) { + echo "<!-- <ERROR4> ".session_id() . " " . session_id() . " -->\n"; + exit; +} +if($ct["contestlocalsite"]==$ct["contestmainsite"]) { + $fromsite = $_SESSION["usertable"]["usericpcid"]; + LOGLevel("Connection received from site=$fromsite PHPID=".$_COOKIE['PHPSESSID'].",extra=".$_SESSION['usertable']['usersessionextra']. + ",session=".session_id().",name=".$getx['name'].", check=".$getx['check'],2); + if($fromsite != '' && is_numeric($fromsite) && $fromsite > 0) { + $siteinfo = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$fromsite); + $scores = explode(",", $siteinfo['siteglobalscore']); + if(count($scores)==0 || (count($scores)==1 && !is_numeric($scores[0]))) $scores=array($fromsite); + $judges = explode(",", $siteinfo['sitejudging']); + if(count($judges)==0 || (count($judges)==1 && !is_numeric($judges[0]))) $judges=array($fromsite); + $scores = array_unique(array_merge($scores,$judges)); + if(in_array(0,$scores)) $scores=null; + + $tasks = explode(",", $siteinfo['sitetasking']); + if(count($tasks)==0 || (count($tasks)==1 && !is_numeric($tasks[0]))) $tasks=array($fromsite); + } else { + echo "<!-- <ERROR9> ".session_id() . " " . session_id() . " -->\n"; + exit; + } + if(isset($_POST) && isset($_POST['xml'])) { +// $fp=fopen('/tmp/aaa',"w"); fwrite($fp,$_POST['xml']); fclose($fp); + $s = decryptData(rawurldecode($_POST['xml']),myhash($_SESSION["usertable"]["userpassword"])); +// $fp=fopen('/tmp/aaa1',"w"); fwrite($fp,$s); fclose($fp); + + $ac=array(); + $ac['SITEREC']=array( + 'site'=>$fromsite, + 'sitenumber'=>0, + 'number'=>0, + 'sitename'=>0, + 'siteip'=>0, + 'siteduration'=>0, + 'sitelastmileanswer'=>0, + 'sitelastmilescore'=>0, +// 'sitejudging'=>0, +// 'sitetasking'=>0, + 'siteautoend'=>0, +// 'siteglobalscore'=>0, + 'siteactive'=>0, + 'sitescorelevel'=>0, + 'sitepermitlogins'=>0, + 'siteautojudge'=>0, + 'sitenextuser'=>0, + 'sitenextclar'=>0, + 'sitenextrun'=>0, + 'sitenexttask'=>0, + 'sitemaxtask'=>0, + 'sitechiefname'=>0, + 'updatetime'=>0); + $ac['SITETIME']=array('site'=>$fromsite, + 'number'=>0, + 'start'=>0, + 'enddate'=>0, + 'updatetime'=>0); + $ac['USERREC']=array('site'=>$fromsite, + 'user'=>0, + 'number'=>0, + 'username'=>0, + 'usericpcid'=>0, + 'userfull'=>0, + 'userdesc'=>0, + 'type'=>0, + 'enabled'=>0, + 'multilogin'=>0, + 'userip'=>0, + 'userlastlogin'=>0, + 'userlastlogout'=>0, + 'permitip'=>0, + 'updatetime'=>0); + $ac['CLARREC']=array('site'=>$judges, + 'user'=>0, + 'number'=>0, + 'problem'=>0, + 'question'=>0, + 'clarnumber'=>0, + 'clardate'=>0, + 'clardatediff'=>0, + 'clardatediffans'=>0, + 'claranswer'=>0, + 'clarstatus'=>0, + 'clarjudge'=>0, + 'clarjudgesite'=>0, + 'updatetime'=>0); + $ac['RUNREC']=array('site'=>$judges, + 'user'=>0, + 'number'=>0, + 'runnumber'=>0, + 'problem'=>0, + 'lang'=>0, + 'filename'=>0, + 'filepath'=>0, + 'rundate'=>0, + 'rundatediff'=>0, + 'rundatediffans'=>0, + 'runanswer'=>0, + 'runstatus'=>0, + 'runjudge'=>0, + 'runjudgesite'=>0, + 'runjudge1'=>0, + 'runjudgesite1'=>0, + 'runanswer1'=>0, + 'runjudge2'=>0, + 'runjudgesite2'=>0, + 'runanswer2'=>0, + 'autoip'=>0, + 'autobegindate'=>0, + 'autoenddate'=>0, + 'autoanswer'=>0, + 'autostdout'=>0, + 'autostderr'=>0, + 'updatetime'=>0); + $ac['TASKREC']=array( + 'site'=>$tasks, + 'user'=>0, + 'desc'=>0, + 'number'=>0, + 'tasknumber'=>0, + 'color'=>0, + 'colorname'=>0, + 'updatetime'=>0, + 'filename'=>0, + 'filepath'=>0, + 'sys'=>0, + 'status'=>0, + 'taskdate'=>0, + 'taskdatediff'=>0, + 'taskdatediffans'=>0, + 'taskstaffnumber'=>0, + 'taskstaffsite'=>0); + + if(importFromXML($s,$ac,$_SESSION["usertable"]["contestnumber"])) + echo "<!-- <OK> -->"; + else + echo "<!-- <NOTOK> -->"; + } + $xml = generateXML($_SESSION["usertable"]["contestnumber"],0,$scores); + echo encryptData($xml,myhash($_SESSION["usertable"]["userpassword"])); +} else + echo "<!-- <ERROR3> ".session_id() . " " . session_id() . " -->\n"; +?> diff --git a/boca-1.5.0/src/site/header.php b/boca-1.5.0/src/site/header.php new file mode 100644 index 0000000..f1b47b3 --- /dev/null +++ b/boca-1.5.0/src/site/header.php @@ -0,0 +1,88 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +header ("Content-Type: text/html; charset=utf-8"); +session_start(); +//require_once('../version.php'); +require_once("../globals.php"); +require_once("../db.php"); + +if(!function_exists("globalconf") || !function_exists("sanitizeVariables")) { + ob_end_flush(); + ForceLoad("../index.php"); + exit; +} + +$getx=array(); +if(isset($_GET['name'])) $getx['name']=$_GET['name']; +if(isset($_GET['password'])) $getx['password']=$_GET['password']; +if(isset($_GET['check'])) $getx['check']=$_GET['check']; +//if(isset($_POST)) { +if(isset($_POST["name"])) $getx['name']=$_POST['name']; +if(isset($_POST["password"])) $getx['password']=$_POST['password']; +if(isset($_POST["check"])) $getx['check']=$_POST['check']; +//} +//LOGError("PHPID=".$_COOKIE['PHPSESSID'].",extra=".$_SESSION['usertable']['usersessionextra']. +// ",session=".session_id().",name=".$getx['name'].", password=".$getx['password'].",check=".$getx['check']); +if (!isset($_SESSION["usertable"])) { + if(isset($getx['name']) && $getx['name'] != "" && isset($getx['password']) && $getx['password'] != "") { + $name = $getx["name"]; + LogLevel("Connection try by IP " . getIP() . ", username=" . $name,2); + $password = $getx["password"]; + $usertable = DBLogIn($name, $password, false); + if(!$usertable) { + ob_end_flush(); + echo "<!-- <ERROR1> ". session_id() . " " . session_id() . " -->\n"; + exit; + } + if(!isset($getx['check'])) { + ob_end_flush(); + echo "<!-- <ERROR2> ". session_id() . " " . session_id() . " -->\n"; + exit; + } + } else { + ob_end_flush(); + LogLevel("Init connection by IP " . getIP(),2); + echo "<!-- <SESSION1> ". session_id() . " " . session_id() . " -->\n"; + exit; + } +} +if(!ValidSession()) { + ob_end_flush(); + InvalidSession("site/index.php"); + ForceLoad("../index.php"); + exit; +} +if(isset($getx['check']) && isset($getx["password"]) && $getx['check'] != myhash($getx["password"] . $_SESSION['usertable']['userpassword'])) { + ob_end_flush(); + echo "<!-- <SESSION2> ". session_id() . " " . $_SESSION['usertable']['usersessionextra'] . " -->\n"; + exit; +} + +if($_SESSION["usertable"]["usertype"] != "site") { + ob_end_flush(); + IntrusionNotify("site/index.php"); + ForceLoad("../index.php"); + exit; +} +?> diff --git a/boca-1.5.0/src/site/index.php b/boca-1.5.0/src/site/index.php new file mode 100644 index 0000000..3b066ab --- /dev/null +++ b/boca-1.5.0/src/site/index.php @@ -0,0 +1,312 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +require('header.php'); +if(isset($_GET['mainuser']) && isset($_GET['mainpass']) && $_GET['mainuser']!="" && $_GET['mainpass']!="") { + $_SESSION['mainuser'] = $_GET['mainuser']; + $_SESSION['mainpass'] = $_GET['mainpass']; + $_SESSION['check'] = $_GET['check']; + unset($_GET['mainuser']); + unset($_GET['mainpass']); + unset($_GET['check']); + ForceLoad('index.php'); +} +$smi = isset($_SESSION['mainid'])? $_SESSION['mainid']: ""; +$smu = isset($_SESSION['mainuser'])? $_SESSION['mainuser']: ""; +$smp = isset($_SESSION['mainpass'])? $_SESSION['mainpass']: ""; +$smc = isset($_SESSION['check'])? $_SESSION['check']: ""; +//MSGError("id=".$smi." user=".$smu." pass=".$smp. " check=".$smc); + +echo "<html><head><title>Site Page</title>\n"; +echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"; +echo "<link rel=stylesheet href=\"../Css.php\" type=\"text/css\">\n"; +if ($smp != $smc && $smp != '' && $smc != '') + echo "<meta http-equiv=\"refresh\" content=\"60\" />"; + +if ($smu != '') + echo "</head><body onload=\"document.form1.password.focus()\"><table border=1 width=\"100%\">\n"; +else + echo "</head><body onload=\"document.form1.name.focus()\"><table border=1 width=\"100%\">\n"; +echo "<tr><td nowrap bgcolor=\"#ff00ff\" align=center>"; +echo "<img src=\"../images/smallballoontransp.png\" alt=\"\">"; +echo "<font color=\"#000000\">BOCA</font>"; +echo "</td><td bgcolor=\"#ff00ff\" width=\"99%\">\n"; +echo "Username: " . $_SESSION["usertable"]["userfullname"] . " (site=".$_SESSION["usertable"]["usersitenumber"].")<br>\n"; +list($clockstr,$clocktype)=siteclock(); +echo "</td><td bgcolor=\"#ff00ff\" align=center nowrap> ".$clockstr." </td></tr>\n"; +echo "</table>\n"; +echo "<table border=0 width=\"100%\" align=center>\n"; +echo " <tr>\n"; +echo " <td align=center><a class=menu style=\"font-weight:bold\" href=../index.php>Logout</a></td>\n"; +echo " </tr>\n"; +echo "</table>\n"; + +list($t,$id,$idextra) = getMainXML($smu,$smi,$smp,$smc); +//MSGError("t=". ($t==false?"false":"true") ." id=$id idextra=$idextra"); +if($t==false) + $_SESSION['mainid'] = $id; +$_SESSION['mainok'] = $t; + +if(!$t) { + unset($_GET['mainuser']); + unset($_GET['mainpass']); + unset($_GET['check']); + unset($_SESSION["mainuser"]); + unset($_SESSION["mainpass"]); + unset($_SESSION["check"]); +?> +<script language="JavaScript" src="../sha256.js"></script> +<script language="JavaScript"> +function computeHASH() +{ + var userHASH, passHASH, passHASH2; + userHASH = document.form1.name.value; + <?php if(strlen($id) > 20 && strlen($idextra) > 20) { ?> + tmpv = js_myhash(document.form1.password.value); + passHASH = js_myhash(tmpv+'<?php echo $id; ?>'); + passHASH2 = js_myhash(tmpv+'<?php echo $idextra; ?>'); + <?php } ?> + tmpv = ' '; + document.form1.name.value = ''; + document.form1.password.value = ' '; + document.location = 'index.php?mainuser='+userHASH+'&mainpass='+passHASH+'&check='+passHASH2; +} +</script> +<table width="100%" height="100%" border="0"> + <tr align="center" valign="middle"> + <td> + <form name="form1" action="javascript:computeHASH()"> + <div align="center"> + <table border="0" align="center"> +<?php + if($id == '' || $idextra=='') { +?> + <input type="hidden" name="name" value=""> + <input type="hidden" name="password" value=""> + <tr> + <td nowrap> + <div align="center"><font face="Verdana, Arial, Helvetica, sans-serif" size="+1"> +Cannot access main server. Check IP address,<br> password and internet connection, then press OK.</font></div> + </td> + </tr> + <tr> + <td valign="top"> + <center><input type="submit" name="Submit" value="OK"></center> + </td> + </tr> +<?php + } else { +?> + <tr> + <td nowrap> + <div align="center"><font face="Verdana, Arial, Helvetica, sans-serif" size="+1"> + <?php + if($id==$idextra) { + $contest=$_SESSION["usertable"]["contestnumber"]; + $ct = DBContestInfo($contest); + echo "Credentials to connect to main server<br>"; + echo "at URL: " . $ct['contestmainsiteurl']; + } else + echo "<u>Status</u>: initial connection established<br><br>To guarantee an encrypted connection, please type the same password again:"; +?> + </font></div> + </td> + </tr> + <tr> + <td valign="top"> + <table border="0" align="left"> + <tr> + <td><font face="Verdana, Arial, Helvetica, sans-serif" > + Name + </font></td> + <td> + <input type="text" name="name" value="<?php echo $smu; ?>"> + </td> + </tr> + <tr> + <td><font face="Verdana, Arial, Helvetica, sans-serif" >Password</font></td> + <td> + <input type="password" name="password"> + </td> + </tr> + </table> + <input type="submit" name="Submit" value="Login"> + </td> + </tr> +<?php } ?> + </table> + </div> + </form> + </td> + </tr> +</table> +<?php +} else { + if($idextra == "<OK>") + echo "<u>Data sent correctly to main server</u><br><br>"; + else + echo "<u>Error sending data to main server</u><br><br>"; + $ac['CONTESTREC']=array('number'=>-1, + 'name'=>-1, + 'startdate'=>-1, + 'duration'=>-1, + 'lastmileanswer'=>-1, + 'lastmilescore'=>-1, + 'penalty'=>-1, + 'maxfilesize'=>-1, + 'updatetime'=>-1); + $ac['ANSWERREC']=array('number'=>-1, + 'name'=>-1, + 'yes'=>-1, + 'updatetime'=>-1); + $ac['LANGUAGEREC']=array('number'=>-1, + 'name'=>-1, + 'filepath'=>-1, + 'filename'=>-1, + 'comppath'=>-1, + 'compname'=>-1, + 'problemnumber'=>-1, + 'updatetime'=>-1); + $ac['PROBLEMREC']=array('number'=>-1, + 'name'=>-1, + 'fullname'=>-1, + 'basename'=>-1, + 'inputfilename'=>-1, + 'inputfilepath'=>-1, + 'solfilename'=>-1, + 'solfilepath'=>-1, + 'descfilename'=>-1, + 'descfilepath'=>-1, + 'tl'=>-1, +// 'colorname'=>-1, +// 'color'=>-1, + 'fake'=>-1, + 'updatetime'=>-1); + $ac['SITETIME']=array('site'=>-1, + 'start'=>-1, + 'enddate'=>-1, + 'updatetime'=>-1); + $ac['SITEREC']=array('sitenumber'=>-1, + 'site'=>-1, + 'number'=>-1, + 'sitename'=>-1, + 'siteip'=>-1, + 'siteduration'=>-1, + 'sitelastmileanswer'=>-1, + 'sitelastmilescore'=>-1, + 'sitejudging'=>-1, + 'sitetasking'=>-1, + 'siteautoend'=>-1, + 'siteglobalscore'=>-1, + 'siteactive'=>-1, + 'sitescorelevel'=>-1, + 'sitepermitlogins'=>-1, + 'siteautojudge'=>-1, + 'sitenextuser'=>-1, + 'sitenextclar'=>-1, + 'sitenextrun'=>-1, + 'sitenexttask'=>-1, + 'sitemaxtask'=>-1, + 'sitechiefname'=>-1, + 'updatetime'=>-1); + $ac['USERREC']=array('site'=>-1, + 'user'=>-1, + 'number'=>-1, + 'username'=>-1, + 'updatetime'=>-1, + 'usericpcid'=>-1, + 'userfull'=>-1, + 'userdesc'=>-1, + 'type'=>-1, + 'enabled'=>-1, + 'multilogin'=>-1, + 'userip'=>-1, + 'userlastlogin'=>-1, + 'userlastlogout'=>-1, + 'permitip'=>-1); + $ac['CLARREC']=array('site'=>-1, + 'user'=>-1, + 'number'=>-1, + 'problem'=>-1, + 'question'=>-1, + 'clarnumber'=>-1, + 'clardate'=>-1, + 'clardatediff'=>-1, + 'clardatediffans'=>-1, + 'claranswer'=>-1, + 'clarstatus'=>-1, + 'clarjudge'=>-1, + 'clarjudgesite'=>-1, + 'updatetime'=>-1); + $ac['RUNREC']=array('site'=>-1, + 'user'=>-1, + 'number'=>-1, + 'runnumber'=>-1, + 'problem'=>-1, + 'lang'=>-1, + 'filename'=>-1, + 'filepath'=>-1, + 'rundate'=>-1, + 'rundatediff'=>-1, + 'rundatediffans'=>-1, + 'runanswer'=>-1, + 'runstatus'=>-1, + 'runjudge'=>-1, + 'runjudgesite'=>-1, + 'runjudge1'=>-1, + 'runjudgesite1'=>-1, + 'runanswer1'=>-1, + 'runjudge2'=>-1, + 'runjudgesite2'=>-1, + 'runanswer2'=>-1, + 'autoip'=>-1, + 'autobegindate'=>-1, + 'autoenddate'=>-1, + 'autoanswer'=>-1, + 'autostdout'=>-1, + 'autostderr'=>-1, + 'updatetime'=>-1); + $ac['TASKREC']=array( + 'site'=>-1, + 'user'=>-1, + 'desc'=>-1, + 'number'=>-1, + 'tasknumber'=>-1, + 'color'=>-1, + 'colorname'=>-1, + 'updatetime'=>-1, + 'filename'=>-1, + 'filepath'=>-1, + 'sys'=>-1, + 'status'=>-1, + 'taskdate'=>-1, + 'taskdatediff'=>-1, + 'taskdatediffans'=>-1, + 'taskstaffnumber'=>-1, + 'taskstaffsite'=>-1); + + if(importFromXML($id,$ac,$_SESSION["usertable"]["contestnumber"])) + echo "<u>Data received correctly from main server at " . dateconv(time()) . "</u>"; + else + echo "<u>Error receiving data from main server at ". dateconv(time()) . "</u>"; +// echo "<pre>" . $id . "</pre>"; + echo "<br><br><b>waiting for next round...</b>"; +} +?> +</body> +</html> diff --git a/boca-1.5.0/src/site/putfile.php b/boca-1.5.0/src/site/putfile.php new file mode 100644 index 0000000..d320a1a --- /dev/null +++ b/boca-1.5.0/src/site/putfile.php @@ -0,0 +1,171 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +//Last updated 10/jul/2012 by cassio@ime.usp.br +// +//PC^2 integration developed by Fabio Antonio Avellaneda Pachon +$quiet=true; +require 'header.php'; +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; +$remotedir=$ds . "private" . $ds . "remotescores"; + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) +exit; +if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) +exit; + +if(is_writable($_SESSION["locr"] . $remotedir)) { + if(isset($_POST['PC2']) && is_numeric($_POST['PC2']) && $_POST['PC2'] > 0) { + $site = $_POST['PC2']; + $problemCount = 4; + for($i=0;$i<$problemCount;$i++) { + $problems[$i]["name"]=chr($i+ord("A")); + $problems[$i]["color"]="FFFFFF"; + $problems[$i]["colorname"]="white"; + $problems[$i]["solved"]=0; + $problems[$i]["judging"]=false; + $problems[$i]["time"]=0; + $problems[$i]["penalty"]=0; + $problems[$i]["count"]=0; + } + + /*** Load PC2 summary.html **/ + $board=base64_decode($_POST['data']); + + /*** a new dom object ***/ + $dom = new domDocument; + + /*** load the html into the object ***/ + $dom->loadHTML($board); + + /*** discard white space ***/ + $dom->preserveWhiteSpace = false; + + /*** the table by its tag name ***/ + $tables = $dom->getElementsByTagName('table'); + + /*** get all rows from the table ***/ + $rows = $tables->item(0)->getElementsByTagName('tr'); + + /*** loop over the table rows ***/ + $userCount = 1; + $firstProblem=-1; + foreach ($rows as $row) + { + //teams are always being renumbered since their number is not important... just they have to be different + $team["user"]=(string)$userCount; + $team["site"]=(string)$site; + + /*** get each column by tag name ***/ + $cols = $row->getElementsByTagName('td'); + $colCount=0; + $probCount=1; + //Ignore empty cols + if($cols->item(0)->nodeValue=="") + { + continue; + } + foreach ($cols as $col) + { + switch($colCount) + { + //First column, start the problem counter and by default, the team hasnt solved a problem + case 0; + $probCount=1; + $firstProblem=-1; + break; + //First column: team name + case 1: + $team["username"]=$col->nodeValue; +// echo "username: $col->nodeValue\n"; + $team["usertype"]="team"; + $team["userfullname"]=$col->nodeValue; + break; + //Second column: How many problems does the team solved at this time + case 2: + $team["totalcount"]=(int)$col->nodeValue; + // echo "totalcount: $col->nodeValue\n"; + break; + //Third column: Elapsed time, including penalisations + case 3: + $team["totaltime"]=$col->nodeValue; + // echo "totaltime: $col->nodeValue\n"; + break; + //No more problems to process + case $problemCount+4: + $total[$userCount-1]=$team; + //If firstProblem is different to -1 is because the team has solved at least one problem + if($firstProblem!=-1) + { + $total[$userCount-1]["first"]=$firstProblem; + } + break; + //Problems columns + default: + list($count, $time) = split('/', $col->nodeValue); + //echo "Sol: $solved / time: $count"; + if($time=="--") + { + $solved=false; + $time=""; + }else + { + $solved=true; + } + $team["problem"][$probCount]=$problems[$probCount]; + $team["problem"][$probCount]["solved"]=$solved; + $team["problem"][$probCount]["time"]=$time; + //I can calculate the effective time and the penalisation time, if needed + $team["problem"][$probCount]["penalty"]=$time; + $team["problem"][$probCount]["count"]=$count; + //look for the time which first problem was solved + if($firstProblem==-1 && $solved) + { + $firstProblem=$time; + }else + { + if($solved && $time<$firstProblem) + { + $firstProblem=$time; + } + } + $probCount++; + }//end switch + + $colCount++; //echo $col->nodeValue."\t"; + }//end col for + + $userCount++; +// echo '<hr />'; + } //end row col +//echo print_r($total); + $total=base64_encode(serialize($total)); + } else + $total=$_POST['data']; + + $fn = tempnam($_SESSION["locr"] . $remotedir,"score_"); + $fout = fopen($fn,"wb"); + fwrite($fout,$total,10000000); + fclose($fout); + + if(@rename($fn, $_SESSION["locr"] . $remotedir . $ds . "score_" . $_SESSION["usertable"]["username"] . "_" . md5(getIP()) . ".dat")) + echo "SCORE UPLOADED OK\n"; + else + echo "FAILED: UPDATE SCORE ERROR\n"; +} else echo "FAILED: PERMISSION DENIED IN THE SERVER\n"; +?> diff --git a/boca-1.5.0/src/staff/header.php b/boca-1.5.0/src/staff/header.php new file mode 100644 index 0000000..27119a6 --- /dev/null +++ b/boca-1.5.0/src/staff/header.php @@ -0,0 +1,74 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +header ("Content-Type: text/html; charset=utf-8"); +session_start(); +ob_end_flush(); +require_once('../version.php'); + +require_once("../globals.php"); +require_once("../db.php"); + +echo "<html><head><title>Staff's Page</title>\n"; +echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"; +echo "<link rel=stylesheet href=\"../Css.php\" type=\"text/css\">\n"; + +//echo "<meta http-equiv=\"refresh\" content=\"60\" />"; + +if(!ValidSession()) { + InvalidSession("staff/index.php"); + ForceLoad("../index.php"); +} +if($_SESSION["usertable"]["usertype"] != "staff" + && $_SESSION["usertable"]["usertype"] != "admin") { + IntrusionNotify("staff/index.php"); + ForceLoad("../index.php"); +} + +echo "<script language=\"javascript\" src=\"../reload.js\"></script>\n"; +echo "</head><body onload=\"Comecar()\" onunload=\"Parar()\"><table border=1 width=\"100%\">\n"; +echo "<tr><td nowrap bgcolor=\"#ffa020\" align=center>"; +echo "<img src=\"../images/smallballoontransp.png\" alt=\"\">"; +echo "<font color=\"#000000\">BOCA</font>"; +echo "</td><td bgcolor=\"#ffa020\" width=\"99%\">\n"; +echo "Username: " . $_SESSION["usertable"]["userfullname"] . " (site=".$_SESSION["usertable"]["usersitenumber"].")<br>\n"; +list($clockstr,$clocktype)=siteclock(); +echo "</td><td bgcolor=\"#ffa020\" align=center nowrap> ".$clockstr." </td></tr>\n"; +echo "</table>\n"; + +if(($s = DBSiteInfo($_SESSION["usertable"]["contestnumber"], $_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +$task = DBOpenTasksInSites($_SESSION["usertable"]["contestnumber"], $s["sitetasking"]); +$nr=count($task); + +echo "<table border=0 width=\"100%\" align=center>\n"; +echo " <tr>\n"; +echo " <td align=center width=\"20%\"><a class=menu style=\"font-weight:bold\" href=task.php>Tasks ($nr)</a></td>\n"; +echo " <td align=center width=\"20%\"><a class=menu style=\"font-weight:bold\" href=score.php>Score</a></td>\n"; +echo " <td align=center width=\"20%\"><a class=menu style=\"font-weight:bold\" href=option.php>Options</a></td>\n"; +echo " <td align=center width=\"20%\"><a class=menu style=\"font-weight:bold\" href=../index.php>Logout</a></td>\n"; +echo " </tr>\n"; +echo "</table>\n"; +?> + diff --git a/boca-1.5.0/src/staff/index.php b/boca-1.5.0/src/staff/index.php new file mode 100644 index 0000000..ec74ce9 --- /dev/null +++ b/boca-1.5.0/src/staff/index.php @@ -0,0 +1,22 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +?> +</body> +</html> diff --git a/boca-1.5.0/src/staff/option.php b/boca-1.5.0/src/staff/option.php new file mode 100644 index 0000000..81e5879 --- /dev/null +++ b/boca-1.5.0/src/staff/option.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +require('../optionlower.php'); +?> diff --git a/boca-1.5.0/src/staff/score.php b/boca-1.5.0/src/staff/score.php new file mode 100644 index 0000000..ef9675d --- /dev/null +++ b/boca-1.5.0/src/staff/score.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +require('../scorelower.php'); +?> diff --git a/boca-1.5.0/src/staff/task.php b/boca-1.5.0/src/staff/task.php new file mode 100644 index 0000000..283b9bb --- /dev/null +++ b/boca-1.5.0/src/staff/task.php @@ -0,0 +1,129 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); + +if (isset($_GET["return"]) && is_numeric($_GET["return"]) && isset($_GET["site"]) && is_numeric($_GET["site"])) { + DBTaskGiveUp ($_GET["return"], $_GET["site"], $_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usernumber"], $_SESSION["usertable"]["usersitenumber"]); + ForceLoad("task.php"); +} + +if (isset($_GET["get"]) && is_numeric($_GET["get"]) && isset($_GET["site"]) && is_numeric($_GET["site"])) { + DBGetTaskToAnswer($_GET["get"], $_GET["site"], $_SESSION["usertable"]["contestnumber"]); + ForceLoad("task.php"); +} + +if (isset($_GET["done"]) && is_numeric($_GET["done"]) && isset($_GET["site"]) && is_numeric($_GET["site"])) { + DBUpdateTask( $_SESSION["usertable"]["contestnumber"], $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], $_GET["site"], $_GET["done"], 'done'); + ForceLoad("task.php"); +} + + + +?> +<br> + <script language="javascript"> + function conf2(url) { +// if (confirm("Confirm?")) { + document.location=url; +// } else { +// document.location='task.php'; +// } + } + </script> +<table width="100%" border=1> + <tr> + <td><b>Task #</b></td> + <td><b>Time</b></td> + <td><b>User / Site</b></td> + <td><b>Description</b></td> + <td><b>File</b></td> + <td><b>Status</b></td> + <td><b>Actions</b></td> + </tr> +<?php +if (($s=DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +$task = DBOpenTasksInSites($_SESSION["usertable"]["contestnumber"], $s["sitetasking"]); + +for ($i=0; $i<count($task); $i++) { + $st = $task[$i]["status"]; + + if($st == "processing" && $task[$i]["staff"]==$_SESSION["usertable"]["usernumber"] && + $task[$i]["staffsite"]==$_SESSION["usertable"]["usersitenumber"]) $mine=1; + else $mine=0; + + echo " <tr>\n"; + echo " <td nowrap>" . $task[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . dateconvminutes($task[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>".$task[$i]["username"]."(" . $task[$i]["user"] . ") / ".$task[$i]["site"]."</td>\n"; + + echo " <td>" . $task[$i]["description"]; + if($task[$i]["color"] != "") { + echo " <img alt=\"".$task[$i]["colorname"]."\" width=\"25\" ". + "src=\"" . balloonurl($task[$i]["color"]) ."\" />"; + } + echo "</td>\n"; + if ($task[$i]["oid"] != null) { + $msg = $task[$i]["username"]." ".$task[$i]["username"]." ".$task[$i]["username"]." ". + $task[$i]["username"]." ".$task[$i]["username"]." ".$task[$i]["username"]; + echo " <td nowrap><a href=\"../filedownload.php?" . filedownload($task[$i]["oid"],$task[$i]["filename"]) . + "\">" . $task[$i]["filename"] . "</a>"; + echo " <a href=\"#\" class=menu style=\"font-weight:bold\" onClick=\"window.open('../filewindow.php?". + filedownload($task[$i]["oid"],$task[$i]["filename"],$msg) . + "', 'Viewx$i','width=680,height=600,scrollbars=yes,toolbar=yes,". + "resizable=yes')\">view</a>"; + echo "</td>\n"; + } + + + else + echo " <td nowrap> </td>\n"; + + if ($mine) $color="ff7777"; + else if ($st == "done") $color="bbbbff"; + else if ($st == "processing") $color="77ff77"; + else if ($st == "opentask") $color="ffff88"; + else $color="ffffff"; + + echo " <td nowrap bgcolor=\"#$color\">$st</td>\n <td nowrap>"; + + if($st == "opentask") + echo " <a href=\"javascript: conf2('task.php?get=" . $task[$i]["number"] . "&site=" . + $task[$i]["site"] . "')\">get</a>\n"; + if($st == "processing" && $mine==1) { + echo " <a href=\"javascript: conf2('task.php?return=" . $task[$i]["number"] . "&site=" . + $task[$i]["site"] . "')\">return</a>\n"; + echo " <a href=\"javascript: conf2('task.php?done=" . $task[$i]["number"] . "&site=" . + $task[$i]["site"] . "')\">done</a>\n"; + } + echo " </td>\n"; +} +echo "</table>"; +if (count($task) == 0) echo "<br><center><b><font color=\"#ff0000\">NO TASKS FOUND</font></b></center>"; + +?> + +</body> +</html> diff --git a/boca-1.5.0/src/system/contest.php b/boca-1.5.0/src/system/contest.php new file mode 100644 index 0000000..2d4d788 --- /dev/null +++ b/boca-1.5.0/src/system/contest.php @@ -0,0 +1,214 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +//Change list: +// 02/jul/2006 by cassio@ime.usp.br +// 25/aug/2007 by cassio@ime.usp.br: php initial tag changed to complete form + +require 'header.php'; + +if (isset($_GET["new"]) && $_GET["new"]=="1") { + $n = DBNewContest(); + ForceLoad("contest.php?contest=$n"); +} + +if (isset($_GET["contest"]) && is_numeric($_GET["contest"])) + $contest=$_GET["contest"]; +else + $contest=$_SESSION["usertable"]["contestnumber"]; + +if(($ct = DBContestInfo($contest)) == null) + ForceLoad("../index.php"); +if ($ct["contestlocalsite"]==$ct["contestmainsite"]) $main=true; else $main=false; + +if (isset($_POST["Submit3"]) && isset($_POST["penalty"]) && is_numeric($_POST["penalty"]) && + isset($_POST["maxfilesize"]) && isset($_POST["mainsite"]) && isset($_POST['localsite']) && + isset($_POST["name"]) && $_POST["name"] != "" && isset($_POST["lastmileanswer"]) && + is_numeric($_POST["lastmileanswer"]) && is_numeric($_POST["mainsite"]) && is_numeric($_POST['localsite']) && + isset($_POST["lastmilescore"]) && is_numeric($_POST["lastmilescore"]) && isset($_POST["duration"]) && + is_numeric($_POST["duration"]) && + isset($_POST["startdateh"]) && $_POST["startdateh"] >= 0 && $_POST["startdateh"] <= 23 && + isset($_POST["contest"]) && is_numeric($_POST["contest"]) && + isset($_POST["startdatemin"]) && $_POST["startdatemin"] >= 0 && $_POST["startdatemin"] <= 59 && + isset($_POST["startdated"]) && isset($_POST["startdatem"]) && isset($_POST["startdatey"]) && + checkdate($_POST["startdatem"], $_POST["startdated"], $_POST["startdatey"])) { + if ($_POST["confirmation"] == "confirm") { + $t = mktime ($_POST["startdateh"], $_POST["startdatemin"], 0, $_POST["startdatem"], + $_POST["startdated"], $_POST["startdatey"]); + if ($_POST["Submit3"] == "Activate") $ac=1; + else $ac=0; + $param['number']=$_POST["contest"]; + $param['name']=$_POST["name"]; + $param['startdate']=$t; + $param['duration']=$_POST["duration"]*60; + $param['lastmileanswer']=$_POST["lastmileanswer"]*60; + $param['lastmilescore']= $_POST["lastmilescore"]*60; + $param['penalty']=$_POST["penalty"]*60; + $param['maxfilesize']=$_POST["maxfilesize"]*1000; + $param['active']=$ac; + $param['mainsite']=$_POST["mainsite"]; + $param['localsite']=$_POST["localsite"]; + $param['mainsiteurl']=$_POST["mainsiteurl"]; + + DBUpdateContest ($param); + if ($ac == 1 && $_POST["contest"] != $_SESSION["usertable"]["contestnumber"]) { + $cf = globalconf(); + if($cf["basepass"] == "") + MSGError("You must log in the new contest. The standard admin password is empty (if not changed yet)."); + else + MSGError("You must log in the new contest. The standard admin password is " . $cf["basepass"] . " (if not changed yet)."); + + ForceLoad("../index.php"); + } + } + ForceLoad("contest.php?contest=".$_POST["contest"]); +} +?> +<br> + +<form name="form1" enctype="multipart/form-data" method="post" action="contest.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + function newcontest() { + document.location='contest.php?new=1'; + } + function contestch(n) { + if(n==null) { + k=document.form1.contest[document.form1.contest.selectedIndex].value; + if(k=='new') newcontest(); + else document.location='contest.php?contest='+k; + } else { + document.location='contest.php?contest='+n; + } + } + </script> + <br><br> + <center> + <table border="0"> + <tr> + <td width="35%" align=right>Contest number:</td> + <td width="65%"> +<select onChange="contestch()" name="contest"> +<?php +$cs = DBAllContestInfo(); +$isfake=false; +for ($i=0; $i<count($cs); $i++) { + echo "<option value=\"" . $cs[$i]["contestnumber"] . "\" "; + if ($contest == $cs[$i]["contestnumber"]) { + echo "selected"; + if($cs[$i]["contestnumber"] == 0) $isfake=true; + } + echo ">" . $cs[$i]["contestnumber"] . ($cs[$i]["contestactive"]=="t"?"*":"") ."</option>\n"; +} +?> +<option value="new">new</option> +</select> + </td> + </tr> + <?php if(!$isfake) { ?> + <tr> + <td width="35%" align=right>Name:</td> + <td width="65%"> + <input type="text" <?php if(!$main) echo "readonly"; ?> name="name" value="<?php echo $ct["contestname"]; ?>" size="50" maxlength="50" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Start date:</td> + <td width="65%"> hh:mm + <input type="text" <?php if(!$main) echo "readonly"; ?> name="startdateh" value="<?php echo date("H", $ct["conteststartdate"]); ?>" size="2" maxlength="2" /> + : + <input type="text" <?php if(!$main) echo "readonly"; ?> name="startdatemin" value="<?php echo date("i", $ct["conteststartdate"]); ?>" size="2" maxlength="2" /> + dd/mm/yyyy + <input type="text" <?php if(!$main) echo "readonly"; ?> name="startdated" value="<?php echo date("d", $ct["conteststartdate"]); ?>" size="2" maxlength="2" /> + / + <input type="text" <?php if(!$main) echo "readonly"; ?> name="startdatem" value="<?php echo date("m", $ct["conteststartdate"]); ?>" size="2" maxlength="2" /> + / + <input type="text" <?php if(!$main) echo "readonly"; ?> name="startdatey" value="<?php echo date("Y", $ct["conteststartdate"]); ?>" size="4" maxlength="4" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Duration (in minutes):</td> + <td width="65%"> + <input type="text" name="duration" <?php if(!$main) echo "readonly"; ?> value="<?php echo $ct["contestduration"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Stop answering (in minutes):</td> + <td width="65%"> + <input type="text" name="lastmileanswer" <?php if(!$main) echo "readonly"; ?> value="<?php echo $ct["contestlastmileanswer"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Stop scoreboard (in minutes):</td> + <td width="65%"> + <input type="text" name="lastmilescore" <?php if(!$main) echo "readonly"; ?> value="<?php echo $ct["contestlastmilescore"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Penalty (in minutes):</td> + <td width="65%"> + <input type="text" name="penalty" <?php if(!$main) echo "readonly"; ?> value="<?php echo $ct["contestpenalty"]/60; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Max file size allowed for teams (in KB):</td> + <td width="65%"> + <input type="text" name="maxfilesize" <?php if(!$main) echo "readonly"; ?> + value="<?php echo $ct["contestmaxfilesize"]/1000; ?>" size="20" maxlength="20" /> + </td> + </tr> + <tr><td width="35%" align=right> + Your PHP config. allows at most:</td> + <td width="65%"> + <?php echo ini_get('post_max_size').'B(max. post) and '.ini_get('upload_max_filesize').'B(max. filesize)'; ?> + </td></tr> + <tr> + <td width="35%" align=right>Contest main site URL (IP/bocafolder):</td> + <td width="65%"> + <input type="text" name="mainsiteurl" value="<?php echo $ct["contestmainsiteurl"]; ?>" size="40" maxlength="200" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Contest main site number:</td> + <td width="65%"> + <input type="text" name="mainsite" value="<?php echo $ct["contestmainsite"]; ?>" size="4" maxlength="4" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Contest local site number:</td> + <td width="65%"> + <input type="text" name="localsite" value="<?php echo $ct["contestlocalsite"]; ?>" size="4" maxlength="4" /> + </td> + </tr> + </table> + </center> + <center> + <input type="submit" name="Submit3" value="Send" onClick="conf()"> + <input type="submit" name="Submit3" value="Activate" onClick="conf()"> + <input type="reset" name="Submit4" value="Clear"> + </center> + <?php } else { echo "<br><br><center>Select a contest or create a new one.</center><br><br>"; } ?> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/system/header.php b/boca-1.5.0/src/system/header.php new file mode 100644 index 0000000..75d0fca --- /dev/null +++ b/boca-1.5.0/src/system/header.php @@ -0,0 +1,63 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +header ("Content-Type: text/html; charset=utf-8"); +session_start(); +ob_end_flush(); +require_once('../version.php'); + +require_once("../globals.php"); +require_once("../db.php"); + +echo "<html><head><title>System's Page</title>\n"; +echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"; +echo "<link rel=stylesheet href=\"../Css.php\" type=\"text/css\">\n"; + +//echo "<meta http-equiv=\"refresh\" content=\"60\" />"; +if(!ValidSession()) { + InvalidSession("system/index.php"); + ForceLoad("../index.php"); +} +if($_SESSION["usertable"]["usertype"] != "system") { + IntrusionNotify("system/index.php"); + ForceLoad("../index.php"); +} + +echo "</head><body><table border=1 width=\"100%\">\n"; +echo "<tr><td nowrap bgcolor=\"eeee00\" align=center>"; +echo "<img src=\"../images/smallballoontransp.png\" alt=\"\">"; +echo "<font color=\"#000000\">BOCA</font>"; +echo "</td><td bgcolor=\"#eeee00\" width=\"99%\">\n"; +echo "Username: " . $_SESSION["usertable"]["userfullname"] ."<br>\n"; +list($clockstr,$clocktype)=siteclock(); +echo "</td><td bgcolor=\"#eeee00\" align=center nowrap> ".$clockstr." </td></tr>\n"; +echo "</table>\n"; +echo "<table border=0 width=\"100%\" align=center>\n"; +echo " <tr>\n"; +echo " <td align=center><a class=menu style=\"font-weight:bold\" href=contest.php>Contest</a></td>\n"; +echo " <td align=center><a class=menu style=\"font-weight:bold\" href=importxml.php>Import</a></td>\n"; +echo " <td align=center><a class=menu style=\"font-weight:bold\" href=option.php>Options</a></td>\n"; +echo " <td align=center><a class=menu style=\"font-weight:bold\" href=../index.php>Logout</a></td>\n"; +echo " </tr>\n"; +echo "</table>\n"; +?> diff --git a/boca-1.5.0/src/system/importxml.php b/boca-1.5.0/src/system/importxml.php new file mode 100644 index 0000000..5fcaef3 --- /dev/null +++ b/boca-1.5.0/src/system/importxml.php @@ -0,0 +1,245 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +//Change list +// 15/June/2011 by cassio@ime.usp.br: created based on import.php + +require('header.php'); +$id = ''; + +if(isset($_POST["Submit"])) { + if(isset($_SESSION["importfile"])) { + $importfile = $_SESSION['importfile']; + } + if (isset($_FILES["importfile"]) && $_FILES["importfile"]["name"]!="") { + $importfile = $_FILES["importfile"]; + } + if(isset($importfile)) { + $_SESSION['importfile'] = $importfile; + + if ($_POST["confirmation"] == "confirm") { + $type=htmlspecialchars($importfile["type"]); + $size=htmlspecialchars($importfile["size"]); + $name=htmlspecialchars($importfile["name"]); + $temp=htmlspecialchars($importfile["tmp_name"]); + if(isset($importfile['filecontent'])) + $ar = $importfile['filecontent']; + else { + if (!is_uploaded_file($temp)) { + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + if (($ar = file($temp)) === false) { + IntrusionNotify("Unable to open the uploaded file."); + ForceLoad("../index.php"); + } + $ar=implode('',$ar); + $_SESSION['importfile']['filecontent']=$ar; + } + $localsite=0; + if(isset($_POST['localsite']) && is_numeric($_POST['localsite'])) $localsite=$_POST['localsite']; + $acr['CONTESTREC']=array('number'=>-1, + 'name'=>-1, + 'startdate'=>-1, + 'duration'=>-1, + 'lastmileanswer'=>-1, + 'lastmilescore'=>-1, + 'localsite'=>-1, + 'penalty'=>-1, + 'maxfilesize'=>-1, + 'updatetime'=>-1); + if($localsite > 0) + $acr['CONTESTREC']['localsite'] = "" . $localsite; + + $acr['ANSWERREC']=array('number'=>-1, + 'name'=>-1, + 'yes'=>-1, + 'updatetime'=>-1); + $acr['LANGUAGEREC']=array('number'=>-1, + 'name'=>-1, + 'filepath'=>-1, + 'filename'=>-1, + 'comppath'=>-1, + 'compname'=>-1, + 'problemnumber'=>-1, + 'updatetime'=>-1); + $acr['PROBLEMREC']=array('number'=>-1, + 'name'=>-1, + 'fullname'=>-1, + 'basename'=>-1, + 'inputfilename'=>-1, + 'inputfilepath'=>-1, + 'solfilename'=>-1, + 'solfilepath'=>-1, + 'descfilename'=>-1, + 'descfilepath'=>-1, + 'tl'=>-1, + 'colorname'=>-1, + 'color'=>-1, + 'fake'=>-1, + 'updatetime'=>-1); + $acr['SITETIME']=array('site'=>-1, + 'start'=>-1, + 'enddate'=>-1, + 'updatetime'=>-1); + $acr['SITEREC']=array('sitenumber'=>-1, + 'site'=>-1, + 'number'=>-1, + 'sitename'=>-1, + 'siteip'=>-1, + 'siteduration'=>-1, + 'sitelastmileanswer'=>-1, + 'sitelastmilescore'=>-1, + 'sitejudging'=>-1, + 'sitetasking'=>-1, + 'siteautoend'=>-1, + 'siteglobalscore'=>-1, + 'siteactive'=>-1, + 'sitescorelevel'=>-1, + 'sitepermitlogins'=>-1, + 'siteautojudge'=>-1, + 'sitenextuser'=>-1, + 'sitenextclar'=>-1, + 'sitenextrun'=>-1, + 'sitenexttask'=>-1, + 'sitemaxtask'=>-1, + 'sitechiefname'=>-1, + 'updatetime'=>-1); + $acr['USERREC']=array('site'=>-1, + 'user'=>-1, + 'number'=>-1, + 'username'=>-1, + 'updatetime'=>-1, + 'usericpcid'=>-1, + 'userfull'=>-1, + 'userdesc'=>-1, + 'type'=>-1, + 'enabled'=>-1, + 'multilogin'=>-1, + 'userip'=>-1, + 'userlastlogin'=>-1, + 'userlastlogout'=>-1, + 'permitip'=>-1); + + if(strtoupper(substr($ar,0,5)) != '<XML>' && isset($_POST['password']) && strlen($_POST['password'])>20) { + echo "<br>Starting to create the contest<br>"; + $str = strtok($ar," \n\t"); + $str = strtok(" \n\t"); + $ar = decryptData($str,$_POST['password'],'importxml'); + if(strtoupper(substr($ar,0,5)) != '<XML>') { + echo "<br>Error decrypting file. Import aborted.<br>"; + echo "</body></html>"; + exit; + } + } + if(strtoupper(substr($ar,0,5)) == '<XML>') { + echo "<br>File has been loaded.<br>"; +// echo "<pre>\n$ar</pre>\n"; + if(!importFromXML($ar,$acr,0,$localsite)) + echo "<br>Error during updating of the local database.<br>"; + echo "</body></html>"; + exit; + } + else + $id = rawurldecode(strtok($ar," \n\t")); + } + } +} else { + unset($_POST['localsite']); + unset($_SESSION['importfile']); +} +?> +<br> +<br> +<center><b> +To import a pre-defined contest, just fill in the import file field.</b></center> +<br> +<body onload="document.form1.name.focus()"> +<script language="JavaScript" src="../sha256.js"></script> +<script language="JavaScript"> +function computeHASH() +{ + var passHASH; + passHASH = ''; + <?php if(strlen($id) > 0) { ?> + passHASH = js_myhash(js_myhash(document.form1.password.value)+'<?php echo $id; ?>'); + <?php } ?> + document.form1.password.value = passHASH; +} +</script> + +<form name="form1" enctype="multipart/form-data" method="post" action="importxml.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="0"> + <tr> + <td width="50%" align=right>Local site number:</td> + <td width="50%"> +<?php + if(isset($_POST["localsite"])) { + echo $_POST['localsite']; + echo "<input type=\"hidden\" name=\"localsite\" size=\"10\" value=\"" .$_POST['localsite']. "\">"; + } else + echo "<input type=\"text\" name=\"localsite\" size=\"10\">"; +?> + </td> + </tr> +<?php + if(isset($_SESSION['importfile'])) { + echo "<tr><td width=\"50%\" align=right>Challenge string:</td><td width=\"50%\">" . $id . "</td></tr>\n"; + } else { +?> + <tr> + <td width="50%" align=right>Import file:</td> + <td width="50%"> + <input type="file" name="importfile" size="40"> + </td> + </tr> +<?php + } + if($id == '') { + echo "<input type=\"hidden\" name=\"password\">"; + } else { +?> + <tr> + <td width="50%" align=right>Encryption key:</td> + <td width="50%"> + <input type="password" name="password"> + </td> + </tr> +<?php + } +?> + </table> + </center> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + computeHASH(); + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Import" onClick="conf()"> + <input type="reset" name="Submit2" value="Clear"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/system/index.php b/boca-1.5.0/src/system/index.php new file mode 100644 index 0000000..ec74ce9 --- /dev/null +++ b/boca-1.5.0/src/system/index.php @@ -0,0 +1,22 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +?> +</body> +</html> diff --git a/boca-1.5.0/src/system/option.php b/boca-1.5.0/src/system/option.php new file mode 100644 index 0000000..81e5879 --- /dev/null +++ b/boca-1.5.0/src/system/option.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +require('../optionlower.php'); +?> diff --git a/boca-1.5.0/src/team/clar.php b/boca-1.5.0/src/team/clar.php new file mode 100644 index 0000000..7b391b9 --- /dev/null +++ b/boca-1.5.0/src/team/clar.php @@ -0,0 +1,117 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +if (isset($_POST["message"]) && isset($_POST["problem"]) && isset($_POST["Submit"]) && is_numeric($_POST["problem"])) { + if ($_POST["confirmation"] == "confirm") { + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + $param['site']=$_SESSION["usertable"]["usersitenumber"]; + $param['user']= $_SESSION["usertable"]["usernumber"]; + $param['problem'] = htmlspecialchars($_POST["problem"]); + $param['question'] = htmlspecialchars($_POST["message"]); + DBNewClar($param); + } + ForceLoad("clar.php"); +} +?> +<br> +<table width="100%" border=1> + <tr> +<!-- <td><b>Clar #</b></td>--> + <td><b>Time</b></td> + <td><b>Problem</b></td> +<!-- <td><b>Status</b></td>--> + <td><b>Question</b></td> + <td><b>Answer</b></td> + </tr> +<?php +if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); +$clar = DBUserClars($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"]); +for ($i=0; $i<count($clar); $i++) { + echo " <tr>\n"; +// echo " <td nowrap>" . $clar[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . dateconvminutes($clar[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $clar[$i]["problem"] . "</td>\n"; +// echo " <td nowrap>" . $clar[$i]["status"] . "</td>\n"; + if ($clar[$i]["question"] == "") $clar[$i]["question"] = " "; + echo " <td>"; +// echo "<pre>" . $clar[$i]["question"] . "</pre>"; + echo " <textarea name=\"m$i\" cols=\"60\" rows=\"8\" readonly>".$clar[$i]["question"]."</textarea>\n"; + echo "</td>\n"; + + if ($clar[$i]["timestamp"]>$_SESSION["usertable"]["userlastlogin"]-$st["sitestartdate"] && $clar[$i]["timestamp"] < $st['siteduration'] && + trim($clar[$i]["answer"])!='' && !isset($_SESSION["popups"]['clar' . $i . '-' . $clar[$i]["timestamp"]])) { + $_SESSION["popups"]['clar' . $i . '-' . $clar[$i]["timestamp"]] = "Clarification for problem ".$clar[$i]["problem"]." answered<br>"; + } + + if (trim($clar[$i]["answer"]) == "") $clar[$i]["answer"] = "Not answered yet"; + echo " <td>"; +// echo " <pre>" . $clar[$i]["answer"] . "</pre>"; + echo " <textarea name=\"a$i\" cols=\"60\" rows=\"8\" readonly>".$clar[$i]["answer"]."</textarea>\n"; + echo "</td>\n"; + echo " </tr>\n"; +} +echo "</table>"; +if (count($clar) == 0) echo "<br><center><b><font color=\"#ff0000\">NO CLARIFICATIONS AVAILABLE</font></b></center>"; + +?> + +<br><br><center><b>To submit a clarification, just fill in the following fields</b></center> +<form name="form1" method="post" action="clar.php"> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="0"> + <tr> + <td width="13%" align=right>Problem:</td> + <td width="87%"> + <select name="problem" onclick="Arquivo()"> +<?php +$prob = DBGetAllProblems($_SESSION["usertable"]["contestnumber"]); +for ($i=0;$i<count($prob);$i++) + echo "<option value=\"" . $prob[$i]["number"] . "\">" . $prob[$i]["problem"] . "</option>\n"; +?> + </select> + </td> + </tr> + <tr> + <td width="13%" align=right>Clarification:</td> + <td width="87%"> + <textarea name="message" cols="60" rows="8" maxlength="2000"></textarea> + </td> + </tr> + </table> + </center> + <script language="javascript"> + function conf() { + if (confirm("Confirm clarification?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Send" onClick="conf()"> + <input type="reset" name="Submit2" value="Clear"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/team/files.php b/boca-1.5.0/src/team/files.php new file mode 100644 index 0000000..42fba28 --- /dev/null +++ b/boca-1.5.0/src/team/files.php @@ -0,0 +1,123 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require 'header.php'; + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); +if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +if (isset($_GET["delete"]) && is_numeric($_GET["delete"])) { + DBBkpDelete($_GET["delete"],$_SESSION["usertable"]["usersitenumber"],$_SESSION["usertable"]["contestnumber"], $_SESSION["usertable"]["usernumber"]); + ForceLoad("files.php"); +} + +if (isset($_FILES["sourcefile"]) && isset($_POST["Submit"]) && $_FILES["sourcefile"]["name"]!="") { + if ($_POST["confirmation"] == "confirm") { + $type=myhtmlspecialchars($_FILES["sourcefile"]["type"]); + $size=myhtmlspecialchars($_FILES["sourcefile"]["size"]); + $name=myhtmlspecialchars($_FILES["sourcefile"]["name"]); + $temp=myhtmlspecialchars($_FILES["sourcefile"]["tmp_name"]); + + if ($size > $ct["contestmaxfilesize"]) { + LOGLevel("User {$_SESSION["usertable"]["username"]} tried to submit file " . + "$name with $size bytes ({$ct["contestmaxfilesize"]} max allowed).", 1); + MSGError("File size exceeds the limit allowed."); + ForceLoad("run.php"); + } + if (!is_uploaded_file($temp) || strlen($name)>100) { + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + + DBNewBkp ($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], + $name, + $temp, $size); + } + ForceLoad("files.php"); +} +?> +<br> +<table width="100%" border=1> + <tr> + <td><b>Bkp #</b></td> + <td><b>Time</b></td> + <td><b>File</b></td> + </tr> +<?php +$run = DBUserBkps($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"]); + +for ($i=0; $i<count($run); $i++) { + echo " <tr>\n"; + echo " <td nowrap><a href=\"javascript:conf2('files.php?delete=" . $run[$i]["number"] . + "')\">" . $run[$i]["number"] . "</a></td>\n"; + + echo " <td nowrap>" . dateconvsimple($run[$i]["timestamp"]) . "</td>\n"; + echo "<td nowrap><a href=\"../filedownload.php?". filedownload($run[$i]["oid"],$run[$i]["filename"]) . "\">"; + echo $run[$i]["filename"] . "</a>"; + + echo "</td>\n"; + echo " </tr>\n"; + +} +echo "</table>"; +if (count($run) == 0) echo "<br><center><b><font color=\"#ff0000\">NO BACKUPS AVAILABLE</font></b></center>"; + +?> + +<br><br><center><b>To erase a file, click on its number. To download a file, click on its name. +To submit a new backup file, just fill in the following fields:</b></center> +<form name="form1" enctype="multipart/form-data" method="post" action="files.php"> +<!--<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $ct["contestmaxfilesize"] ?>">--> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="0"> + <tr> + <td width="35%" align=right>File (size restrictions apply):</td> + <td width="65%"> + <input type="file" name="sourcefile" size="40"> + </td> + </tr> + </table> + </center> + <script language="javascript"> + function conf() { + if (confirm("Confirm submission?")) { + document.form1.confirmation.value='confirm'; + } + } + function conf2(url) { + if (confirm("Confirm?")) { + document.location=url; + } else { + document.location='files.php'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Send" onClick="conf()"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/team/getfile.php b/boca-1.5.0/src/team/getfile.php new file mode 100644 index 0000000..8c594d0 --- /dev/null +++ b/boca-1.5.0/src/team/getfile.php @@ -0,0 +1,47 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require 'header.php'; + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); +if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +$fn = tempnam("/tmp","bkp-"); +$fout = fopen($fn,"wb"); +echo $_POST; +echo $_POST['data']; +fwrite($fout,base64_decode($_POST['data'])); +fclose($fout); +$size=filesize($fn); +$name=$_POST['name']; + if ($size > $ct["contestmaxfilesize"] || strlen($name)>100 || strlen($name)<1) { + LOGLevel("User {$_SESSION["usertable"]["username"]} tried to submit file " . + ":${name}: with $size bytes.", 1); + MSGError("File size exceeds the limit allowed or invalid name."); + } else + + DBNewBkp ($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"], + $name, + $fn, $size); +@unlink($fn); +ForceLoad("../index.php"); +?> diff --git a/boca-1.5.0/src/team/header.php b/boca-1.5.0/src/team/header.php new file mode 100644 index 0000000..862f284 --- /dev/null +++ b/boca-1.5.0/src/team/header.php @@ -0,0 +1,114 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +ob_start(); +header ("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); +header ("Cache-Control: no-cache, must-revalidate"); +header ("Pragma: no-cache"); +header ("Content-Type: text/html; charset=utf-8"); +session_start(); +ob_end_flush(); +require_once('../version.php'); + +require_once("../globals.php"); +require_once("../db.php"); +$runteam='run.php'; + +echo "<html><head><title>Team's Page</title>\n"; +echo "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\">\n"; +echo "<link rel=stylesheet href=\"../Css.php\" type=\"text/css\">\n"; + +//echo "<meta http-equiv=\"refresh\" content=\"60\" />"; + +if(!ValidSession()) { + InvalidSession("team/index.php"); + ForceLoad("../index.php"); +} +if($_SESSION["usertable"]["usertype"] != "team") { + IntrusionNotify("team/index.php"); + ForceLoad("../index.php"); +} + +echo "<script language=\"javascript\" src=\"../reload.js\"></script>\n"; +echo "</head><body onload=\"Comecar()\" onunload=\"Parar()\"><table border=1 width=\"100%\">\n"; +echo "<tr><td nowrap bgcolor=\"#aaaaee\" align=center>"; +echo "<img src=\"../images/smallballoontransp.png\" alt=\"\">"; +echo "<font color=\"#000000\">BOCA</font>"; +echo "</td><td bgcolor=\"#aaaaee\" width=\"99%\">\n"; +echo "Username: " . $_SESSION["usertable"]["userfullname"] . " (site=".$_SESSION["usertable"]["usersitenumber"].")\n"; + +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +$runtmp = $_SESSION["locr"] . $ds . "private" . $ds . "runtmp" . $ds . "run-contest" . $_SESSION["usertable"]["contestnumber"] . + "-site". $_SESSION["usertable"]["usersitenumber"] . "-user" . $_SESSION["usertable"]["usernumber"] . ".php"; +$doslow=true; +if(file_exists($runtmp)) { + if(($strtmp = file_get_contents($runtmp,FALSE,NULL,-1,1000000)) !== FALSE) { + $postab=strpos($strtmp,"\t"); + $conf=globalconf(); + $strcolors = decryptData(substr($strtmp,$postab+1,strpos($strtmp,"\n")-$postab-1),$conf['key'],''); + $doslow=false; + $rn=explode("\t",$strcolors); + $n=count($rn); + for($i=1; $i<$n-1;$i++) { + echo "<img alt=\"".$rn[$i]."\" width=\"10\" ". + "src=\"" . balloonurl($rn[$i+1]) . "\" />\n"; + $i++; + } + } else unset($strtmp); +} +if($doslow) { + $run = DBUserRunsYES($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"]); + $n=count($run); + for($i=0; $i<$n;$i++) { + echo "<img alt=\"".$run[$i]["colorname"]."\" width=\"10\" ". + "src=\"" . balloonurl($run[$i]["color"]) . "\" />\n"; + } +} + +$str = ''; +foreach($_SESSION["popups"] as $key => $value) { + if($value != null) { + $str .= $value; + $_SESSION["popups"][$key] = null; + } +} +if($str != '') { + MSGError('YOU GOT NEWS:<br>' . $str); +} + +list($clockstr,$clocktype)=siteclock(); +echo "</td><td bgcolor=\"#aaaaee\" align=center nowrap> ".$clockstr." </td></tr>\n"; +echo "</table>\n"; +echo "<table border=0 width=\"100%\" align=center>\n"; +echo " <tr>\n"; +echo " <td align=center width=\"12%\"><a class=menu style=\"font-weight:bold\" href=problem.php>Problems</a></td>\n"; +echo " <td align=center width=\"12%\"><a class=menu style=\"font-weight:bold\" href=run.php>Runs</a></td>\n"; +echo " <td align=center width=\"12%\"><a class=menu style=\"font-weight:bold\" href=score.php>Score</a></td>\n"; +echo " <td align=center width=\"12%\"><a class=menu style=\"font-weight:bold\" href=clar.php>Clarifications</a></td>\n"; +echo " <td align=center width=\"12%\"><a class=menu style=\"font-weight:bold\" href=task.php>Tasks</a></td>\n"; +echo " <td align=center width=\"12%\"><a class=menu style=\"font-weight:bold\" href=files.php>Backups</a></td>\n"; +echo " <td align=center width=\"12%\"><a class=menu style=\"font-weight:bold\" href=option.php>Options</a></td>\n"; +echo " <td align=center width=\"12%\"><a class=menu style=\"font-weight:bold\" href=../index.php>Logout</a></td>\n"; +echo " </tr>\n"; +echo "</table>\n"; +?> diff --git a/boca-1.5.0/src/team/index.php b/boca-1.5.0/src/team/index.php new file mode 100644 index 0000000..ec74ce9 --- /dev/null +++ b/boca-1.5.0/src/team/index.php @@ -0,0 +1,22 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +?> +</body> +</html> diff --git a/boca-1.5.0/src/team/option.php b/boca-1.5.0/src/team/option.php new file mode 100644 index 0000000..81e5879 --- /dev/null +++ b/boca-1.5.0/src/team/option.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +require('../optionlower.php'); +?> diff --git a/boca-1.5.0/src/team/problem.php b/boca-1.5.0/src/team/problem.php new file mode 100644 index 0000000..c5bc8cb --- /dev/null +++ b/boca-1.5.0/src/team/problem.php @@ -0,0 +1,58 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); + +?> +<br> +<table width="100%" border=1> + <tr> + <td><b>Name</b></td> + <td><b>Basename</b></td> + <td><b>Fullname</b></td> + <td><b>Descfile</b></td> + </tr> +<?php +$prob = DBGetProblems($_SESSION["usertable"]["contestnumber"]); +for ($i=0; $i<count($prob); $i++) { + echo " <tr>\n"; +// echo " <td nowrap>" . $prob[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . $prob[$i]["problem"]; + if($prob[$i]["color"] != "") + echo " <img alt=\"".$prob[$i]["colorname"]."\" width=\"20\" ". + "src=\"" . balloonurl($prob[$i]["color"]) ."\" />\n"; + echo "</td>\n"; + echo " <td nowrap>" . $prob[$i]["basefilename"] . " </td>\n"; + echo " <td nowrap>" . $prob[$i]["fullname"] . " </td>\n"; + if (isset($prob[$i]["descoid"]) && $prob[$i]["descoid"] != null) { + echo " <td nowrap><a href=\"../filedownload.php?" . filedownload($prob[$i]["descoid"], $prob[$i]["descfilename"]) . + "\">" . basename($prob[$i]["descfilename"]) . "</td>\n"; + } + else + echo " <td nowrap>no description file available</td>\n"; + echo " </tr>\n"; +} +echo "</table>"; +if (count($prob) == 0) echo "<br><center><b><font color=\"#ff0000\">NO PROBLEMS AVAILABLE YET</font></b></center>"; + +?> +</body> +</html> diff --git a/boca-1.5.0/src/team/run.php b/boca-1.5.0/src/team/run.php new file mode 100644 index 0000000..f00adac --- /dev/null +++ b/boca-1.5.0/src/team/run.php @@ -0,0 +1,190 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 21/jul/2012 by cassio@ime.usp.br +require('header.php'); + +if (isset($_FILES["sourcefile"]) && isset($_POST["problem"]) && isset($_POST["Submit"]) && isset($_POST["language"]) && + is_numeric($_POST["problem"]) && is_numeric($_POST["language"]) && $_FILES["sourcefile"]["name"]!="") { + if ($_POST["confirmation"] == "confirm") { + if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); + + $prob = myhtmlspecialchars($_POST["problem"]); + $lang = myhtmlspecialchars($_POST["language"]); + + $type=myhtmlspecialchars($_FILES["sourcefile"]["type"]); + $size=myhtmlspecialchars($_FILES["sourcefile"]["size"]); + $name=myhtmlspecialchars($_FILES["sourcefile"]["name"]); + $temp=myhtmlspecialchars($_FILES["sourcefile"]["tmp_name"]); + + if ($size > $ct["contestmaxfilesize"]) { + LOGLevel("User {$_SESSION["usertable"]["username"]} tried to submit file " . + "$name with $size bytes ({$ct["contestmaxfilesize"]} max allowed).", 1); + MSGError("File size exceeds the limit allowed."); + ForceLoad($runteam); + } + if (!is_uploaded_file($temp) || strlen($name)>100) { + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + + + $ac=array('contest','site','user','problem','lang','filename','filepath'); + $ac1=array('runnumber','rundate','rundatediff','rundatediffans','runanswer','runstatus','runjudge','runjudgesite', + 'runjudge1','runjudgesite1','runanswer1','runjudge2','runjudgesite2','runanswer2', + 'autoip','autobegindate','autoenddate','autoanswer','autostdout','autostderr','updatetime'); + $param = array('contest'=>$_SESSION["usertable"]["contestnumber"], + 'site'=>$_SESSION["usertable"]["usersitenumber"], + 'user'=> $_SESSION["usertable"]["usernumber"], + 'problem'=>$prob, + 'lang'=>$lang, + 'filename'=>$name, + 'filepath'=>$temp); + DBNewRun ($param); + $_SESSION['forceredo']=true; + } + ForceLoad($runteam); +} + +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +$runtmp = $_SESSION["locr"] . $ds . "private" . $ds . "runtmp" . $ds . "run-contest" . $_SESSION["usertable"]["contestnumber"] . + "-site". $_SESSION["usertable"]["usersitenumber"] . "-user" . $_SESSION["usertable"]["usernumber"] . ".php"; +$redo = TRUE; +if(!isset($_SESSION['forceredo']) || $_SESSION['forceredo']==false) { + $actualdelay = 30; + if(file_exists($runtmp)) { + if(isset($strtmp) || (($strtmp = file_get_contents($runtmp,FALSE,NULL,-1,1000000)) !== FALSE)) { + list($d) = sscanf($strtmp,"%*s %d"); + if($d > time() - $actualdelay) { + $conf=globalconf(); + $strtmp = decryptData(substr($strtmp,strpos($strtmp,"\n")+1),$conf["key"],'runtmp'); + if($strtmp !== false) + $redo = FALSE; + } + } + } +} +if($redo) { + $_SESSION['forceredo']=false; + if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + $strtmp="<br>\n<table width=\"100%\" border=1>\n <tr>\n <td><b>Run #</b></td>\n<td><b>Time</b></td>\n". + " <td><b>Problem</b></td>\n <td><b>Language</b></td>\n <td><b>Answer</b></td>\n <td><b>File</b></td>\n </tr>\n"; + $strcolors = "0"; + $run = DBUserRuns($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"]); + for ($i=0; $i<count($run); $i++) { + $strtmp .= " <tr>\n"; + $strtmp .= " <td nowrap>" . $run[$i]["number"] . "</td>\n"; + $strtmp .= " <td nowrap>" . dateconvminutes($run[$i]["timestamp"]) . "</td>\n"; + $strtmp .= " <td nowrap>" . $run[$i]["problem"] . "</td>\n"; + $strtmp .= " <td nowrap>" . $run[$i]["language"] . "</td>\n"; +// $strtmp .= " <td nowrap>" . $run[$i]["status"] . "</td>\n"; + if (trim($run[$i]["answer"]) == "") { + $run[$i]["answer"] = "Not answered yet"; + $strtmp .= " <td>Not answered yet"; + } + else { + $strtmp .= " <td>" . $run[$i]["answer"]; + if($run[$i]['yes']=='t') { + $strtmp .= " <img alt=\"".$run[$i]["colorname"]."\" width=\"15\" ". + "src=\"" . balloonurl($run[$i]["color"]) ."\" />"; + $strcolors .= "\t" . $run[$i]["colorname"] . "\t" . $run[$i]["color"]; + } + } + $strtmp .= "</td>\n"; + $strtmp .= "<td nowrap><a href=\"../filedownload.php?" . filedownload($run[$i]["oid"],$run[$i]["filename"]) . "\">"; + $strtmp .= $run[$i]["filename"] . "</a>"; + + $strtmp .= "</td>\n"; + + $strtmp .= " </tr>\n"; + + if ($run[$i]["anstime"]>$_SESSION["usertable"]["userlastlogin"]-$st["sitestartdate"] && $run[$i]["anstime"] < $st['sitelastmileanswer'] && + $run[$i]["ansfake"]!="t" && !isset($_SESSION["popups"]['run' . $i . '-' . $run[$i]["anstime"]])) { + $_SESSION["popups"]['run' . $i . '-' . $run[$i]["anstime"]] = "Run ".$run[$i]["number"]." result: ".$run[$i]["answer"]. "<br>"; + } + } +$strtmp .= "</table>"; +if (count($run) == 0) $strtmp .= "<br><center><b><font color=\"#ff0000\">NO RUNS AVAILABLE</font></b></center>"; + +$strtmp .= "<br><br><center><b>To submit a program, just fill in the following fields:</b></center>\n". +"<form name=\"form1\" enctype=\"multipart/form-data\" method=\"post\" action=\"". $runteam ."\">\n". +" <input type=hidden name=\"confirmation\" value=\"noconfirm\" />\n". +" <center>\n". +" <table border=\"0\">\n". +" <tr> \n". +" <td width=\"25%\" align=right>Problem:</td>\n". +" <td width=\"75%\">\n". +" <select name=\"problem\" onclick=\"Arquivo()\">\n"; +$prob = DBGetProblems($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usertype"]=='judge'); +for ($i=0;$i<count($prob);$i++) + $strtmp .= "<option value=\"" . $prob[$i]["number"] . "\">" . $prob[$i]["problem"] . "</option>\n"; +$strtmp .= " </select>\n". +" </td>\n". +" </tr>\n". +" <tr> \n". +" <td width=\"25%\" align=right>Language:</td>\n". +" <td width=\"75%\"> \n". +" <select name=\"language\" onclick=\"Arquivo()\">\n"; +$lang = DBGetLanguages($_SESSION["usertable"]["contestnumber"]); +for ($i=0;$i<count($lang);$i++) + $strtmp .= "<option value=\"" . $lang[$i]["number"] . "\">" . $lang[$i]["name"] . "</option>\n"; +$strtmp .= " </select>\n". +" </td>\n". +" </tr>\n". +" <tr> \n". +" <td width=\"25%\" align=right>Source code:</td>\n". +" <td width=\"75%\">\n". +" <input type=\"file\" name=\"sourcefile\" size=\"40\" onclick=\"Arquivo()\">\n". +" </td>\n". +" </tr>\n". +" </table>\n". +" </center>\n". +" <script language=\"javascript\">\n". +" function conf() {\n". +" if (confirm(\"Confirm submission?\")) {\n". +" document.form1.confirmation.value='confirm';\n". +" }\n". +" }\n". +" </script>\n". +" <center>\n". +" <input type=\"submit\" name=\"Submit\" value=\"Send\" onClick=\"conf()\">\n". +" <input type=\"reset\" name=\"Submit2\" value=\"Clear\">\n". +" </center>\n". +"</form>\n"; + $conf=globalconf(); + $strtmp1 = "<!-- " . time() . " --> <?php exit; ?>\t" . encryptData($strcolors,$conf["key"],false) . "\n" . encryptData($strtmp,$conf["key"],false); + $randnum = session_id() . "_" . rand(); + if(file_put_contents($runtmp . "_" . $randnum, $strtmp1,LOCK_EX)===FALSE) { + if(!isset($_SESSION['writewarn'])) { + LOGError("Cannot write to the user-run cache file $runtmp -- performance might be compromised"); + $_SESSION['writewarn']=true; + } + } + @rename($runtmp . "_" . $randnum, $runtmp); +} +echo $strtmp; +?> + + +</body> +</html> diff --git a/boca-1.5.0/src/team/score.php b/boca-1.5.0/src/team/score.php new file mode 100644 index 0000000..ef9675d --- /dev/null +++ b/boca-1.5.0/src/team/score.php @@ -0,0 +1,21 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); +require('../scorelower.php'); +?> diff --git a/boca-1.5.0/src/team/task.php b/boca-1.5.0/src/team/task.php new file mode 100644 index 0000000..b23605c --- /dev/null +++ b/boca-1.5.0/src/team/task.php @@ -0,0 +1,121 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br +require('header.php'); + +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); +if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) == null) + ForceLoad("../index.php"); + +if (isset($_POST["Submit"]) && $_POST["Submit"]=="S.O.S.") { + if ($_POST["confirmation"] == "confirm") { + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + $param['site']=$_SESSION["usertable"]["usersitenumber"]; + $param['user']=$_SESSION["usertable"]["usernumber"]; + $param['desc']= "Staff assistance"; + DBNewTask ($param); + } + ForceLoad("task.php"); +} +if (isset($_FILES["filename"]) && isset($_POST["Submit"]) && $_FILES["filename"]["name"]!="") { + if ($_POST["confirmation"] == "confirm") { + $type=myhtmlspecialchars($_FILES["filename"]["type"]); + $size=myhtmlspecialchars($_FILES["filename"]["size"]); + $name=myhtmlspecialchars($_FILES["filename"]["name"]); + $temp=myhtmlspecialchars($_FILES["filename"]["tmp_name"]); + + if ($size > $ct["contestmaxfilesize"]) { + LOGLevel("User {$_SESSION["usertable"]["username"]} tried to print file " . + "$name with $size bytes ({$ct["contestmaxfilesize"]} max allowed).", 1); + MSGError("File size exceeds the limit allowed."); + ForceLoad("task.php"); + } + if (!is_uploaded_file($temp)) { + IntrusionNotify("Printing file upload problem"); + ForceLoad("../index.php"); + } + $param['contest']=$_SESSION["usertable"]["contestnumber"]; + $param['site']=$_SESSION["usertable"]["usersitenumber"]; + $param['user']=$_SESSION["usertable"]["usernumber"]; + $param['desc']= "File to print"; + $param['filename']=$name; + $param['filepath']=$temp; + DBNewTask ($param); + } + ForceLoad("task.php"); +} +?> +<br> +<table width="100%" border=1> + <tr> + <td><b>Task #</b></td> + <td><b>Time</b></td> + <td><b>Description</b></td> + <td><b>File</b></td> + <td><b>Status</b></td> + </tr> +<?php +$task = DBUserTasks($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"]); +for ($i=0; $i<count($task); $i++) { + echo " <tr>\n"; + echo " <td nowrap>" . $task[$i]["number"] . "</td>\n"; + echo " <td nowrap>" . dateconvminutes($task[$i]["timestamp"]) . "</td>\n"; + echo " <td nowrap>" . $task[$i]["description"] . "</td>\n"; + echo " <td nowrap>" . $task[$i]["filename"] . " </td>\n"; + echo " <td nowrap>" . $task[$i]["status"] . "</td>\n"; +} +echo "</table>"; +if (count($task) == 0) echo "<br><center><b><font color=\"#ff0000\">NO TASKS FOUND</font></b></center>"; +?> + +<br><br><center><b>To submit a file for printing, just fill in the following field:</b></center> +<form name="form1" enctype="multipart/form-data" method="post" action="task.php"> +<!--<input type="hidden" name="MAX_FILE_SIZE" value="<?php echo $ct["contestmaxfilesize"] ?>">--> + <input type=hidden name="confirmation" value="noconfirm" /> + <center> + <table border="0"> + <tr> + <td width="25%" align=right>File name:</td> + <td width="75%"> + <input type="file" name="filename" size="40" onclick="Arquivo()"> + </td> + </tr> + </table> + </center> + <script language="javascript"> + function conf() { + if (confirm("Confirm?")) { + document.form1.confirmation.value='confirm'; + } + } + </script> + <center> + <input type="submit" name="Submit" value="Send" onClick="conf()"> + <input type="reset" name="Submit2" value="Clear"> + </center> +<br><br><center><b>If you needed staff assistance, please click +on the button above and wait.</b><br> + <input type="submit" name="Submit" value="S.O.S." onClick="conf()"> + </center> +</form> + +</body> +</html> diff --git a/boca-1.5.0/src/test.php b/boca-1.5.0/src/test.php new file mode 100644 index 0000000..694120a --- /dev/null +++ b/boca-1.5.0/src/test.php @@ -0,0 +1,16 @@ +<?php +$simple = file_get_contents('../doc/test.dat'); +$p = xml_parser_create(); +xml_parser_set_option($p, XML_OPTION_CASE_FOLDING, 1); +xml_parser_set_option($p, XML_OPTION_SKIP_WHITE, 1); +xml_parse_into_struct($p, $simple, $vals, $index); +xml_parser_free($p); +echo "Index array\n"; +print_r($index); +echo "\nVals array\n"; +print_r($vals); + +$aa = "aaa"; +$$aa = "a"; +echo "==>" . $aa . " " . $aaa . "\n"; +?> diff --git a/boca-1.5.0/src/version b/boca-1.5.0/src/version new file mode 100644 index 0000000..ee61382 --- /dev/null +++ b/boca-1.5.0/src/version @@ -0,0 +1 @@ +boca-1.5.0 diff --git a/boca-1.5.0/src/version.php b/boca-1.5.0/src/version.php new file mode 100644 index 0000000..8a8cfef --- /dev/null +++ b/boca-1.5.0/src/version.php @@ -0,0 +1,30 @@ +<?php +//////////////////////////////////////////////////////////////////////////////// +//BOCA Online Contest Administrator +// Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// 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 the +// GNU General Public License for more details. +// You should have received a copy of the GNU General Public License +// along with this program. If not, see <http://www.gnu.org/licenses/>. +//////////////////////////////////////////////////////////////////////////////// +// Last modified 05/aug/2012 by cassio@ime.usp.br + +require 'versionnum.php'; + +echo "<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\">\n"; +echo "<!-- BOCA $BOCAVERSION. Copyright (c) 2003-$YEAR Cassio Polpo de Campos -->\n"; +echo "<!-- http://www.ime.usp.br/~cassio/boca -->\n"; +echo "<!-- This program is free software: you can redistribute it and/or modify -->\n"; +echo "<!-- it under the terms of the GNU General Public License as published by -->\n"; +echo "<!-- the Free Software Foundation, either version 3 of the License, or -->\n"; +echo "<!-- (at your option) any later version. A copy of the -->\n"; +echo "<!-- license can be found with this software or at http://www.gnu.org/licenses/ -->\n"; +?> diff --git a/boca-1.5.0/src/versionnum.php b/boca-1.5.0/src/versionnum.php new file mode 100644 index 0000000..8455227 --- /dev/null +++ b/boca-1.5.0/src/versionnum.php @@ -0,0 +1,5 @@ +<?php +$BOCAVERSION='boca-1.5.0'; +$YEAR='2012'; +?> + diff --git a/boca-1.5.0/src/webcast.zip b/boca-1.5.0/src/webcast.zip Binary files differnew file mode 100644 index 0000000..577ba23 --- /dev/null +++ b/boca-1.5.0/src/webcast.zip diff --git a/boca-1.5.0/src/webcast/config.php b/boca-1.5.0/src/webcast/config.php new file mode 100644 index 0000000..843842b --- /dev/null +++ b/boca-1.5.0/src/webcast/config.php @@ -0,0 +1,8 @@ +<?php + +$contest = 1; +$site = 1; + +$freezeTime = 240; + +?> diff --git a/boca-1.5.0/src/webcast/contest/index.php b/boca-1.5.0/src/webcast/contest/index.php new file mode 100644 index 0000000..8d68f34 --- /dev/null +++ b/boca-1.5.0/src/webcast/contest/index.php @@ -0,0 +1,54 @@ +<?php + +require '../../db.php'; +require '../config.php'; + +header('Content-type: text/plain; encoding=utf-8'); + +$ct = DBContestInfo($contest); + +echo + $ct['contestname'] . "\n"; + +echo + $ct['contestduration']/60 . '' . + $ct['contestlastmileanswer']/60 . '' . + $ct['contestlastmilescore']/60 . '' . + $ct['contestpenalty']/60 . "\n"; + +$c = DBConnect(); + +$r = DBExec($c, + 'SELECT problemnumber FROM problemtable' . + ' WHERE contestnumber = ' . $contest . + ' AND problemnumber > 0'); + +$numProblems = DBnlines($r); + +$r = DBExec($c, + 'SELECT username, userfullname FROM usertable' . + ' WHERE contestnumber = ' . $contest . + ' AND userenabled = \'t\' AND usersitenumber = ' . $site . + ' AND usertype = \'team\''); + +$numTeams = DBnlines($r); + +echo + $numTeams . '' . + $numProblems . "\n"; + +for ($i = 0; $i < $numTeams; $i++) { + $a = DBRow($r, $i); + $teamID = $a['username']; + $pieces = explode('</b>', $a['userfullname']); + $teamName = trim($pieces[1]); + $pieces = explode('<b>', $pieces[0]); + $teamUni = trim($pieces[1]); + + echo + $teamID . '' . + $teamUni . '' . + $teamName . "\n"; +} + +?> diff --git a/boca-1.5.0/src/webcast/runs/index.php b/boca-1.5.0/src/webcast/runs/index.php new file mode 100644 index 0000000..e28567e --- /dev/null +++ b/boca-1.5.0/src/webcast/runs/index.php @@ -0,0 +1,41 @@ +<?php + +require '../../db.php'; +require '../config.php'; + +header('Content-type: text/plain; encoding=utf-8'); + +$s = DBSiteInfo($contest, $site); + +$run = DBAllRunsInSites($contest, $site, 'run'); + +$numRuns = count($run); + +for ($i = 0; $i < $numRuns; $i++) { + $u = DBUserInfo($contest, $site, $run[$i]['user']); + + $runID = $run[$i]['number']; + $runTime = dateconvminutes($run[$i]['timestamp']); + $runTeam = $u['username']; + $runProblem = $run[$i]['problem']; + + if ($runTime > $freezeTime) { + continue; + } + + echo + $runID . '' . + $runTime . '' . + $runTeam . '' . + $runProblem . ''; + + if ($run[$i]['yes']=='t') { + echo 'Y' . "\n"; + } else if ($run[$i]['answer'] == 'Not answered yet') { + echo '?' . "\n"; + } else { + echo 'N' . "\n"; + }; +} + +?> diff --git a/boca-1.5.0/src/webcast/time/index.php b/boca-1.5.0/src/webcast/time/index.php new file mode 100644 index 0000000..061c81f --- /dev/null +++ b/boca-1.5.0/src/webcast/time/index.php @@ -0,0 +1,12 @@ +<?php + +require '../../db.php'; +require '../config.php'; + +header('Content-type: text/plain; encoding=utf-8'); + +$s = DBSiteInfo($contest, $site); + +echo $s['currenttime']; + +?> diff --git a/boca-1.5.0/src/webcast/version/index.php b/boca-1.5.0/src/webcast/version/index.php new file mode 100644 index 0000000..4d474a2 --- /dev/null +++ b/boca-1.5.0/src/webcast/version/index.php @@ -0,0 +1,10 @@ +<?php + +require '../../db.php'; +require '../config.php'; + +header('Content-type: text/plain; encoding=utf-8'); + +echo '1.0' . "\n"; + +?> diff --git a/boca-1.5.0/tools/.htaccess b/boca-1.5.0/tools/.htaccess new file mode 100644 index 0000000..3a42882 --- /dev/null +++ b/boca-1.5.0/tools/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/boca-1.5.0/tools/READMEubuntu.txt b/boca-1.5.0/tools/READMEubuntu.txt new file mode 100644 index 0000000..09994a8 --- /dev/null +++ b/boca-1.5.0/tools/READMEubuntu.txt @@ -0,0 +1,33 @@ +ICPC Linux installation script +---------------------------------- +Copyright (c) 2009 C. P. de Campos. +Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". +--------------------------------- +File last modified: 11/oct/2011 + +==> The installv2.sh script is not necessary if you are using the virtual machine version. This is intended to those that +want to install the system as the host of a computer, or desire to create again the virtual machine version from the beginning. + +The script installv2.sh available here was used to create the "ICPC Linux" image after a standard installation +of the ubuntu (or xubuntu) distribution. This is well-suitable in case you do not want to +use the virtualized version, for example, in the server of the contest. After using the installv2.sh script over a fresh +install of the ubuntu, you reach the exactly same content of the virtual machine version that is available. +Take care with the following points during the installation of the ubuntu: +1) Use the name "icpcadmin" and password "icpcadmin" (no quotes obviously) as the standard user during the installation. +2) Call the machine "icpc" (in the same screen where you set up the username above). +3) Use the simplest partitioning option (that is, everything in a single partition) and choose at least 10GB for it. + +After installing ubuntu, the system reboots. Download the script installv2.sh to the home directory of icpcadmin, +make it executable by chmod 755 installv2.sh, and run it as root: sudo ./installv2.sh +and reboot the system to finish the configuration (such as setting passwords, IPs, etc). +Note this is going to give you a system just like you would get from the box (the virtual machine version). If you +want it to become a server, you must follow the same procedure that is indicated in the READMEvm.txt. This +mainly means that you need to run the script /etc/icpc/becomeserver.sh + +The most recent installv2.sh script is available at http://www.ime.usp.br/~cassio/boca/ link named installv2.sh +In case of any questions, do not hesitate to contact me: bocasystem@gmail.com. Have fun! diff --git a/boca-1.5.0/tools/READMEvm.txt b/boca-1.5.0/tools/READMEvm.txt new file mode 100644 index 0000000..e78fca8 --- /dev/null +++ b/boca-1.5.0/tools/READMEvm.txt @@ -0,0 +1,163 @@ +READMEvm.txt file of the ICPC Linux VM (release 2011) +================================= +Copyright (c) 2009-2011 C. P. de Campos. +Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.3 + or any later version published by the Free Software Foundation; + with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. + A copy of the license is included in the section entitled "GNU + Free Documentation License". +================================= +Last modified: 10/Oct/2011 + +This file concerns the ICPC Linux image available in this directory. It is a vmware-type +hard-disk image with a system built up over a ubuntu (or xubuntu) distribution. This is +also relevant if you have used the installv2.sh script to build the server natively, as the +system will have the exactly same characteristics of the VM version mentioned here. + +- You need the vmplayer from www.vmware.com to use this image. As far as I know, vmplayer is +free-of-charge for linux and windows hosts. Check it. There is another version based on virtualbox, +which is just a translation from the image here. virtualbox is free and works pretty well too. + +- Internet access is restricted inside the box. By default, users can only access +bombonera.ime.usp.br, the home of BOCA. During the first boot time, you are able to choose a +different IP address of your server instead of bombonera. If you are going to run a contest, +you must do that! The system inside the virtual machine (or just VM) will +only be able to access such server and nothing else. An alias with the name boca is created +for such IP, so it is possible to connect to it using the name boca instead of typing the +IP address. So, during the first initialization of each VM you should configure the IP address +of your BOCA server. The image provided here can be used as a BOCA server too. See next bullets +on how to do that. In the team machines, check if the internet is really blocked. If not, the +initialization scripts might be malfunctioning, or the computer might be mistakenly set to be +a server (this can be easily checked by verifying whether the file /etc/icpc/.isserver exists or not). + +- There are two linux users in the box: icpcadmin, which has right to become root using +sudo, and the user icpc. The latter has password icpc, and more restricted access. The user +icpc is intended to be used by the teams, judges, staff, or anyone else. The icpcadmin is +an administrative account and the password must be known only by the sysadmin, director of the +contest, and so on. During the first boot time, you are able to change the password of the icpcadmin +account. DO IT and keep it safe! The default password is icpcadmin. Note that such +users (icpcadmin and icpc) have nothing to do with users of the BOCA web system. Each +team must have a distinct user to login on BOCA, which are configured through the BOCA web interface. +Still, each team will logon into the linux box using the same user: icpc. As mentioned, this is +not a security problem because the user icpc is just a local account in the linux system without +any privileges. + +- To run a contest using a virtual machine, you probably need at least 384MB of RAM inside a +"good" computer (then you can configure the VM to run with 256MB). I have tested the vm image +configured to use 512MB. If your host has for example 1GB, you may change the vmplayer +to use 768MB, although 512 should be fine too. Just keep some room for the underlying operating +system. Using more memory inside the vm is better for the teams, so they can run heavier tools. + +- Unzipped, the image takes around 12 GB of your hard disk. You need this space in the hard +disk of each computer. If this is a problem for you, it is possible to rebuild the vm system +with less space (8GB for clients is enough, the server has to have more). + +- It is possible to maximize the VM window so as it uses the whole screen area. The current +image is set to 800x600 or 1024x768 pixels, but that can probably be increased depending on your +video card and monitor settings. The keyboard config can also be changed +inside the x-window system configurations. + +- During the first startup, an script will ask you for the BOCA database password (after +asking the BOCA server IP address and password of the icpcadmin). YOU MUST ONLY FILL +SUCH PASSWORD IN THERE IF the machine being configured is NOT going to be used by a team. With +this password, it will be possible to access the database directly (instead of by web). Teams +shall access the system only by using the web interface. This password is intended to be used +in the machine that will have the autojudging system, as the autojudging script needs to +connect to the database directly (see next item about the autojudge). In fact only the +autojudging machine (or machines, if you have more than one) need this password to be set. + +- An autojugding machine is used to automatically compile and execute the codes submitted +by the teams. DO NOT run it on the same computer as the BOCA server (the web server and the database +server). Because teams may submit malicious code, it is safe to run it on a separate computer. +The worst scenario (in case a team's code hangs the computer) will require to reboot such +computer. About the configuration, the only difference between the autojudge computer and +team's computers is the setup of the database password, as mentioned before. You must set up +the database password during the initialization of the autojudging computer. Then, to run the +autojudging system, you need to login as icpcadmin (privileged user), open a command-line +terminal (it is inside accessories), and run "sudo /var/www/boca/tools/autojudge.sh" (without quotes). +If everything is fine, some dots will appear on the screen while the script runs an infinite +loop waiting for submissions. Ctrl-C stops the autojudge. The autojudging shall be started +after configuring the server to run the contest, otherwise it will eventually output an error or +freeze. If you see the dots happening every few seconds, you are in the correct track. + +- With old versions of ICPC Linux, all the team files were kept in the server. Now this is +NOT true anymore. Everything is stored locally. So, after a warmup and before the real +contest, it is necessary to go to each team computer, open a command-line shell (you do not +need to change to the privileged user, the unprivilegied icpc user is enough) and run +the command +/etc/icpc/cleandisk.sh +After that, reboot the system inside the virtual machine (not the host computer itself!) and you +are done. All files belonging to the icpc user have been erased. + +- Because the files are stored in the local team computers, now BOCA (by web) has an option +to make file backups, where teams can save their files on the server. Currently this must be done +manually by the teams (using the web interface of BOCA). There is a script available inside the +ICPC linux (and inside the BOCA package) that teams may use to backup their files. To +do that, they can just run "makebkp.sh". If they want to save other files, it is possible to use +the web interface of the teams. Note that teams should submit backup files with small size only, but +that is not a problem because source codes are really small. The script makebkp.sh is available +(but not very tested) which sends files .c, .cpp, .java and .in (it looks for these files in the +current directory) to the server. IT IS IMPORTANT TO LET THE TEAMS KNOW ABOUT THIS SITUATION AND +THE POSSIBILITY OF SAVING FILES TO THE SERVER, EITHER BY USING THE makebkp.sh IN THE COMMAND-LINE, +OR BY DIRECTLY UPLOADING THE FILES IN THE WEB INTERFACE. + +- The most complicated thing to run the contest using a VM is that you need to restrict the +use of the host operating system. For example, it would be possible for a team to switch +the window (from the VM to another program), and then use the internet (in case you have +internet available in the host, which is usually true). I believe that the simplest approach +to restrict the system is to impose a set of packet filtering rules in the host system, using +a firewall solution. That would make the host system useless for the team. The only permission +that the host must have is to allow connections to the BOCA server and (possibly) to the +authentication server of your network (in case it is needed to keep the host running. Better +if that can be avoided too). If your host is linux, then it is easy: you just need to include some +rules in the iptables (certainly a sysadmin knows how to do it). +For windows (which is probably more usual and easy to deal with), there are many free-of-charge +solutions. I do not know them well, but let me cite some: www.r-firewall.com, +www.personalfirewall.comodo.com, tiny personal firewall (it is possible to find it online), +perhaps the windows firewall can be enough (in some windows versions). NOW THE MOST COMMON / +PRACTICAL WAY TO SOLVE THE PROBLEM: keep an eye on the teams all the time. Have some volunteers +looking the teams work on the computers during the whole contest. No one is allowed to leave the +VM and use the underlying system. If they do that, then simply expel them from the contest! +Give a warn of the possible penalty to everyone before starting and that is it. Quick and clean :D + +- Any vm can become a server for the contest, which in this case will be a BOCA server running +inside a virtual machine system. To do that, you just need to login as user +icpcadmin, become root using the command "sudo /bin/bash" +and execute the script /etc/icpc/becomeserver.sh +READ THE FULL TEXT BEFORE RUNNING THIS SCRIPT. THE VM MUST BE IN BRIDGE MODE (see explanation +below). At this moment, you will be prompted to define the DB password or use a random one. After +that, the IP address of this computer must be used to configure all other VMs (during those +startup questions). +Some considerations about a server: more memory must be used for the server. Have a computer +with enough memory and increase the memory of the VM. Also take care with the +disk space. The current image has only around 1.6GB free (still, that must be more than enough). +Finally, note that to run the VM as the server, it must be configured to run in BRIDGE mode +with respect to the network interface, otherwise it will not be possible for other computers +to reach it. BRIDGE mode means that you must look in your vmplayer (whatever player you are using) +to configure the network as in BRIDGE mode). You may need to reboot the VM. If after rebooting it +and running the command-line program "ifconfig" you can see that the IP address of your computer +is the same inside the VM and outside, you are done. Besides that, the underlying operating +system must have NO apache or postgresql running, nor +any other TCP server in the ports 80 (http), 443 (https) and 5432 (postgres). +Yet I point out that running the BOCA system in a server computer (without the VM) +is the mostly tested solution, but the VM version was used in many sites already. If you want to +run it natively, stop here and go to the xubuntu directory of bombonera.ime.usp.br to see the +instructions. You will need a computer that you can format and reinstall. +That is the simplest way of having a full ICPC linux server +running apart from using the VM version itself, as explained here. + +- After having the server and clients running up, it is necessary to configure the BOCA +web system. For that purpose, please follow the steps of the ADMIN.txt file in the doc/ +folder of the boca system. It is available in the BOCA package or inside the ICPC +linux at /var/www/boca/doc/. There are some examples inside the bits/ subfolder. + +- Try to use the vm without fear. In the worst case, download it again and start again +(or even better, keep a copy of the image without changes). Any questions, please +do not hesitate to contact me: bocasystem@gmail.com. + +- If you need to update the BOCA system that is running in your server (with the risk of losing +data in the database of BOCA!), then you may run the script /etc/icpc/installboca.sh +If you need to update general scripts that are used in the system and were installed by the +installv2.sh procedure, you may run the script /etc/icpc/installscripts.sh +These are easy ways to update the system in case bugs are found and fixed. diff --git a/boca-1.5.0/tools/autojudge.sh b/boca-1.5.0/tools/autojudge.sh new file mode 100755 index 0000000..d0e097b --- /dev/null +++ b/boca-1.5.0/tools/autojudge.sh @@ -0,0 +1,3 @@ +#!/bin/bash +cd /var/www/boca +php private/autojudging.php diff --git a/boca-1.5.0/tools/etc/apache2/conf.d/boca b/boca-1.5.0/tools/etc/apache2/conf.d/boca new file mode 100644 index 0000000..66c62fe --- /dev/null +++ b/boca-1.5.0/tools/etc/apache2/conf.d/boca @@ -0,0 +1,15 @@ +<Directory /var/www/boca/src> + AllowOverride Options AuthConfig Limit + Order Allow,Deny + Allow from all + AddDefaultCharset utf-8 +</Directory> +<Directory /var/www/boca/src/private> + AllowOverride Options AuthConfig Limit + Deny from all +</Directory> +<Directory /var/www/boca> + AllowOverride Options AuthConfig Limit + Deny from all +</Directory> +Alias /boca /var/www/boca/src diff --git a/boca-1.5.0/tools/etc/cron.hourly/.placeholder b/boca-1.5.0/tools/etc/cron.hourly/.placeholder new file mode 100644 index 0000000..76cb8d0 --- /dev/null +++ b/boca-1.5.0/tools/etc/cron.hourly/.placeholder @@ -0,0 +1,2 @@ +# DO NOT EDIT OR REMOVE +# This file is a simple placeholder to keep dpkg from removing this directory diff --git a/boca-1.5.0/tools/etc/cron.hourly/ntp b/boca-1.5.0/tools/etc/cron.hourly/ntp new file mode 100755 index 0000000..40ea135 --- /dev/null +++ b/boca-1.5.0/tools/etc/cron.hourly/ntp @@ -0,0 +1,2 @@ +#!/bin/bash +ntpdate -u 143.107.255.15 diff --git a/boca-1.5.0/tools/etc/icpc/becomeserver.sh b/boca-1.5.0/tools/etc/icpc/becomeserver.sh new file mode 100755 index 0000000..bbbc43b --- /dev/null +++ b/boca-1.5.0/tools/etc/icpc/becomeserver.sh @@ -0,0 +1,193 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 05/aug/2012 by cassio@ime.usp.br +for i in id chown chmod cut awk grep cat sed makepasswd ifconfig iptables php touch mkdir update-rc.d su rm mv; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done + +privatedir=/var/www/boca/private +if [ ! -d $privatedir ]; then + echo "Could not find directory $privatedir" + exit 1 +fi + +apacheuser= +[ -r /etc/icpc/apacheuser ] && apacheuser=`cat /etc/icpc/apacheuser | sed 's/ \t\n//g'` +[ "$apacheuser" == "" ] && apacheuser=www-data +id -u $apacheuser >/dev/null 2>/dev/null +[ $? != 0 ] && echo "User $apacheuser not found -- error to set permissions with chown/chmod" + +postgresuser=postgres +id -u $postgresuser >/dev/null 2>/dev/null +if [ $? != 0 ]; then + echo "User $postgresuser not found -- maybe you use another name (then update this script) or postgres is not installed" + exit 1 +fi + +uid=`id -u` +if [ "$uid" != "0" ]; then + echo "Must be root to run this script. Use sudo /bin/bash first" + exit 1 +fi + +grep -iq "iface.*eth0.*inet.*static" /etc/network/interfaces +if [ $? != 0 ]; then + echo "*****************************************" + echo "IMPORTANT NOTICE ************************" + echo "Network interface eth0 has to be set with" + echo "a static IP address for this computer to " + echo "be a proper server -- DO IT ASAP ********" + echo "*****************************************" + sleep 2 +fi + +BOCASERVER=localhost +if [ -f /etc/icpc/postgresql.version ]; then + . /etc/icpc/postgresql.version +else +POSTGRESV="" +if [ ! -f /etc/init.d/postgresql ]; then + POSTGRESV="-8.4" +fi +fi +if [ ! -f /etc/init.d/postgresql$POSTGRESV ]; then + echo "I did not find the correct version of postgres -- please check it and update this script" + exit 1 +fi + +for i in `ls /etc/postgresql/*/main/pg_hba.conf`; do + grep -q "host.*bocadb.*bocauser" $i + if [ $? != 0 ]; then + echo "############" + echo "I AM GIVING ACCESS TO THE DATABASE FROM ANY IP (AS LONG AS THE PASSWORD IS OK)" + echo "In order to improve security, it is possible to alter the file $i" + echo "and perform a finer tune. Nevertheless, if the password of the DB is safe, there is no big threat" + echo "############" + echo "host bocadb bocauser 0/0 md5" >> $i + fi +done + +for i in `ls /etc/postgresql/*/main/postgresql.conf`; do +grep -q "^[^\#]*listen_addresses" $i +if [ $? != 0 ]; then + echo "listen_addresses = '*'" >> $i +fi +done +for i in `ls /etc/postgresql/*/main/postgresql.conf`; do +grep -q "^[^\#]*max_connections" $i +if [ $? != 0 ]; then + echo "max_connections = 100" >> $i +fi +done +for i in `ls /etc/postgresql/*/main/postgresql.conf`; do +grep -q "^[^\#]*maintenance_work_mem" $i +if [ $? != 0 ]; then + echo "maintenance_work_mem = 64MB" >> $i +fi +done +for i in `ls /etc/postgresql/*/main/postgresql.conf`; do +grep -q "^[^\#]*shared_buffers" $i +if [ $? != 0 ]; then + echo "shared_buffers = 32MB" >> $i +fi +done +for i in `ls /etc/postgresql/*/main/postgresql.conf`; do +grep -q "^[^\#]*work_mem" $i +if [ $? != 0 ]; then + echo "work_mem = 3MB" >> $i +fi +done + +echo "You need to define a password to be used in the database." +echo -n "It is possible generate a random one. Want a random password " +read -p "[Y/n]? " OK +if [ "$OK" = "n" ]; then + read -p "Enter DB password: " -s PASS +else + PASS=`makepasswd --char 8` + echo "The DB password is $PASS" +fi +echo "Keep the DB password safe!" +echo "The IP address that is computer is using is" +echo "(check using the command ifconfig, if desired. Use this address to configure other computers)" +ifconfig eth0 | grep -i "inet addr" + +PASSK=`makepasswd --chars 20` +awk -v boca="$BOCASERVER" -v pass="$PASS" -v passk="$PASSK" '{ if(index($0,"[\"dbpass\"]")>0) \ + print "$conf[\"dbpass\"]=\"" pass "\";"; \ + else if(index($0,"[\"dbhost\"]")>0) print "$conf[\"dbhost\"]=\"" boca "\";"; \ + else if(index($0,"[\"dbsuperpass\"]")>0) print "$conf[\"dbsuperpass\"]=\"" pass "\";"; \ + else if(index($0,"[\"key\"]")>0) print "$conf[\"key\"]=\"" passk "\";"; else print $0; }' \ + < $privatedir/conf.php > $privatedir/conf.php1 +mv -f $privatedir/conf.php1 $privatedir/conf.php +echo "Deny from all" > $privatedir/.htaccess +chown -R $apacheuser.root $privatedir +chmod -R u+rw,g+rw,o-rw $privatedir +iptables -F +echo "BOCASERVER=0/0" > /etc/icpc/bocaserver.sh + + +grep -iq "^[^\#]*ServerName" /etc/apache2/apache2.conf +if [ $? != 0 ]; then + echo "ServerName boca" >> /etc/apache2/apache2.conf +fi + +/etc/init.d/apache2 restart +mkdir -p /var/run/postgresql +chown $postgresuser.$postgresuser /var/run/postgresql +/etc/init.d/postgresql$POSTGRESV restart +update-rc.d apache2 defaults +update-rc.d postgresql$POSTGRESV defaults + +rm -f /tmp/.boca.tmp +su - $postgresuser -c "echo select contestnumber from contesttable | psql -d bocadb | grep contestnumber >/tmp/.boca.tmp 2>/tmp/.boca.tmp" +su - $postgresuser -c "echo drop user bocauser | psql -d template1 >/dev/null 2>/dev/null" +su - $postgresuser -c "echo create user bocauser createdb password \'$PASS\' | psql -d template1" +su - $postgresuser -c "echo alter user bocauser createdb password \'$PASS\' | psql -d template1" + +OK=y +grep -qi contestnumber /tmp/.boca.tmp +if [ $? == 0 ]; then + OK=x + while [ "$OK" != "y" -a "$OK" != "n" ]; do + echo "====== An old database seems to exist. I can keep it, but it might not work with the version" + echo -n "of BOCA being installed. May I erase all the content of the bocadb database [y/n]" + OK=x + read -p "?" OK + done +fi +if [ "$OK" == "y" ]; then +cd /var/www/boca +php private/createdb.php +cd - + echo "database renewed. Data on bocadb has been lost" +else + echo "*** database not erased. Check if BOCA is compatible. You can always erase the database and" + echo "*** fix the problem by running (as root) cd /var/www/boca; php private/createdb.php" + echo "*** still, all data regarding BOCA in the database will be lost" +fi +touch /etc/icpc/.isserver + +echo "configuration finished. Boca should be available at http://localhost/boca/" +echo "reboot might not be required, but is advised." diff --git a/boca-1.5.0/tools/etc/icpc/bocaserver.sh b/boca-1.5.0/tools/etc/icpc/bocaserver.sh new file mode 100755 index 0000000..8bb6c2c --- /dev/null +++ b/boca-1.5.0/tools/etc/icpc/bocaserver.sh @@ -0,0 +1 @@ +BOCASERVER=127.0.0.1 diff --git a/boca-1.5.0/tools/etc/icpc/cleandisk.sh b/boca-1.5.0/tools/etc/icpc/cleandisk.sh new file mode 100755 index 0000000..0d177de --- /dev/null +++ b/boca-1.5.0/tools/etc/icpc/cleandisk.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +mkdir -p /home/icpc +/usr/bin/touch /home/icpc/.cleandisk.sh diff --git a/boca-1.5.0/tools/etc/icpc/createbocajail.sh b/boca-1.5.0/tools/etc/icpc/createbocajail.sh new file mode 100644 index 0000000..e8e0d84 --- /dev/null +++ b/boca-1.5.0/tools/etc/icpc/createbocajail.sh @@ -0,0 +1,122 @@ +#!/bin/bash +homejail=/home/bocajail +[ "$1" != "" ] && homejail=$1 +echo "=================================================================================" +echo "============= CREATING $homejail (this might take some time) ===============" +echo "=================================================================================" +for i in setquota ln id chown chmod dirname useradd mkdir cp rm mv apt-get dpkg uname debootstrap schroot; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done +if [ "`id -u`" != "0" ]; then + echo "Must be run as root" + exit 1 +fi +if [ ! -r /etc/lsb-release ]; then + echo "File /etc/lsb-release not found. Is this a ubuntu or debian-like distro?" + echo "If so, execute the command" + echo "" + echo "DISTRIB_CODENAME=WXYZ > /etc/lsb-release" + echo "" + echo "to save the release name to that file (replace WXYZ with your distro codename)" + exit 1 +fi +. /etc/lsb-release +if [ -d /bocajail/ ]; then + echo "You seem to have already a /bocajail installed" + echo "If you want to reinstall, remove it first (e.g. rm /bocajail) and then run /etc/icpc/createbocajail.sh" + exit 1 +fi + +if [ -f $homejail/proc/cpuinfo ]; then + echo "You seem to have already installed /bocajail and the /bocajail/proc seems to be mounted" + chroot $homejail umount /sys >/dev/nul 2>/dev/null + chroot $homejail umount /proc >/dev/nul 2>/dev/null + echo "Please reboot the system to remove such mounted point" + exit 1 +fi + +id -u bocajail >/dev/null 2>/dev/null +if [ $? != 0 ]; then + useradd -m -s /bin/bash -d $homejail -g users bocajail + if [ -d /etc/gdm ]; then + echo -e "[greeter]\nExclude=bocajail,nobody\n" >> /etc/gdm/custom.conf + fi + sleep 1 +else + echo "user bocajail already exists" + echo "if you want to proceed, first remove it (e.g. userdel bocajail) and then run /etc/icpc/createbocajail.sh" + exit 1 +fi +setquota -u bocajail 0 500000 0 10000 -a + +rm -rf /bocajail +mkdir -p $homejail/tmp +chmod 1777 $homejail/tmp +ln -s $homejail /bocajail +[ -f /usr/bin/safeexec ] && cp -a /usr/bin/safeexec /bocajail/usr/bin/ +#for i in usr lib var bin sbin etc dev; do +# [ -d $homejail/$i ] && rm -rf $homejail/$i +# cp -ar /$i $homejail +#done +#rm -rf $homejail/var/lib/postgres* +#rm -rf $homejail/var/www/* +#mkdir -p $homejail/proc +#mkdir -p $homejail/sys +uname -m | grep -q 64 +if [ $? == 0 ]; then + archt=amd64 +else + archt=i386 +fi + +cat <<FIM > /etc/schroot/chroot.d/bocajail.conf +[bocajail] +description=Jail +location=$homejail +directory=$homejail +root-users=root +type=directory +users=bocajail,nobody,root +FIM + +#debootstrap --arch $archt $DISTRIB_CODENAME $homejail +debootstrap $DISTRIB_CODENAME $homejail +if [ $? != 0 ]; then + echo "bocajail failed to debootstrap" + exit 1 +else +schroot -l | grep -q bocajail +if [ $? == 0 ]; then + echo "bocajail successfully installed at $homejail" +else + echo "*** some error has caused bocajail not to install properly -- I will try it again with different parameters" + grep -v "^location" /etc/schroot/chroot.d/bocajail.conf > /tmp/.boca.tmp + mv /tmp/.boca.tmp /etc/schroot/chroot.d/bocajail.conf + debootstrap $DISTRIB_CODENAME $homejail + schroot -l | grep -q bocajail + if [ $? == 0 ]; then + echo "*** bocajail successfully installed at $homejail" + else + echo "*** bocajail failed to install" + exit 1 + fi +fi +fi + +echo "*** Populating $homejail" +cat <<EOF > /home/bocajail/tmp/populate.sh +#!/bin/bash +mount -t proc proc /proc +apt-get -y update +apt-get -y install g++ gcc libstdc++6 sharutils default-jdk default-jre +umount /proc +EOF +cp -f /etc/apt/sources.list $homejail/etc/apt/ +chmod 755 /home/bocajail/tmp/populate.sh +cd / ; chroot $homejail /tmp/populate.sh diff --git a/boca-1.5.0/tools/etc/icpc/doclean.sh b/boca-1.5.0/tools/etc/icpc/doclean.sh new file mode 100755 index 0000000..ea7d517 --- /dev/null +++ b/boca-1.5.0/tools/etc/icpc/doclean.sh @@ -0,0 +1,28 @@ +#!/bin/bash +cd /home +if [ -f /home/icpc/.cleandisk.sh ]; then +rm -rf /home/icpc +find /home -user icpc -delete +if [ -x /usr/bin/makepasswd ]; then + pass=`echo -n icpc | makepasswd --clearfrom - --crypt-md5 | cut -d'$' -f2-` + pass=\$`echo $pass` + id -u icpc >/dev/null 2>/dev/null + if [ $? != 0 ]; then + useradd -d /home/icpc -m -p "$pass" -s /bin/bash -g users icpc + else + usermod -d /home/icpc -p "$pass" -s /bin/bash -g users icpc + fi +fi +for i in media mnt var opt tmp usr; do + find /$i -user icpc -delete +done +if [ ! -d /home/icpc ]; then + rm -rf /home/icpc + rm -rf /home/skel + cp -ar /etc/skel/ /home + mv /home/skel /home/icpc +fi +chown -R icpc.users /home/icpc +fi +cd - >/dev/null +exit 0 diff --git a/boca-1.5.0/tools/etc/icpc/installboca.sh b/boca-1.5.0/tools/etc/icpc/installboca.sh new file mode 100644 index 0000000..3f91729 --- /dev/null +++ b/boca-1.5.0/tools/etc/icpc/installboca.sh @@ -0,0 +1,106 @@ +#!/bin/bash +di=`date +%s` +echo "===================================================" +echo "=================== obtaining BOCA ===============" +echo "===================================================" + +wget -O /tmp/.boca.tmp "http://www.ime.usp.br/~cassio/boca/boca.date.txt" +echo ">>>>>>>>>>" +echo ">>>>>>>>>> Downloading boca release `cat /tmp/.boca.tmp`" +echo ">>>>>>>>>>" + +if [ "$1" == "" ]; then +wget -O /tmp/.boca.tmp "http://www.ime.usp.br/~cassio/boca/bocaver.txt" +bocaver=`cat /tmp/.boca.tmp` +else +bocaver=$1 +fi +echo "Looking for BOCA version $bocaver from http://www.ime.usp.br/~cassio/boca/" +cd /var/www +rm -f boca-$bocaver.tgz +wget -O boca-$bocaver.tgz "http://www.ime.usp.br/~cassio/boca/download.php?filename=boca-$bocaver.tgz" +if [ "$?" != "0" -o ! -f boca-$bocaver.tgz ]; then + echo "ERROR downloading BOCA package version $bocaver. Aborting *****************" + exit 1 +fi +grep -qi "bad parameters" boca-$bocaver.tgz +if [ "$?" == "0" ]; then + echo "ERROR downloading BOCA package version $bocaver. Aborting *****************" + exit 1 +fi +echo "===========================================================" +echo "====================== BACKUPING OLD BOCA ===============" +echo "===========================================================" +if [ -d boca-$bocaver ]; then + mv boca-$bocaver boca-$bocaver.$di + echo "OLD BOCA FOLDER for version $bocaver saved as boca-$bocaver.$di" +fi + +echo "=====================================================" +echo "=================== EXTRACTING BOCA ===============" +echo "=====================================================" + +OK=x +if [ -f boca-$bocaver.$di/src/private/conf.php ]; then + echo "OLD CONFIG FILE EXISTS" + OK=x + while [ "$OK" != "y" -a "$OK" != "n" ]; do + OK=x + read -p "Do you want to keep the old private/conf.php file [y/n] (note that the old file might be incompatible with this version)? " OK + done + if [ "$OK" == "n" ]; then + echo "You probably need to update the new file boca-$bocaver/src/private/conf.php with the correct passwords - PLEASE CHECK IT - NOT DONE AUTOMATICALLY" + fi +fi +tar xzf boca-$bocaver.tgz +chown -R www-data.www-data boca-$bocaver/ +[ -f boca-$bocaver.$di/src/private/otherservers ] && cp -f boca-$bocaver.$di/src/private/otherservers boca-$bocaver/src/private/otherservers +if [ "$OK" == "y" ]; then + cp -f boca-$bocaver.$di/src/private/conf.php boca-$bocaver/src/private/conf.php + chown www-data.www-data boca-$bocaver/src/private/conf.php + chmod 660 boca-$bocaver/src/private/conf.php +fi +chown root.root boca-$bocaver/src/private/autojudging.php +chmod 600 boca-$bocaver/src/private/autojudging.php +chown root.root boca-$bocaver/src/private/createdb.php +chmod 600 boca-$bocaver/src/private/createdb.php +chown root.root boca-$bocaver/tools/*.sh +chmod 700 boca-$bocaver/tools/*.sh + +echo "==========================================================================================" +echo "=========== SETTING UP SOME LINKS (main apache server index.html updated) ===============" +echo "==========================================================================================" + +rm -f /var/www/boca /usr/bin/makebkp.sh +ln -s /var/www/boca-$bocaver /var/www/boca +ln -s /var/www/boca/tools/makebkp.sh /usr/bin/makebkp.sh +chmod 755 /var/www/boca/tools/makebkp.sh +chmod 755 /var/www/boca/tools/singlefilebkp.sh + +echo "==============================================================" +echo "================== COMPILING safeexec utility ===============" +echo "==============================================================" + +cd /var/www/boca/tools +gcc -static -O2 -Wall safeexec.c -o safeexec +if [ $? == 0 ]; then + echo "COMPILATION OK" +fi +strip safeexec +cp -f safeexec /usr/bin +chmod 4555 /usr/bin/safeexec + +echo "==================================================" +echo "=================== SERVER SETUP ===============" +echo "==================================================" + +OK=n +echo "You can run at anytime later the script /etc/icpc/becomeserver.sh to prepare the computer to be the BOCA server" +read -p "Do you want me to call the script to make this computer the server (don't do it if this install is for a team or autojudge) [y/N]? " OK +if [ "$OK" == "y" -o "$OK" == "Y" ]; then + OK=n + read -p "Do you really want to make this computer the server (you don't need to do it if you are only upgrading BOCA)? [y/N]? " OK + if [ "$OK" == "y" -o "$OK" == "Y" ]; then + /etc/icpc/becomeserver.sh + fi +fi diff --git a/boca-1.5.0/tools/etc/icpc/restart.sh b/boca-1.5.0/tools/etc/icpc/restart.sh new file mode 100755 index 0000000..8c6c98c --- /dev/null +++ b/boca-1.5.0/tools/etc/icpc/restart.sh @@ -0,0 +1,31 @@ +#!/bin/bash +uid=`id -u` +if [ "$uid" != "0" ]; then + echo "Must be root to run this script. Use sudo /bin/bash first" + exit 1 +fi + +apt-get clean +if [ -f /etc/icpc/postgresql.version ]; then + . /etc/icpc/postgresql.version +else +POSTGRESV="" +if [ ! -f /etc/init.d/postgresql ]; then + POSTGRESV="-8.4" +fi +fi + +pass=\$`echo -n icpc | makepasswd --clearfrom - --crypt-md5 | cut -d'$' -f2-` +usermod -p "$pass" icpc + +rm -f /etc/icpc/.isserver +rm -f /etc/icpc/.firsttimedone +rm -f /etc/icpc/bocaserver.sh +/etc/icpc/cleandisk.sh +/etc/init.d/apache2 stop +/etc/init.d/postgresql$POSTGRESV stop +rm -f /var/log/apache2/* +rm -f /var/log/postgresql/* +update-rc.d -f apache2 remove +update-rc.d -f postgresql$POSTGRESV remove + diff --git a/boca-1.5.0/tools/etc/icpc/setup.sh b/boca-1.5.0/tools/etc/icpc/setup.sh new file mode 100755 index 0000000..a854581 --- /dev/null +++ b/boca-1.5.0/tools/etc/icpc/setup.sh @@ -0,0 +1,91 @@ +#!/bin/bash + +if [ ! -x /etc/icpc/bocaserver.sh ]; then + OK=1 + while [ "$OK" != "0" ]; do + IP=`zenity --title="Setting up the BOCA server IP number" --text="Enter the IP address of the server (format x.y.w.z)\n\ +If this is supposed to be the server, then leave it empty" --width=500 --height=100 --entry` + [ "$IP" == "" ] && IP=LOCAL + zenity --title="IP confirmation" --text="The chosen IP is $IP\nDo you confirm?" --question + OK=$? + done + if [ "$IP" = "local" -o "$IP" = "LOCAL" ]; then + IP=127.0.0.1 + BOCASERVER=0/0 + fi + echo "BOCASERVER=$IP" > /etc/icpc/bocaserver.sh + echo "$IP boca boca" >> /etc/hosts + chmod 755 /etc/icpc/bocaserver.sh +fi +. /etc/icpc/bocaserver.sh + +if [ ! -f /etc/icpc/.firsttimedone ]; then + + zenity --title="PAY ATTENTION TO THE FOLLOWING:" \ + --text="It is HIGHLY recommended that you set up a super-user password NOW. Set up the super-user password now?" --question + OK=$? + if [ "$OK" == "0" ]; then + id -u icpcadmin 2>\dev\null >\dev\null + if [ "$?" == "0" ]; then + OK=1 + while [ $OK != 0 ]; do + pass=`zenity --title="Setting up a icpcadmin password" --text="Take care \ + to keep it safe. icpcadmin is the user that \n\ + can become root using the command sudo, e.g. \n\ + sudo /bin/bash \n\ + TEAMS WILL USE THE ACCOUNT icpc, WITH PASSWORD\n\ + icpc. THEY MUST NOT KNOW THE PASSWORD YOU\n\ + ARE SETTING UP HERE, WHICH IS A PRIVILEGIED USER.\n\ + If you need to change the password later, you \n\ + must know the current password and use the \n\ + command-line passwd to change it. Do not forget it" --entry --hide-text` + pass2=`zenity --title="Setting up a icpcadmin password" --text="Re-type it" --entry --hide-text` + if [ "$pass" == "$pass2" -a "$pass" != "" ]; then + OK=0 + else + zenity --info --title="Error" --text="Passwords do not match" + fi + done + pass=\$`/bin/echo -n "$pass2" | /usr/bin/makepasswd --clearfrom - --crypt-md5 | /usr/bin/cut -d'$' -f2-` + pass2="" + /usr/sbin/usermod -p "$pass" icpcadmin + pass=`echo -n icpc | makepasswd --clearfrom - --crypt-md5 | cut -d'$' -f2-` + pass=\$`echo $pass` + /usr/sbin/usermod -p "$pass" icpc + zenity --info --title="Updated" --text="Password of icpcadmin should be updated\nIf not, login in and change it to something safe" + else + zenity --info --title="Update error" --text="User icpcadmin not found -- update your password by yourself." + fi + fi + + if [ "$BOCASERVER" != "0/0" ]; then + OK=1 + while [ $OK != 0 ]; do + pass=`zenity --title="Setting up password of BOCA database" --text="Enter the password of the BOCA database IF AND ONLY IF \n\ +this is NOT a team machine. The password must be entered \n\ +in case this machine will be used for autojudging. \n\ +If you do not enter a password now, it is possible to do \n\ +it later using the command-line /etc/icpc/updatedbpass.sh \n\ +IF THIS IS GOING TO BE USED BY A TEAM, THEN JUST \n\ +PRESS ENTER WITHOUT TYPING ANY PASSWORD\n\ +If this is a server, you may also leave this field empty" --entry --hide-text` + if [ "$pass" == "" ]; then + break + fi + pass2=`zenity --title="Setting up password of BOCA database" --text="Re-type it" --entry --hide-text` + if [ "$pass" == "$pass2" -a "$pass" != "" ]; then + OK=0 + /etc/icpc/updatedbpass.sh "$pass" + else + zenity --info --title="Error" --text="Passwords do not match" + fi + done + fi + touch /etc/icpc/.firsttimedone + zenity --info --title="Setup completed" --text="The setup is completed. If you want to do it again, you might \n\ +run the command-line /etc/icpc/restart.sh\nbut some files in this computer (e.g. from the icpc user) might be lost." +fi + +if [ -x /etc/network/if-pre-up.d/boca ]; then + . /etc/network/if-pre-up.d/boca +fi diff --git a/boca-1.5.0/tools/etc/icpc/updatedbpass.sh b/boca-1.5.0/tools/etc/icpc/updatedbpass.sh new file mode 100755 index 0000000..b100af5 --- /dev/null +++ b/boca-1.5.0/tools/etc/icpc/updatedbpass.sh @@ -0,0 +1,84 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 05/aug/2012 by cassio@ime.usp.br +privatedir=/var/www/boca/src/private + +if [ ! -d $privatedir ]; then + echo "Could not find directory $privatedir" + exit 1 +fi +for i in id chown chmod awk grep cat sed mv; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done +if [ "`id -u`" != "0" ]; then + echo "Script must run as root" +fi + +apacheuser= +[ -r /etc/icpc/apacheuser ] && apacheuser=`cat /etc/icpc/apacheuser | sed 's/ \t\n//g'` +[ "$apacheuser" == "" ] && apacheuser=www-data +id -u $apacheuser >/dev/null 2>/dev/null +[ $? != 0 ] && echo "User $apacheuser not found -- error to set permissions with chown/chmod" + +BOCASERVER=localhost +[ -x /etc/icpc/bocaserver.sh ] && . /etc/icpc/bocaserver.sh +if [ "$BOCASERVER" = "0/0" -o "$BOCASERVER" = "" ]; then + BOCASERVER=localhost +fi +echo "BOCA server is configured to be $BOCASERVER" +if [ "$1" == "" ]; then + read -p "DB password: " -s PASS +else + zenity --info --title="Server info" --text="BOCA server is configured to be $BOCASERVER" + PASS=$1 +fi +PASSK=`makepasswd --chars 20` +awk -v boca="$BOCASERVER" -v pass="$PASS" -v passk="$PASSK" '{ if(index($0,"[\"dbpass\"]")>0) \ + print "$conf[\"dbpass\"]=\"" pass "\";"; \ + else if(index($0,"[\"dbhost\"]")>0) print "$conf[\"dbhost\"]=\"" boca "\";"; \ + else if(index($0,"[\"dbsuperpass\"]")>0) print "$conf[\"dbsuperpass\"]=\"" pass "\";"; \ + else if(index($0,"[\"key\"]")>0) print "$conf[\"key\"]=\"" passk "\";"; else print $0; }' \ + < $privatedir/conf.php > $privatedir/conf.php1 +mv -f $privatedir/conf.php1 $privatedir/conf.php +echo "Deny from all" > $privatedir/.htaccess +chown -R $apacheuser.root $privatedir +chmod -R u+rw,g+rw,o-rw $privatedir +echo "passwords updated in $privatedir/conf.php" + +postgresuser=postgres +id -u $postgresuser >/dev/null 2>/dev/null +if [ $? == 0 -a "$BOCASERVER" == "localhost" ]; then + echo "trying to update password for user bocauser in the database"; + rm -f /tmp/.boca.tmp + su - $postgresuser -c "echo select contestnumber from contesttable | psql -d bocadb | grep contestnumber >/tmp/.boca.tmp 2>/tmp/.boca.tmp" + su - $postgresuser -c "echo drop user bocauser | psql -d template1 >/dev/null 2>/dev/null" + su - $postgresuser -c "echo create user bocauser createdb password \'$PASS\' | psql -d template1 2>/dev/null" + su - $postgresuser -c "echo alter user bocauser createdb password \'$PASS\' | psql -d template1" + rm -f /tmp/.boca.tmp +fi + + +if [ "$1" != "" ]; then + zenity --info --title="Updated" --text="Password updated in $privatedir/conf.php file" +fi diff --git a/boca-1.5.0/tools/etc/network/if-pre-up.d/boca b/boca-1.5.0/tools/etc/network/if-pre-up.d/boca new file mode 100644 index 0000000..f65a27f --- /dev/null +++ b/boca-1.5.0/tools/etc/network/if-pre-up.d/boca @@ -0,0 +1,25 @@ +#!/bin/bash +if [ ! -f /etc/icpc/.isserver ]; then +if [ -x /etc/icpc/bocaserver.sh ]; then + . /etc/icpc/bocaserver.sh +fi +/sbin/iptables -F INPUT +/sbin/iptables -A INPUT -i lo -j ACCEPT +/sbin/iptables -A INPUT -s 143.107.255.15 -j ACCEPT + +# just to make things easier, let's allow communication to/from BOCA servers +/sbin/iptables -A INPUT -s 143.107.45.122 -j ACCEPT +/sbin/iptables -A INPUT -s 50.116.19.221 -j ACCEPT + +if [ "$BOCASERVER" != "" ]; then + /sbin/iptables -A INPUT -s $BOCASERVER -j ACCEPT +fi +/sbin/iptables -A INPUT -m udp -p udp -s 0/0 --sport 67:68 --dport 67:68 -j ACCEPT +/sbin/iptables -A INPUT -m udp -p udp -s 0/0 --sport 53 --dport 53 -j ACCEPT +/sbin/iptables -A INPUT -m tcp -p tcp -s 0/0 --sport 53 --dport 53 -j ACCEPT +/sbin/iptables -A INPUT -j REJECT +else + if [ -x /etc/icpc/bocaserver.iptables ]; then + . /etc/icpc/bocaserver.iptables + fi +fi diff --git a/boca-1.5.0/tools/etc/network/if-up.d/boca b/boca-1.5.0/tools/etc/network/if-up.d/boca new file mode 100644 index 0000000..0f31ee0 --- /dev/null +++ b/boca-1.5.0/tools/etc/network/if-up.d/boca @@ -0,0 +1,17 @@ +#!/bin/bash +if [ ! -f /etc/icpc/.isserver ]; then +if [ -x /etc/icpc/bocaserver.sh ]; then + . /etc/icpc/bocaserver.sh +fi +/sbin/iptables -F INPUT +/sbin/iptables -A INPUT -i lo -j ACCEPT +/sbin/iptables -A INPUT -s 143.107.255.15 -j ACCEPT +if [ "$BOCASERVER" != "" ]; then + /sbin/iptables -A INPUT -s $BOCASERVER -j ACCEPT +fi +/sbin/iptables -A INPUT -j REJECT +else + if [ -x /etc/icpc/bocaserver.iptables ]; then + . /etc/icpc/bocaserver.iptables + fi +fi diff --git a/boca-1.5.0/tools/etc/rc.local b/boca-1.5.0/tools/etc/rc.local new file mode 100755 index 0000000..2b0fff8 --- /dev/null +++ b/boca-1.5.0/tools/etc/rc.local @@ -0,0 +1,34 @@ +#!/bin/bash +# +# rc.local +# +# This script is executed at the end of each multiuser runlevel. +# Make sure that the script will "exit 0" on success or any other +# value on error. +# +# In order to enable or disable this script just change the execution +# bits. +# +# By default this script does nothing. + +if [ -x /etc/icpc/doclean.sh ]; then + /etc/icpc/doclean.sh +fi + +grep -iq "iface.*eth0" /etc/network/interfaces +if [ $? != 0 ]; then + echo "auto eth0" >> /etc/network/interfaces + echo "iface eth0 inet dhcp" >> /etc/network/interfaces +fi + +grep -q "143.107.255.15.*ntp.usp.br.*ntp.usp.br" /etc/hosts +if [ $? != 0 ]; then + echo "143.107.255.15 ntp.usp.br ntp.usp.br" >> /etc/hosts +fi +grep -q "143.107.45.22.*www.ime.usp.br.*www.ime.usp.br" /etc/hosts +if [ $? != 0 ]; then + echo "143.107.45.22 www.ime.usp.br www.ime.usp.br" >> /etc/hosts +fi +ntpdate -u ntp.usp.br +ntpdate -u ntp.usp.br +exit 0 diff --git a/boca-1.5.0/tools/etc/sysctl.d/10-shmmax.conf b/boca-1.5.0/tools/etc/sysctl.d/10-shmmax.conf new file mode 100644 index 0000000..2e7599d --- /dev/null +++ b/boca-1.5.0/tools/etc/sysctl.d/10-shmmax.conf @@ -0,0 +1,2 @@ +kernel.shmmax = 134217728 +kernel.shmall = 33554543 diff --git a/boca-1.5.0/tools/etc/sysctl.d/10-vm-swappiness.conf b/boca-1.5.0/tools/etc/sysctl.d/10-vm-swappiness.conf new file mode 100644 index 0000000..c062945 --- /dev/null +++ b/boca-1.5.0/tools/etc/sysctl.d/10-vm-swappiness.conf @@ -0,0 +1 @@ +vm.swappiness=20 diff --git a/boca-1.5.0/tools/genpackage.sh b/boca-1.5.0/tools/genpackage.sh new file mode 100755 index 0000000..0a61c3a --- /dev/null +++ b/boca-1.5.0/tools/genpackage.sh @@ -0,0 +1,34 @@ +#!/bin/bash +cdir=`pwd` +basen=`basename $cdir` +if [ ! -f "$cdir/genpackage.sh" -o "$basen" != "tools" ]; then + echo "Please run this script from its own directory in tools/ of the BOCA directory" +else +ver=$(basename $(dirname $cdir) | cut -d'-' -f2-) +echo "*** Processing version $ver" +cd ../.. +if [ "$ver" != "" -a -d "boca-$ver" ]; then +echo "boca-$ver" > boca-$ver/src/version +echo -e "<?php\n\$BOCAVERSION='boca-$ver';\n\$YEAR='2012';\n?>\n" > boca-$ver/src/versionnum.php +touch boca-$ver/src/private/runtmp/run0.php boca-$ver/src/private/scoretmp/0.php boca-$ver/src/private/remotescores/0.dat \ + boca-$ver/src/private/remotescores/0.tmp boca-$ver/src/private/problemtmp/problem0.tmp +rm -f boca-$ver/src/balloons/*.png +rm -f boca-$ver/src/private/runtmp/run*.php boca-$ver/src/private/scoretmp/*.php boca-$ver/src/private/remotescores/*.dat \ + boca-$ver/src/private/remotescores/*.tmp +rm -rf boca-$ver/src/private/problemtmp/problem* +touch boca-$ver/.temp +rm boca-$ver/.temp `find boca-$ver/ -name "*.orig"` +touch boca-$ver/.temp +rm boca-$ver/.temp `find boca-$ver/ -name "*~"` +touch boca-$ver/.temp +rm boca-$ver/.temp `find boca-$ver/ -name ".\#*"` +cd boca-$ver/tools/etc +tar cvzf ../icpc.etc.tgz * +cd ../../.. +tar czf boca-$ver.tgz boca-$ver/ +echo "*** file generated: `pwd`/boca-$ver.tgz" +else + echo "*** boca-$ver not found" +fi +fi +cd $cdir diff --git a/boca-1.5.0/tools/icpc.etc.tgz b/boca-1.5.0/tools/icpc.etc.tgz Binary files differnew file mode 100644 index 0000000..890dc3a --- /dev/null +++ b/boca-1.5.0/tools/icpc.etc.tgz diff --git a/boca-1.5.0/tools/installv2.sh b/boca-1.5.0/tools/installv2.sh new file mode 100755 index 0000000..79443ba --- /dev/null +++ b/boca-1.5.0/tools/installv2.sh @@ -0,0 +1,321 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +# // Last modified 05/aug/2012 by cassio@ime.usp.br +#/////////////////////////////////////////////////////////////////////////////////////////// +echo "#############################################################" +echo "### installv2.sh of 09/july/2012 (A) by cassio@ime.usp.br ###" +echo "#############################################################" +# checked with ubuntu 10.04 and 10.10 and 11.04 and 12.04 + +for i in id chown chmod cut awk tail grep cat sed mkdir rm mv sleep apt-get add-apt-repository update-alternatives; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done +sleep 2 + +echo "$0" | grep -q "install.*sh" +if [ $? != 0 ]; then + echo "Make the install script executable (using chmod) and run it directly, like ./installv2.sh" +else + +if [ "`id -u`" != "0" ]; then + echo "Must be run as root" + exit 1 +fi + +if [ "$1" != "alreadydone" ]; then + echo "It is recommended that you run the commands" + echo " apt-get update; apt-get upgrade" + echo "by your own before running this script. If you have already done it," + echo "please run the script as" + echo " ./install.sh alreadydone" + exit 1 +fi + +if [ ! -r /etc/lsb-release ]; then + echo "File /etc/lsb-release not found. Is this a ubuntu or debian-like distro?" + exit 1 +fi +. /etc/lsb-release + +echo "=============================================================" +echo "============== DISABLING AUTO-UPDATE POP-UPS ===============" +echo "=============================================================" +gconftool -s --type bool /apps/update-notifier/auto_launch false +gsettings set com.ubuntu.update-notifier no-show-notifications true +sed -i 's/X-GNOME-Autostart-Delay=60/X-GNOME-Autostart-enabled=false/' /etc/xdg/autostart/update-notifier.desktop + +echo "=============================================================" +echo "========= UNINSTALLING SOME UNNECESSARY PACKAGES ===========" +echo "=============================================================" +apt-get -y purge libreoffice-common libreoffice-base-core bluez thunderbird \ + ubuntuone-client python-ubuntuone-client \ + ubuntuone-installer python-ubuntuone-storageprotocol + +sysvutils=sysvutils +if [ "$DISTRIB_CODENAME" == "oneiric" -o "$DISTRIB_CODENAME" == "precise" ]; then + sysvutils=sysvinit-utils +fi + +echo "=====================================================================" +echo "============== CHECKING FOR canonical.com APT SERVER ===============" +echo "=====================================================================" + +cd +grep -q "^[^\#]*deb http://archive.canonical.com.* $DISTRIB_CODENAME .*partner" /etc/apt/sources.list +if [ $? != 0 ]; then + add-apt-repository "deb http://archive.canonical.com/ubuntu $DISTRIB_CODENAME partner" +fi +apt-get -y update +apt-get -y upgrade + +libCppdev=`apt-cache search libstdc++ | grep "libstdc++6-.*-dev " | sort | tail -n1 | cut -d' ' -f1` +if [ "$libCppdev" == "" ]; then + echo "libstdc++6-*-dev not found" + exit 1 +fi +libCppdbg=`apt-cache search libstdc++ | grep "libstdc++6-.*-dbg " | sort | tail -n1 | cut -d' ' -f1` +if [ "$libCppdbg" == "" ]; then + echo "libstdc++6-*-dbg not found" + exit 1 +fi +libCppdoc=`apt-cache search libstdc++ | grep "libstdc++6-.*-doc " | sort | tail -n1 | cut -d' ' -f1` +if [ "$libCppdoc" == "" ]; then + echo "libstdc++6-*-doc not found" + exit 1 +fi + +echo "=====================================================================" +echo "================= installing packages needed by BOCA ===============" +echo "=====================================================================" + +apt-get -y install zenity apache2 eclipse-pde eclipse-rcp eclipse-platform eclipse-jdt eclipse emacs \ + evince g++ gcc gedit scite libstdc++6 makepasswd manpages-dev mii-diag php5-cli php5-mcrypt openjdk-6-dbg \ + php5 php5-pgsql postgresql postgresql-client postgresql-contrib quota sharutils default-jdk openjdk-6-doc \ + vim-gnome geany geany-plugin-addons geany-plugin-gdb geany-plugins default-jre sysstat \ + $sysvutils vim xfce4 $libCppdev $libCppdoc $libCppdbg php5-gd stl-manual gcc-doc debootstrap schroot c++-annotations +if [ $? != 0 ]; then + echo "" + echo "ERROR running the apt-get -- must check if all needed packages are available" + exit 1 +fi + +for i in makepasswd useradd update-rc.d; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done + + +echo "==================================================================" +echo "============= creating user icpc with password icpc =============" +echo "==================================================================" + +pass=`echo -n icpc | makepasswd --clearfrom - --crypt-md5 | cut -d'$' -f2-` +pass=\$`echo $pass` +id -u icpc >/dev/null 2>/dev/null +if [ $? != 0 ]; then + useradd -d /home/icpc -m -p "$pass" -s /bin/bash -g users icpc +else + usermod -d /home/icpc -p "$pass" -s /bin/bash -g users icpc + echo "user icpc already exists" +fi + +if [ -f /etc/lightdm/lightdm.conf ]; then + echo "==============================================================" + echo "============ disabling guest account on lightdm.conf ========" + echo "==============================================================" + grep -q "^[^\#]*allow-guest" /etc/lightdm/lightdm.conf + if [ $? != 0 ]; then + echo "allow-guest=false" >> /etc/lightdm/lightdm.conf + fi + grep -q "^[^\#]*greeter-hide-users" /etc/lightdm/lightdm.conf + if [ $? != 0 ]; then + echo "greeter-hide-users=true" >> /etc/lightdm/lightdm.conf + fi +fi + +echo "=====================================================================================" +echo "============ updating grub boot loader to make it password protected ===============" +echo "=====================================================================================" + +grep -q "^[^\#]*password" /etc/grub.d/40_custom +if [ $? != 0 ]; then + echo "updated with new password (if needed, see the password at /etc/grub.d/40_custom)" + echo -e "set superusers=\"root\"" >> /etc/grub.d/40_custom + echo -e "password root `makepasswd`" >> /etc/grub.d/40_custom + chmod go-rw /etc/grub.d/40_custom + grub-mkconfig > /boot/grub/grub.cfg + chmod go-rw /boot/grub/grub.cfg +fi +echo "grub loader configured with password (if needed, see the password at /etc/grub.d/40_custom)" + +echo "==============================================================" +echo "============= INSTALLING SCRIPTS at /etc/icpc ===============" +echo "==============================================================" +mkdir -p /etc/icpc +chown root.root /etc/icpc +chmod 755 /etc/icpc +cat <<EOF > /etc/icpc/installscripts.sh +#!/bin/bash +echo "================================================================================" +echo "========== downloading config files from www.ime.usp.br/~cassio/boca ==========" +echo "================================================================================" +iptables -F +wget -O /tmp/.boca.tmp "http://www.ime.usp.br/~cassio/boca/icpc.etc.date.txt" +echo ">>>>>>>>>>" +echo ">>>>>>>>>> Downloading scripts release \`cat /tmp/.boca.tmp\`" +echo ">>>>>>>>>>" + +if [ "\$1" == "" ]; then +wget -O /tmp/.boca.tmp "http://www.ime.usp.br/~cassio/boca/icpc.etc.ver.txt" +icpcver=\`cat /tmp/.boca.tmp\` +else +icpcver=\$1 +fi +echo "Looking for version \$icpcver from http://www.ime.usp.br/~cassio/boca/" + +rm -f /tmp/icpc.etc.tgz +wget -O /tmp/icpc.etc.tgz "http://www.ime.usp.br/~cassio/boca/download.php?filename=icpc-\$icpcver.etc.tgz" +if [ "\$?" != "0" -o ! -f /tmp/icpc.etc.tgz ]; then + echo "ERROR downloading file icpc-\$icpcver.etc.tgz. Aborting *****************" + exit 1 +fi +grep -qi "bad parameters" /tmp/icpc.etc.tgz +if [ "\$?" == "0" ]; then + echo "ERROR downloading file icpc-\$icpcver.etc.tgz. Aborting *****************" + exit 1 +fi + +cd /etc +di=\`date +%s\` + +echo "==============================================================" +echo "====================== BACKUPING CONFIG FILES ===============" + +for i in \`tar tvzf /tmp/icpc.etc.tgz | awk '{ print \$6; }'\`; do + if [ -f "\$i" ]; then + bn=\`basename \$i\` + dn=\`dirname \$i\` + mv \$i \$dn/.\$bn.bkp.\$di + chmod 600 \$dn/.\$bn.bkp.\$di + fi +done + +echo "==============================================================" +echo "====================== EXTRACTING CONFIG FILES ===============" +tar -xkvzf /tmp/icpc.etc.tgz +for i in \`tar tvzf /tmp/icpc.etc.tgz | awk '{ print \$6; }'\`; do + chown root.root \$i + chmod o-w,u+x \$i +done +EOF +chmod 750 /etc/icpc/installscripts.sh +/etc/icpc/installscripts.sh $3 + +service procps start + +grep -q "quota" /etc/fstab +if [ $? != 0 ]; then + cp -f /etc/fstab /etc/fstab.bkp.$di + sed "s/relatime/quota,relatime/" < /etc/fstab.bkp.$di > /etc/fstab.bkp.$di.1 + sed "s/errors=remount-ro/quota,errors=remount-ro/" < /etc/fstab.bkp.$di.1 > /etc/fstab +fi + +echo "============================================================" +echo "===================== SETTING UP USER QUOTA ===============" +echo "============================================================" + +for i in `mount | grep gvfs | cut -d' ' -f3`; do + umount $i +done + +mount / -o remount +quotaoff -a 2>/dev/null +quotacheck -M -a +quotaon -a +setquota -u postgres 0 3000000 0 10000 -a +setquota -u icpc 0 500000 0 10000 -a +setquota -u nobody 0 500000 0 10000 -a +setquota -u www-data 0 1500000 0 10000 -a + +echo "==============================================================" +echo "================= UPDATING rc.local symlinks ===============" +echo "==============================================================" + +update-rc.d rc.local defaults +update-rc.d -f cups remove +apt-get -y clean + +#echo "==============================================================" +#echo "====================== SETTING UP IPs and PASSWORDs (server config follows) ===============" +# +/etc/icpc/restart.sh +#/etc/icpc/setup.sh + +startscript="NOTOK" +if [ -f /etc/lightdm/lightdm.conf ]; then + startscript="OK" + grep -q "^[^\#]*display-setup-script=/etc/icpc/setup.sh" /etc/lightdm/lightdm.conf + if [ $? != 0 ]; then + echo "display-setup-script=/etc/icpc/setup.sh" >> /etc/lightdm/lightdm.conf + fi +fi +if [ -d /etc/gdm/Init ]; then + startscript="OK" + echo "======================================================================================" + echo "========== UPDATING /etc/gdm/Init/Default TO PROVIDE CONFIG AT STARTUP ===============" + echo "======================================================================================" + echo -e "#!/bin/bash\n[ -x /etc/icpc/setup.sh ] && /etc/icpc/setup.sh\n\n" > /tmp/.boca.tmp + cat /etc/gdm/Init/Default >> /tmp/.boca.tmp + mv /tmp/.boca.tmp /etc/gdm/Init/Default + chmod 755 /etc/gdm/Init/Default +fi +if [ "$startscript" != "OK" ]; then + echo "************ STARTUP CALL OF SCRIPTS NOT CONFIGURED **************" + echo "****** neither /etc/gdm/Init nor /etc/lightdm/lightdm.conf were found ************" +fi + +if [ -f /etc/icpc/createbocajail.sh ]; then + chmod 750 /etc/icpc/createbocajail.sh + if [ "$2" != "notbuildjail" ]; then + /etc/icpc/createbocajail.sh + fi +else + echo "************** SCRIPT TO CREATE BOCAJAIL NOT FOUND -- SOMETHING LOOKS WRONG ***************" +fi + +# BOCA CONFIG +if [ -f /etc/icpc/installboca.sh ]; then + chmod 750 /etc/icpc/installboca.sh + /sbin/iptables -F + /etc/icpc/installboca.sh $3 +else + echo "************* SCRIPT TO INSTALL BOCA NOT FOUND -- SOMETHING IS WRONG -- I CANT INSTALL BOCA **************" +fi + +fi diff --git a/boca-1.5.0/tools/makebkp.sh b/boca-1.5.0/tools/makebkp.sh new file mode 100755 index 0000000..5a99c8a --- /dev/null +++ b/boca-1.5.0/tools/makebkp.sh @@ -0,0 +1,32 @@ +#!/bin/bash + +for i in zip du find cut; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo "$i" not found + exit 1 + fi +done + +ex=`which singlefilebkp.sh` +if [ "$ex" = "" ]; then + ex=/var/www/boca/tools/singlefilebkp.sh +fi + +if [ -x "$ex" ]; then + zip /tmp/bkp.zip `find $cdir -name "*.c"` `find $cdir -name "*.java"` `find $cdir -name "*.cpp"` `find $cdir -name "*.in"` + if [ ! -f /tmp/bkp.zip ]; then + echo "Nothing to backup" + else + size=`du -s /tmp/bkp.zip | cut -f1` + if [ "$size" -gt 100000 ]; then + echo Bkp is already too large. BACKUP ABORTED + else + $ex /tmp/bkp.zip + fi + fi +else + echo Bkp script not found or is not executable +fi diff --git a/boca-1.5.0/tools/postgresql.conf.diffs b/boca-1.5.0/tools/postgresql.conf.diffs new file mode 100644 index 0000000..1f02936 --- /dev/null +++ b/boca-1.5.0/tools/postgresql.conf.diffs @@ -0,0 +1,5 @@ +listen_addresses = '*' +max_connections = 300 # (change requires restart) +shared_buffers = 32MB # min 128kB +work_mem = 4MB +maintenance_work_mem = 64MB # min 1MB diff --git a/boca-1.5.0/tools/safeexec.c b/boca-1.5.0/tools/safeexec.c new file mode 100644 index 0000000..1b08d17 --- /dev/null +++ b/boca-1.5.0/tools/safeexec.c @@ -0,0 +1,513 @@ +/* + safeexec + Executar um comando num ambiente protegido + pbv, 1999-2000 + alterado por cassio@ime.usp.br 2003-2011 + + THIS PROGRAM HAS TO BE INSTALLED WITH SETUID ROOT TO HAVE ALL FUNCTIONS WORKING + $ gcc -Wall -o safeexec safeexec.c + $ chown root.root safeexec + $ chmod 4555 safeexec +*/ +#include <stdlib.h> +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> +#include <glob.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <sys/resource.h> +#include <signal.h> +#include <time.h> + +#include <string.h> +#include <errno.h> + +/* tempo de erro entre o sinal e o estouro no caso de time-limit */ +#define EPSILON 0.01 + +#define KBYTE 1024 +#define MBYTE (KBYTE*KBYTE) + +pid_t child_pid; /* pid of the child process */ + +struct rlimit cpu_timeout = {5,5}; /* max cpu time (seconds) */ +struct rlimit max_nofile = {64,64}; /* max number of open files */ +struct rlimit max_fsize = {128*MBYTE,128*MBYTE}; /* max filesize */ + +struct rlimit max_data = {128*MBYTE, 128*MBYTE}; /* max data segment size */ +struct rlimit max_core = {0, 0}; /* max core file size */ +struct rlimit max_rss = {128*MBYTE, 128*MBYTE}; /* max resident set size */ + +struct rlimit max_processes = {64,64}; /* max number of processes */ + + +int real_timeout = 30; /* max real time (seconds) */ + +int dochroot = 0, st=1; +int nruns = 1; +int allproc; +int killallproc; +int bequiet; +int checknchild; +int user, group; +const char vers[] = "1.4.1"; + +#define BUFFSIZE 256 +char curdir[BUFFSIZE], rootdir[BUFFSIZE], saida[BUFFSIZE], entrada[BUFFSIZE], erro[BUFFSIZE]; + +struct Proc { + int uid, pid, ppid, gid, group; + unsigned long utime, stime; + long cutime, cstime; + unsigned long starttime; + unsigned long vsize; + long rss; + long resident, share, text, lib, data; +}; + +unsigned int getprocs(pid_t ppid, pid_t ppid2, int userid, int groupid, int *nchild, struct Proc **Pr); + +void exitandkill(int ret) { + if(killallproc) { + if(!bequiet) + fprintf(stderr,"Notice: killing all recent processes from this user/group to avoid possible malicious code... use -K if you don't want this\n"); + struct Proc *P; + unsigned n; + int nchild, i; + if((n = getprocs(child_pid,getpid(),user,group,&nchild,&P)) > 0) { + for(i = 0; i < n; i++) { + if(!bequiet) + fprintf(stderr,"killing processes pid=%d\n", P[i].pid); + kill(P[i].pid,9); /* kill children and all processes with userid/groupid that started after us if instructed to do so */ + } + } + } + switch(ret) { + case 8: fprintf(stderr,"safeexec: security threat because strange processes\n"); break; + case 7: fprintf(stderr,"safeexec: memory limit exceeded\n"); break; + case 5: fprintf(stderr,"safeexec: parameter problem\n"); break; + case 6: + case 4: fprintf(stderr,"ERROR: internal error\n"); break; + case 3: fprintf(stderr,"safeexec: time limit exceeded\n"); break; + case 2: fprintf(stderr,"safeexec: runtime error\n"); break; + case 9: fprintf(stderr,"safeexec: runtime error\n"); break; + } + exit(ret); +} + +unsigned int getprocs(pid_t ppid, pid_t ppid2, int userid, int groupid, int *nchild, struct Proc **Pr) { + const int SIZE=10000; + char a[SIZE], b[SIZE]; + unsigned long pidtime=0; + glob_t globbuf; + unsigned int i, j, k, ki, oldi, n; + FILE *tn; + struct stat sstat; + struct Proc *P, Ptmp; + + glob("/proc/[0-9]*", GLOB_NOSORT, NULL, &globbuf); + + P = calloc(globbuf.gl_pathc, sizeof(struct Proc)); + if (P == NULL) { + if(!bequiet) fprintf(stderr,"problem with malloc"); + exitandkill(4); + } + *Pr = P; + + for (i = j = 0; i < globbuf.gl_pathc; i++) { + snprintf(a, sizeof(a)-1, "%s%s", + globbuf.gl_pathv[globbuf.gl_pathc - i - 1], "/stat"); + snprintf(b, sizeof(b)-1, "%s%s", + globbuf.gl_pathv[globbuf.gl_pathc - i - 1], "/statm"); +#ifdef DEBUG + fprintf(stderr,"[opening %s and %s]\n", a,b); +#endif + tn = fopen(b, "r"); + if (tn == NULL) continue; /* process vanished since glob() */ + n = fread(b, 1, SIZE, tn); + fclose(tn); + tn = fopen(a, "r"); + if (tn == NULL) continue; /* process vanished since glob() */ + n = fread(a, 1, SIZE, tn); + fstat(fileno(tn), &sstat); + P[j].uid = sstat.st_uid; + P[j].gid = sstat.st_gid; + fclose(tn); + + sscanf(a, "%d %*s %*s %d %d %*s %*s %*s %*s %*s %*s %*s %*s %lu %lu %ld %ld %*s %*s %*s %*s %lu %lu %ld", + &P[j].pid,&P[j].ppid,&P[j].group,&P[j].utime,&P[j].stime,&P[j].cutime,&P[j].cstime,&P[j].starttime,&P[j].vsize,&P[j].rss); + sscanf(b, "%*s %ld %ld %ld %ld %ld", + &P[j].resident,&P[j].share,&P[j].text,&P[j].lib,&P[j].data); + if(P[j].pid == ppid2) pidtime = P[j].starttime; +#ifdef DEBUG + fprintf(stderr,"[check %d,%d,%d,%ld]", P[j].pid, P[j].ppid, P[j].gid, P[j].rss); +#endif + j++; + } + + i = 0; + oldi = 1; + *nchild = 0; + while(i != oldi) { + oldi = i; + for(k = i; k < j; ++k) { + if(P[k].pid != ppid) { + for(ki = 0; ki < i; ++ki) + if(P[k].ppid == P[ki].pid) { + break; + } + if(ki >= i) { + continue; + } + } + Ptmp = P[i]; + P[i] = P[k]; + P[k] = Ptmp; + ++i; + } + } + *nchild = i; + while(i < j) { + if(P[i].uid != userid || P[i].gid != groupid || P[i].starttime < pidtime || P[i].pid==ppid2) { + P[i] = P[--j]; + } else { + if(!bequiet) + fprintf(stderr,"process %d has user %d, group %d, time %lu, which is suspicious\n",P[i].pid,userid,groupid,P[i].starttime); + i++; + } + } + globfree(&globbuf); + return i; +} + +int testsystem(pid_t p, pid_t pp, int userid, int groupid, double memlim, double rsslim) { + struct rusage uso; + getrusage(RUSAGE_CHILDREN, &uso); + double mem1=0., mem2=0.; + struct Proc *P; + unsigned n, i; + int ret = 1, nchild; + n = getprocs(p,pp,userid,groupid,&nchild,&P); + if(checknchild) { + if(nchild != n) { + if(!bequiet) { + fprintf(stderr,"\n%d children of this user/group, but list has %d processes (who are the others?).\n",nchild,n); + fprintf(stderr,"detached children found! Aborting because of possible malicious code... use -a if you don't want this\n"); + } + exitandkill(8); + } + } + if(n > 0) { + for(i = 0; i < n; i++) { +#ifdef DEBUG + fprintf(stderr,"\ndata+stack:%ld, rss:%ld, exe:%ld\n", P[i].data,P[i].rss,P[i].lib+P[i].text+P[i].share); +#endif + mem2 += (P[i].lib+P[i].text+P[i].share+P[i].data)*getpagesize(); // in pages + mem1 += P[i].rss*getpagesize(); + } +#ifdef DEBUG + fprintf(stderr,"\nTOTAL rss:%lf, data+stack+exe:%lf\n", mem1, mem2); +#endif + if(mem2 > memlim || mem1 > rsslim) { + if(!bequiet) + fprintf(stderr,"\nmemory limit exceeded\n"); + exitandkill(7); + } + if(nchild == 0) ret = 2; + } else { + mem1 = ((uso.ru_maxrss+uso.ru_ixrss+uso.ru_idrss+uso.ru_isrss)); +// fprintf(stderr,"WARNING: controlling only waited-for children! Security issues here if code is not trustful...\n"); + if(mem1 > memlim) { + if(!bequiet) + fprintf(stderr,"\nmemory limit exceeded of %lfMB\n",memlim/1048576.); + exitandkill(7); + } + ret = 0; + } + free(P); + return ret; +} + +/* alarm handler */ +void handle_alarm(int sig) { + static int iter=0; +#ifdef DEBUG + fprintf(stderr,"parent alarmed\n"); +#endif + testsystem(child_pid,getpid(),allproc?user:-1,allproc?group:-1,max_data.rlim_max,max_rss.rlim_max); + if(++iter >= real_timeout) { + if(!bequiet) + fprintf(stderr, "timed-out (realtime) after %d seconds\n", real_timeout); + fflush(stderr); + kill(child_pid,9); /* kill child */ + exitandkill(3); + } + alarm(1); /* set alarm and wait for child execution */ +} + + +void usage(int argc, char **argv) { + fprintf(stderr, "safeexec version %s\nusage: %s [ options ] cmd [ arg1 arg2 ... ]\n", vers, argv[0]); + fprintf(stderr, "available options are:\n"); + fprintf(stderr, "\t-c <max core file size> (default: %d)\n", + (int) max_core.rlim_max); + fprintf(stderr, "\t-f <max file size> (default: %d kbytes)\n", + (int) (max_fsize.rlim_max/1024.)); + fprintf(stderr, "\t-F <max number of files> (default: %d)\n", + (int) max_nofile.rlim_max); + fprintf(stderr, "\t-d <max process memory> (default: %d kbytes)\n", + (int) (max_data.rlim_max/1024.)); + fprintf(stderr, "\t-m <max process resident memory> (default: %d kbytes)\n", + (int) (max_rss.rlim_max/1024.)); + fprintf(stderr, "\t-u <max number of child procs> (default: %d)\n", + (int) max_processes.rlim_max); + fprintf(stderr, "\t-t <max cpu time> (default: %d secs)\n", + (int) cpu_timeout.rlim_max); + fprintf(stderr, "\t-T <max real time> (default: %d secs)\n", + (int) real_timeout); + fprintf(stderr, "\t-C <actual directory> (default: cwd)\n"); + fprintf(stderr, "\t-R <root directory> (default: none)\n"); + fprintf(stderr, "\t-n <chroot it?> (default: %d)\n", dochroot); + fprintf(stderr, "\t-r <number of runs?> (default: %d)\n", nruns); + fprintf(stderr, "\t-i <standard input file> (default: not defined)\n"); + fprintf(stderr, "\t-o <standard output file> (default: not defined)\n"); + fprintf(stderr, "\t-e <standard error file> (default: not defined)\n"); + fprintf(stderr, "\t-U <user id> (default: %d)\n", user); + fprintf(stderr, "\t-G <group id> (default: %d)\n", group); + fprintf(stderr, "\t-p <show spent time?> (default: %d)\n", st); + fprintf(stderr, "\t-a disable checking all processes (look only to the non-detached children) (default %s)\n", allproc?"enabled":"disabled"); + fprintf(stderr, "\t-s disable checking existence of detached children (default %s)\n", checknchild?"enabled":"disabled"); + fprintf(stderr, "\t-K disable killing all processes with user/group id after us (default %s)\n", killallproc?"enabled":"disabled"); + fprintf(stderr, "\t-q be quiet (default %s)\n", bequiet?"enabled":"disabled"); +/******* +Note that currently Linux does not support strong memory usage limits, so we have +to enforce it by checking the amount of memory periodically +********/ +} + +int main(int argc, char **argv) { + int status, opt, ret=0; + time_t ini; + int currun = 0; + struct stat sstat; + double dt; + + entrada[0] = saida[0] = erro[0] = rootdir[0] = curdir[0] = 0; + user = group = -1; + allproc = 1; + checknchild=1; + killallproc=1; + bequiet=0; + + if(argc>1 && !strcmp("--help", argv[1])) { + usage(argc,argv); + exit(5); + } + + /* parse command-line options */ + getcwd(curdir, BUFFSIZE); /* default: use cwd as rootdir */ + while( (opt=getopt(argc,argv,"qKar:c:d:m:f:F:t:T:u:n:i:o:e:C:R:G:U:p:s")) != -1 ) { + switch(opt) { + case 'q': bequiet=1; + break; + case 'a': allproc=0; + break; + case 'K': killallproc=0; + break; + case 's': + checknchild=0; + break; + case 'c': max_core.rlim_max = max_core.rlim_cur = atoi(optarg); + break; + case 'f': max_fsize.rlim_max = max_fsize.rlim_cur = KBYTE*atoi(optarg); + break; + case 'F': max_nofile.rlim_max = max_nofile.rlim_cur = atoi(optarg); + break; + case 'd': max_data.rlim_max = max_data.rlim_cur = KBYTE*atoi(optarg); + break; + case 'm': max_rss.rlim_max = max_rss.rlim_cur = KBYTE*atoi(optarg); + break; + case 't': cpu_timeout.rlim_max = cpu_timeout.rlim_cur = atoi(optarg); + break; + case 'T': real_timeout = atoi(optarg); + break; + case 'u': max_processes.rlim_max = max_processes.rlim_cur = atoi(optarg); + break; + case 'U': user = atoi(optarg); + break; + case 'r': nruns = atoi(optarg); + break; + case 'G': group = atoi(optarg); + break; + case 'R': strncpy(rootdir, optarg, 255); /* root directory */ + rootdir[255]=0; + break; + case 'C': strncpy(curdir, optarg, 255); /* root directory */ + curdir[255]=0; + break; + case 'i': strncpy(entrada, optarg, 255); + entrada[255]=0; + break; + case 'o': strncpy(saida, optarg, 255); + saida[255]=0; + break; + case 'e': strncpy(erro, optarg, 255); + erro[255]=0; + break; + case 'n': dochroot = atoi(optarg); + break; + case 'p': st = atoi(optarg); + break; + case '?': usage(argc,argv); + exit(5); + } + } + + if(optind >= argc) { /* no more arguments */ + usage(argc,argv); + exit(5); + } + + if(dochroot && chroot(rootdir)) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr,"%s: unable to chroot to directory %s\n", + argv[0], rootdir); + exit(4); + } + /* change the root directory (ZP: and working dir, in not root)*/ + if(curdir[0] && chdir(curdir)) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr,"%s: unable to change directory to %s\n", + argv[0], curdir); + exit(4); + } + + stat(".", &sstat); + if(user == -1) { + user = (int) sstat.st_uid; + if(!bequiet) { + fprintf(stderr, "Security note: if the sub-code is not trustful, it shall be run with a different user from the one running safeexec.\ +Use -U and -G for that, but you might need to have root privilegies.\n"); + } + } + if(group == -1) + group = (int) sstat.st_gid; + if(user == 0 || group == 0) { + fprintf(stderr, "ERROR: safeexec shall not be instructed to run the sub-code as root\n"); + exit(4); + } + + time(&ini); + dt = 0.; +// int iter=0; + doagain: + if((child_pid=fork())) { + struct rusage uso; + /* ------------------- parent process ----------------------------- */ + if(currun == 0) { + setrlimit(RLIMIT_CORE, &max_core); + } + currun++; + if(!bequiet) + fprintf(stderr,"Starting the job. Parent controller has pid %d, child is %d...\n",getpid(),child_pid); + alarm(1); /* set alarm and wait for child execution */ + signal(SIGALRM, handle_alarm); + while(waitpid(child_pid, &status, 0) != child_pid) ; + testsystem(child_pid,getpid(),allproc?user:-1,allproc?group:-1,max_data.rlim_max,max_rss.rlim_max); + + getrusage(RUSAGE_CHILDREN, &uso); + dt = uso.ru_utime.tv_sec+(double)uso.ru_utime.tv_usec/1000000.0+ + uso.ru_stime.tv_sec+(double)uso.ru_stime.tv_usec/1000000.0; +// printf("user runnning time: %.4lf\n",uso.ru_utime.tv_sec+(double)uso.ru_utime.tv_usec/1000000.0); +// printf("system runnning time: %.4lf\n",uso.ru_stime.tv_sec+(double)uso.ru_stime.tv_usec/1000000.0); +// printf("total runnning time: %.4lf\n",dt); + + if (dt + EPSILON >= cpu_timeout.rlim_max) { +// printf ("utsec=%d utusec=%d stsec=%d stusec=%d\n", uso.ru_utime.tv_sec, uso.ru_utime.tv_usec, uso.ru_stime.tv_sec, uso.ru_stime.tv_usec); + if(!bequiet) + fprintf(stderr, "timed-out (cputime) after %d seconds\n", (int) cpu_timeout.rlim_max); + fflush(stderr); +// fprintf(stdout, "timed-out (cputime) after %d seconds\n", (int) cpu_timeout.rlim_max); +// fflush(stdout); + exitandkill(3); + } + + // check if child got an uncaught signal error & reproduce it in parent + if(WIFSIGNALED(status)) { + fprintf (stderr, "safeexec: RUN-TIME SIGNAL REPORTED BY THE PROGRAM %s: %d\n", argv[optind], WTERMSIG(status)); + fflush(stderr); +// raise(WTERMSIG(status)); + exitandkill(2); + } + + if(WIFEXITED(status)) { + if(WEXITSTATUS(status)) { + ret = WEXITSTATUS(status)+10; + if(!bequiet) + fprintf (stderr, "safeexec: PROGRAM EXITED WITH NONZERO CODE %s: %d\n", + argv[optind], ret-10); + } else ret = 0; + } else { + fprintf (stderr, "safeexec: PROGRAM TERMINATED ABNORMALLY %s\n", + argv[optind]); + exitandkill(9); + } + + if(currun < nruns) goto doagain; + + // otherwise just report the exit code: + if (st) fprintf (stderr, "safeexec: TOTAL TIME RUNNING %s: %u sec (%lf sec)\n", argv[optind], (unsigned int) (time(NULL)-ini), dt); + exitandkill(ret); + } else { + /* ------------------- child process ------------------------------ */ +#ifdef DEBUG + fprintf(stderr,"child started\n"); +#endif + /* change the group id to 'nobody' */ + if(setgid(group)<0) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr, "%s: unable to change gid to %d\n", argv[0], group); + exit(4); + } + /* change the user id to 'nobody' */ + if(setuid(user)<0) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr, "%s: unable to change uid to %d\n", argv[0], user); + exit(4); + } + + if(currun==nruns-1) { + if (saida[0]) freopen(saida, "w", stdout); + if (erro[0]) freopen(erro, "w", stderr); + } else { + freopen("/dev/null", "w", stdout); + freopen("/dev/null", "w", stderr); + } + if (entrada[0]) freopen(entrada, "r", stdin); + + /* attempt to change the hard limits */ + /*******Note that currently Linux does not support memory usage limits********/ + if( setrlimit(RLIMIT_CPU, &cpu_timeout) || + setrlimit(RLIMIT_DATA, &max_data) || + setrlimit(RLIMIT_STACK, &max_data) || + setrlimit(RLIMIT_CORE, &max_core) || + setrlimit(RLIMIT_RSS, &max_rss) || + setrlimit(RLIMIT_FSIZE, &max_fsize) || + setrlimit(RLIMIT_NOFILE, &max_nofile) || + setrlimit(RLIMIT_NPROC, &max_processes) ) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr, "%s: can't set hard limits\n", argv[0]); + exit(6); + } + + /* attempt to exec the child process */ + if(execv(argv[optind],&argv[optind]) < 0) { + fprintf(stderr,"ERROR %s\n",strerror(errno)); + fprintf(stderr, "%s: unable to exec %s\n", argv[0], argv[optind]); + exit(6); + } + } + return 0; +} diff --git a/boca-1.5.0/tools/sendscore.sh b/boca-1.5.0/tools/sendscore.sh new file mode 100755 index 0000000..371c8d2 --- /dev/null +++ b/boca-1.5.0/tools/sendscore.sh @@ -0,0 +1,69 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +# last modified 10/jul/2012 by cassio@ime.usp.br + +if [ "$1" == "" -o "$2" == "" -o "$3" == "" -o "$4" == "" ]; then + echo "Usage $0 <scorefile> <BOCAaddress> <user> <password> [<PC2site>]" + echo "e.g. $0 score.dat http://bombonera.ime.usp.br/boca site1 hardpass" + echo " $0 summary.html http://bombonera.ime.usp.br/boca site1 hardpass 1" + echo "the last number in the previous line indicates the number of the site, which should be unique among sites" + exit 1 +fi +BOCASERVER=$2 +user=$3 +pass=$4 +pc2=0 +if [ "$5" != "" ]; then +pc2=$5 +fi + +for i in wget tr perl md5sum cut; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done + +if [ -r "$1" ]; then +md=`wget -S -T3 -t3 $BOCASERVER/index.php -O /dev/null --save-cookies /tmp/.cookie.txt --keep-session-cookies 2>&1 | grep PHPSESS | tail -n1 | cut -f2 -d'=' | cut -f1 -d';'` +res=`echo -n $pass | md5sum - | cut -f1 -d' '` +res=`echo -n "${res}${md}" | md5sum - | cut -f1 -d' '` +wget -T3 -t3 "$BOCASERVER/index.php?name=${user}&password=${res}" --load-cookies /tmp/.cookie.txt --keep-session-cookies --save-cookies /tmp/.cookie.txt -O /tmp/.temp.txt 2>/dev/null >/dev/null +grep -qi incorrect /tmp/.temp.txt +if [ $? == 0 ]; then + echo User or password incorrect +else +nom=`echo -n $1 | perl -MURI::Escape -lne 'print uri_escape($_)'` +echo -n "PC2=${pc2}&name=${nom}&data=" > /tmp/.temp.txt +if [ "$pc2" != "0" ]; then + uuencode -m zzzzzzzzzz < "$1" | grep -v "begin-base64.*zzzzzzzzzz" | perl -MURI::Escape -lne 'print uri_escape($_)' >> /tmp/.temp.txt +else + cat "$1" | perl -MURI::Escape -lne 'print uri_escape($_)' >> /tmp/.temp.txt +fi +wget -t3 -T3 "$BOCASERVER/site/putfile.php" --load-cookies /tmp/.cookie.txt --keep-session-cookies -O /tmp/.temp2.txt --post-file=/tmp/.temp.txt >/dev/null 2>/dev/null +[ -r /tmp/.temp2.txt ] && cat /tmp/.temp2.txt +rm -f /tmp/.temp2.txt +fi +rm -f /tmp/.temp.txt +rm -f /tmp/.cookie.txt +else + echo file $1 not found +fi diff --git a/boca-1.5.0/tools/singlefilebkp.sh b/boca-1.5.0/tools/singlefilebkp.sh new file mode 100755 index 0000000..8f68c41 --- /dev/null +++ b/boca-1.5.0/tools/singlefilebkp.sh @@ -0,0 +1,46 @@ +#!/bin/bash + +[ -x /etc/icpc/bocaserver.sh ] && . /etc/icpc/bocaserver.sh +if [ "$BOCASERVER" == "" ]; then + echo "This computer has no configured BOCA server. Ask an admin to update /etc/icpc/bocaserver.sh (usually resetting everything is an easy way)" + exit 1 +fi + +for i in uuencode wget tr perl md5sum cut; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo "$i" not found + exit 1 + fi +done + +if [ "$1" == "" ]; then + echo "Usage: $0 <filename>" + exit 1 +fi + +if [ -r "$1" ]; then +md=`wget -S http://$BOCASERVER/boca/index.php -O /dev/null --save-cookies /tmp/.cookie.txt --keep-session-cookies 2>&1 | grep PHPSESS | tail -n1 | cut -f2 -d'=' | cut -f1 -d';'` +echo -n "User: " +read user +echo -n "Password: " +read pass +res=`echo -n $pass | md5sum - | cut -f1 -d' '` +res=`echo -n "${res}${md}" | md5sum - | cut -f1 -d' '` +wget "http://$BOCASERVER/boca/index.php?name=${user}&password=${res}" --load-cookies /tmp/.cookie.txt --keep-session-cookies --save-cookies /tmp/.cookie.txt -O /tmp/.temp.txt 2>/dev/null >/dev/null +grep -qi incorrect /tmp/.temp.txt +if [ $? == 0 ]; then + echo User or password incorrect +else +nom=`echo -n $1 | perl -MURI::Escape -lne 'print uri_escape($_)'` +echo -n "name=${nom}&data=" > /tmp/.temp.txt +uuencode -m zzzzzzzzzz < $1 | grep -v "begin-base64.*zzzzzzzzzz" | perl -MURI::Escape -lne 'print uri_escape($_)' >> /tmp/.temp.txt +wget "http://$BOCASERVER/boca/team/getfile.php" --load-cookies /tmp/.cookie.txt --keep-session-cookies -O /dev/null --post-file=/tmp/.temp.txt >/dev/null 2>/dev/null +fi +rm -f /tmp/.temp.txt +rm -f /tmp/.cookie.txt +else + echo file $1 not found +fi diff --git a/boca-1.5.0/tools/updatescore.sh b/boca-1.5.0/tools/updatescore.sh new file mode 100755 index 0000000..65522b7 --- /dev/null +++ b/boca-1.5.0/tools/updatescore.sh @@ -0,0 +1,129 @@ +#!/bin/bash +# //////////////////////////////////////////////////////////////////////////////// +# //BOCA Online Contest Administrator +# // Copyright (C) 2003-2012 by BOCA Development Team (bocasystem@gmail.com) +# // +# // This program is free software: you can redistribute it and/or modify +# // it under the terms of the GNU General Public License as published by +# // the Free Software Foundation, either version 3 of the License, or +# // (at your option) any later version. +# // +# // 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 the +# // GNU General Public License for more details. +# // You should have received a copy of the GNU General Public License +# // along with this program. If not, see <http://www.gnu.org/licenses/>. +# //////////////////////////////////////////////////////////////////////////////// +# last updated 10/jul/2012 by cassio@ime.usp.br +privatedir=/var/www/boca/src/private/remotescores +others=$privatedir/otherservers +if [ "$1" == "" -o "$2" == "" ]; then + echo "Usage $0 <remotescorefolder> <serversfile>" + echo "e.g. $0 $privatedir $others" + echo "*** When arguments are not given, default values as of the previous line is used" +fi +if [ "$1" != "" ]; then + privatedir=$1 +fi +if [ "$2" != "" ]; then + others=$2 +else + others=$privatedir/otherservers +fi + +for i in id chown chmod md5sum shasum wget tr cut awk tail head grep cat sed sleep; do + p=`which $i` + if [ -x "$p" ]; then + echo -n "" + else + echo command "$i" not found + exit 1 + fi +done +if [ "`id -u`" != "0" ]; then + echo "Script must run as root" +fi + +if [ ! -d $privatedir ]; then + echo "Could not find directory $privatedir" + exit 1 +fi +tempdir=$privatedir/tmp +mkdir -p $tempdir >/dev/null 2>/dev/null +if [ ! -d $tempdir ]; then + echo "Could not create directory $tempdir" + exit 1 +fi +httpbocadir=boca +secs=120 +apacheuser= +[ -r /etc/icpc/apacheuser ] && apacheuser=`cat /etc/icpc/apacheuser | sed 's/ \t\n//g'` +[ "$apacheuser" == "" ] && apacheuser=www-data +id -u $apacheuser > /dev/null 2>/dev/null +[ $? != 0 ] && echo "User $apacheuser not found -- error to set permissions with chown/chmod" + +hash="shasum -a 256 -" +#hash="md5sum -" + +#rm -f $privatedir/score_*.dat +chown $apacheuser.root $privatedir/score_*.dat + +if [ ! -r $others ]; then + echo "External server list in $others not found" + exit 1 +fi +echo "Starting loop to get scores from servers defined in $others" +while /bin/true; do + echo "Getting scores..." + qtd=1 + for BOCASERVER in `grep -v "^[ \t]*\#" $others | awk '{ print $1; }'`; do + if [ "$BOCASERVER" == "" ]; then + continue + fi + echo $BOCASERVER | grep -q "http" + [ $? == 0 ] || BOCASERVER=http://$BOCASERVER/boca + + user=`grep -v "^[ \t]*\#" $others | head -n$qtd | tail -n1 | awk '{ print $2; }'` + [ "$user" == "" ] && user=score + pass=`grep -v "^[ \t]*\#" $others | head -n$qtd | tail -n1 | awk '{ print $2; }'` + [ "$pass" == "" ] && pass=score + let "qtd = $qtd + 1" + + echo -n "Asking server $BOCASERVER. Authenticating with user '$user'..." + md=`wget -t3 -T3 -S $BOCASERVER/index.php -O /dev/null --save-cookies $tempdir/.cookie.txt --keep-session-cookies 2>&1 | grep PHPSESS | tail -n1 | cut -f2 -d'=' | cut -f1 -d';'` + res=`echo -n $pass | $hash | cut -f1 -d' '` + res=`echo -n "${res}${md}" | $hash | cut -f1 -d' '` + echo -n "sending password..." + wget -t3 -T3 "$BOCASERVER/index.php?name=${user}&password=${res}" --load-cookies $tempdir/.cookie.txt --keep-session-cookies --save-cookies $tempdir/.cookie.txt -O $tempdir/.temp.txt 2>/dev/null >/dev/null + grep -qi incorrect $tempdir/.temp.txt + if [ $? != 0 ]; then + rm -f $tempdir/* + echo "downloading scoretable..." + wget -t3 -T3 "$BOCASERVER/scoretable.php?remote=-42" --load-cookies $tempdir/.cookie.txt --keep-session-cookies --save-cookies $tempdir/.cookie.txt -O $tempdir/score.zip 2>$tempdir/.bocascore.tmp >$tempdir/.bocascore.tmp + if [ $? == 0 ]; then + unzip -qq $tempdir/score.zip + if [ $? == 0 ]; then + for fscore in `ls $tempdir/*.dat`; do + chown $apacheuser.root "$tempdir/$fscore" + chmod 660 "$tempdir/$fscore" + mv "$tempdir/$fscore" "$privatedir/score_$fscore" + echo "Score downloaded successfully into $privatedir/score_$fscore" + done + else + echo "Error: score file from $BOCASERVER is not a valid package" + fi + else + echo "Error getting score file from $BOCASERVER: `cat $tempdir/.bocascore.tmp`" + fi + else + echo "Error authenticating to server $BOCASERVER" + fi + rm -f $tempdir/.temp.txt + rm -f $tempdir/.cookie.txt + done + + echo -n "Waiting $secs secs..." + sleep $secs + echo "" +done |