diff options
Diffstat (limited to 'src')
161 files changed, 20593 insertions, 0 deletions
diff --git a/src/.htaccess b/src/.htaccess new file mode 100644 index 0000000..dbafa30 --- /dev/null +++ b/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/src/Css.php b/src/Css.php new file mode 100644 index 0000000..50680b3 --- /dev/null +++ b/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/src/Md5.js b/src/Md5.js new file mode 100644 index 0000000..65c8c44 --- /dev/null +++ b/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/src/admin/answer.php b/src/admin/answer.php new file mode 100644 index 0000000..c2d1fdc --- /dev/null +++ b/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/src/admin/buildproblem.php b/src/admin/buildproblem.php new file mode 100644 index 0000000..0b6c230 --- /dev/null +++ b/src/admin/buildproblem.php @@ -0,0 +1,108 @@ +<?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 31/aug/2012 by cassio@ime.usp.br +require('header.php'); +if(($ct = DBContestInfo($_SESSION["usertable"]["contestnumber"])) == null) + ForceLoad("../index.php"); + +?> +<br><br><center><b><u> +To build a problem package using standard script files, fill in the following fields.</u></b></center> +<br><br> + +<form name="form1" enctype="multipart/form-data" method="post" action="problem.php"> + <input type=hidden name="noflush" value="true" /> + <input type=hidden name="confirmation" value="noconfirm" /> + <script language="javascript"> + function conf() { + var s2 = String(document.form1.probleminput.value); + var s1 = String(document.form1.problemsol.value); + if(document.form1.fullname.value=="" || document.form1.basename=="" || document.form1.timelimit=="" || s1.length<4 || s2.length<4) { + 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 { + document.form1.confirmation.value='confirm'; + } + } + } + </script> + <center> + <table border="0"> + <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 input file:</td> + <td width="65%"> + <input type="file" name="probleminput" value="" size="40" /> + </td> + </tr> + <tr> + <td width="35%" align=right>Problem correct output file:</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> + </table> + </center> + <center> + <input type="submit" name="Submit5" value="Send" onClick="conf()"> + <input type="reset" name="Submit4" value="Clear"> + </center> +</center> +</form> + +</body> +</html> diff --git a/src/admin/clar.php b/src/admin/clar.php new file mode 100644 index 0000000..66a7b0d --- /dev/null +++ b/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/src/admin/claredit.php b/src/admin/claredit.php new file mode 100644 index 0000000..91fae39 --- /dev/null +++ b/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/src/admin/contest.php b/src/admin/contest.php new file mode 100644 index 0000000..ddffed4 --- /dev/null +++ b/src/admin/contest.php @@ -0,0 +1,256 @@ +<?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'); + DBClearProblemTmp($_SESSION["usertable"]["contestnumber"]); + } + } + $param['atualizasites']=$at; + } + DBUpdateContest ($param); + if(strlen($param['unlockkey'])>1) { + DBClearProblemTmp($_SESSION["usertable"]["contestnumber"]); + 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/src/admin/export.php b/src/admin/export.php new file mode 100644 index 0000000..2682c94 --- /dev/null +++ b/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/src/admin/files.php b/src/admin/files.php new file mode 100644 index 0000000..16f0f2d --- /dev/null +++ b/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/src/admin/header.php b/src/admin/header.php new file mode 100644 index 0000000..c308059 --- /dev/null +++ b/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/src/admin/index.php b/src/admin/index.php new file mode 100644 index 0000000..1b35a4c --- /dev/null +++ b/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/src/admin/language.php b/src/admin/language.php new file mode 100644 index 0000000..b2a7481 --- /dev/null +++ b/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/src/admin/log.php b/src/admin/log.php new file mode 100644 index 0000000..ff915ea --- /dev/null +++ b/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/src/admin/option.php b/src/admin/option.php new file mode 100644 index 0000000..81e5879 --- /dev/null +++ b/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/src/admin/problem.php b/src/admin/problem.php new file mode 100644 index 0000000..6a894ba --- /dev/null +++ b/src/admin/problem.php @@ -0,0 +1,414 @@ +<?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 31/aug/2012 by cassio@ime.usp.br +if ($_POST["confirmation"] != "confirm") + unset($_POST['noflush']); + +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['Submit5']) && $_POST['Submit5']=='Build') + ForceLoad("buildproblem.php"); + +if(isset($_POST['Submit5']) && $_POST['Submit5']=='Send') { + if(isset($_POST['basename']) && + isset($_POST['fullname']) && + isset($_POST['timelimit']) && + $_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)) { + ob_end_flush(); + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + } else $name = ""; + if ($_FILES["problemsol"]["name"] != "") { + $type1=myhtmlspecialchars($_FILES["problemsol"]["type"]); + $size1=myhtmlspecialchars($_FILES["problemsol"]["size"]); + $name1=myhtmlspecialchars($_FILES["problemsol"]["name"]); + $temp1=myhtmlspecialchars($_FILES["problemsol"]["tmp_name"]); + if (!is_uploaded_file($temp1)) { + ob_end_flush(); + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + } else $name1 = ""; + if (isset($_FILES["problemdesc"]) && $_FILES["problemdesc"]["name"] != "") { + $type2=myhtmlspecialchars($_FILES["problemdesc"]["type"]); + $size2=myhtmlspecialchars($_FILES["problemdesc"]["size"]); + $name2=myhtmlspecialchars($_FILES["problemdesc"]["name"]); + $temp2=myhtmlspecialchars($_FILES["problemdesc"]["tmp_name"]); + if (!is_uploaded_file($temp2)) { + ob_end_flush(); + IntrusionNotify("file upload problem."); + ForceLoad("../index.php"); + } + } else $name2 = ""; + + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + $tmpdir = getenv("TMP"); + if($tmpdir=="") $tmpdir = getenv("TMPDIR"); + if($tmpdir[0] != $ds) $tmdir = $ds . "tmp"; + if($tmpdir=="") $tmpdir = $ds . "tmp"; + $locr = $_SESSION["locr"]; + $tfile = tempnam($tmpdir, "problem"); + if(@mkdir($tfile . "_d", 0700)) { + $dir = $tfile . "_d"; + @mkdir($dir . $ds . 'limits'); + @mkdir($dir . $ds . 'compare'); + @mkdir($dir . $ds . 'compile'); + @mkdir($dir . $ds . 'run'); + @mkdir($dir . $ds . 'input'); + @mkdir($dir . $ds . 'output'); + @mkdir($dir . $ds . 'tests'); + @mkdir($dir . $ds . 'description'); + $filea = array('compare' . $ds . 'c','compare' . $ds . 'cpp','compare' . $ds . 'java', + 'compile' . $ds . 'c','compile' . $ds . 'cpp','compile' . $ds . 'java', + 'run' . $ds . 'c','run' . $ds . 'cpp','run' . $ds . 'java'); + foreach($filea as $file) { + $rfile=$locr . $ds . '..' . $ds . 'doc' . $ds . 'problemexamples' . $ds . 'problemtemplate' . $ds . $file; + if(is_readable($rfile)) { + @copy($rfile, $dir . $ds . $file); + } else { + @unlink($tfile); + cleardir($dir); + ob_end_flush(); + MSGError('Could not read problem template file ' . $rfile); + ForceLoad('problem.php'); + } + } + $tl = explode(',',$_POST['timelimit']); + if(!isset($tl[1]) || !is_numeric(trim($tl[1]))) $tl[1]='1'; + $str = "echo " . trim($tl[0]) . "\necho " . trim($tl[1]) . "\necho 512\necho " . floor(10 + $size1 / 512) . "\nexit 0\n"; + file_put_contents($dir . $ds . 'limits' . $ds . 'c',$str); + file_put_contents($dir . $ds . 'limits' . $ds . 'cpp',$str); + file_put_contents($dir . $ds . 'limits' . $ds . 'java',$str); + $str = "basename=" . trim($_POST['basename']) . "\nfullname=" . trim($_POST['fullname']); + if($name2) { + @copy($temp2, $dir . $ds . 'description' . $ds . $name2); + @unlink($temp2); + $str .= "\ndescfile=" . $name2; + } + $str .= "\n"; + file_put_contents($dir . $ds . 'description' . $ds . 'problem.info',$str); + if($name && $name1) { + @copy($temp, $dir . $ds . 'input' . $ds . 'file1'); + @unlink($temp); + @copy($temp1, $dir . $ds . 'output' . $ds . 'file1'); + @unlink($temp1); + } else { + @unlink($tfile); + cleardir($dir); + ob_end_flush(); + MSGError('Could not read problem input/output files'); + ForceLoad('problem.php'); + } + $ret=create_zip($dir, glob($dir . $ds . '*'),$dir . '.zip'); + cleardir($dir); + if($ret <= 0) { + @unlink($tfile); + @unlink($dir . '.zip'); + ob_end_flush(); + MSGError('Could not write to zip file'); + ForceLoad('problem.php'); + } + $str = file_get_contents($dir . '.zip'); + @unlink($dir . '.zip'); + @unlink($tfile); + 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-Disposition: attachment; filename=" . basename($dir . '.zip')); + ob_end_flush(); + echo $str; + exit; + } else { + @unlink($tfile); + ob_end_flush(); + MSGError('Could not write to temporary directory'); + } + } + 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"]; + 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?")) { + 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'; + } + } + function conf3(url) { + if (confirm("Confirm the UNDELETION of the PROBLEM?")) { + document.location=url; + } 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') { + if(strpos($prob[$i]["fullname"],"(DEL)") !== false) { + echo " <td nowrap><a href=\"javascript: conf3('problem.php?delete=" . $prob[$i]["number"] . "&input=" . rawurlencode($prob[$i]["inputfilename"]) . + "')\">" . $prob[$i]["number"]; + echo "(deleted)"; + } else { + echo " <td nowrap><a href=\"javascript: conf2('problem.php?delete=" . $prob[$i]["number"] . "&input=" . rawurlencode($prob[$i]["inputfilename"]) . + "')\">" . $prob[$i]["number"]; + } + echo "</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 && isset($prob[$i]["descfilename"])) { + 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> + + <br><br><br><center>To build a problem package from files, use this link: + <input type="submit" name="Submit5" value="Build"> +</center> +</form> + +</body> +</html> diff --git a/src/admin/report.php b/src/admin/report.php new file mode 100644 index 0000000..fe4b88d --- /dev/null +++ b/src/admin/report.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 07/nov/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/webcast.php', ". + "'Webcast File','width=800,height=600,scrollbars=yes,toolbar=yes,menubar=yes,". + "resizable=yes')\">Webcast 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/src/admin/report/clar.php b/src/admin/report/clar.php new file mode 100644 index 0000000..66bd4cd --- /dev/null +++ b/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/src/admin/report/header.php b/src/admin/report/header.php new file mode 100644 index 0000000..1d191de --- /dev/null +++ b/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/src/admin/report/icpc.php b/src/admin/report/icpc.php new file mode 100644 index 0000000..1bf2b86 --- /dev/null +++ b/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/src/admin/report/linechart.php b/src/admin/report/linechart.php new file mode 100644 index 0000000..fa47b17 --- /dev/null +++ b/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/src/admin/report/piechart.php b/src/admin/report/piechart.php new file mode 100644 index 0000000..e6dbf95 --- /dev/null +++ b/src/admin/report/piechart.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 + +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; +else $chart->order=false; + +$tot=0; +for($i=1;$i<count($v); $i+=2) { + $tot += $v[$i+1]; +} +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); + } + if($v[$i+1] > $tot/100) + $chart->addPoint(new Point($v[$i], $v[$i+1], $color)); + else + $chart->addPoint(new Point($v[$i], $tot/100, $color)); +} + +$chart->setTitle($v[0]); +$chart->setLogo($locr. "/images/poweredbyboca.png"); +$chart->render(); + +?> diff --git a/src/admin/report/run.php b/src/admin/report/run.php new file mode 100644 index 0000000..422200d --- /dev/null +++ b/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/src/admin/report/score.php b/src/admin/report/score.php new file mode 100644 index 0000000..0196b3a --- /dev/null +++ b/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/src/admin/report/site.php b/src/admin/report/site.php new file mode 100644 index 0000000..001d48e --- /dev/null +++ b/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/src/admin/report/stat.php b/src/admin/report/stat.php new file mode 100644 index 0000000..1abfa71 --- /dev/null +++ b/src/admin/report/stat.php @@ -0,0 +1,343 @@ +<?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]; + if(isset($d['user'][$keya])) + $vala = $d['user'][$keya]; + else $vala=0; + 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++; + } + if(isset($res[$pos])) + $res[$pos]++; + else $res[$pos]=1; + 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++; + } + if(isset($res[$pos])) + $res[$pos]++; + else $res[$pos]=1; +} + +$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/src/admin/report/task.php b/src/admin/report/task.php new file mode 100644 index 0000000..59ca0e2 --- /dev/null +++ b/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/src/admin/report/webcast.php b/src/admin/report/webcast.php new file mode 100644 index 0000000..5a595fc --- /dev/null +++ b/src/admin/report/webcast.php @@ -0,0 +1,190 @@ +<?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 07/nov/2012 by cassio@ime.usp.br + +require('header.php'); + +$contest = $_SESSION["usertable"]["contestnumber"]; +$site = $_SESSION["usertable"]["usersitenumber"]; + +$ct = DBContestInfo($contest); +if(($st = DBSiteInfo($contest, $site)) == null) + ForceLoad("../index.php"); + +//if(isset($_GET['full']) && $_GET['full'] > 0) + $freezeTime = $st['siteduration']; +//else +// $freezeTime = $st['sitelastmilescore']; + +$contestfile = $ct['contestname'] . "\n"; + +$contestfile = $contestfile . + $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); + +$contestfile = $contestfile . + $numTeams . '' . + $numProblems . "\n"; + +for ($i = 0; $i < $numTeams; $i++) { + $a = DBRow($r, $i); + $teamID = $a['username']; + if(isset($a['usershortname'])) + $teamName = $a['usershortname']; + else + $teamName = $a['userfullname']; + if(isset($a['usershortinstitution'])) + $teamUni = $a['usershortinstitution']; + else + $teamUni = $teamName; + + $contestfile = $contestfile . + $teamID . '' . + $teamUni . '' . + $teamName . "\n"; +} + +$contestfile = $contestfile . + '1' . '' . '1' . "\n"; +$contestfile = $contestfile . + $numProblems . '' . 'Y' . "\n"; + +$score = DBScore($_SESSION["usertable"]["contestnumber"], false, -1, $ct["contestlocalsite"]); + +//$contestfile = $contestfile . +// "<h2>ICPC Output</h2>"; +//$contestfile = $contestfile . +// "<pre>"; +$n=0; +$class=1; +while(list($e, $c) = each($score)) { + if(isset($score[$e]["site"]) && isset($score[$e]["user"])) { + if(DBSiteInfo($_SESSION["usertable"]["contestnumber"],$score[$e]["site"]) != null) { + $r = DBUserInfo($_SESSION["usertable"]["contestnumber"], + $score[$e]["site"], $score[$e]["user"]); + $contestfile = $contestfile . + $r["usericpcid"] . "," . + $class++ . "," . + $score[$e]["totalcount"] . "," . + $score[$e]["totaltime"] . ","; + + if($score[$e]["first"]) + $contestfile = $contestfile . $score[$e]["first"] . "\n"; + else $contestfile = $contestfile . "0\n"; + $n++; + } + } +} +//$contestfile = $contestfile . +// "</pre>"; + +$timefile = $st['currenttime']; +$versionfile = '1.0' . "\n"; + +$run = DBAllRunsInSites($contest, $site, 'run'); + +$numRuns = count($run); + +$runfile = ''; +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; + } + + $runfile = $runfile . + $runID . '' . + $runTime . '' . + $runTeam . '' . + $runProblem . ''; + + if ($run[$i]['yes']=='t') { + $runfile = $runfile . + 'Y' . "\n"; + } else if ($run[$i]['answer'] == 'Not answered yet') { + $runfile = $runfile . + '?' . "\n"; + } else { + $runfile = $runfile . + 'N' . "\n"; + } +} + +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +if(isset($_SESSION['locr'])) { + $webcastdir = $_SESSION['locr'] . $ds . 'private' .$ds. 'webcast'; + $webcastparentdir = $_SESSION['locr'] . $ds. 'private'; +} else { + $webcastdir = $locr . $ds . 'private' . $ds . 'webcast'; + $webcastparentdir = $locr . $ds . 'private'; +} +cleardir($webcastdir); +@mkdir($webcastdir); +if(is_writable($webcastdir)) { + file_put_contents($webcastdir . $ds . 'runs',$runfile); + file_put_contents($webcastdir . $ds . 'contest',$contestfile); + file_put_contents($webcastdir . $ds . 'version',$versionfile); + file_put_contents($webcastdir . $ds . 'time',$timefile); + if(@create_zip($webcastparentdir,array('webcast'),$webcastdir . ".tmp") != 1) { + LOGError("Cannot create score webcast.tmp file"); + MSGError("Cannot create score webcast.tmp file"); + } else { + $cf = globalconf(); + file_put_contents($webcastdir . ".tmp",encryptData(file_get_contents($webcastdir . ".tmp"), $cf["key"],false)); + @rename($webcastdir . ".tmp",$webcastdir . '.zip'); + } + echo "<br><br><br><center>"; + echo "<a href=\"$locr/filedownload.php?". + filedownload(-1,$webcastdir . '.zip') . "\">CLICK TO DOWNLOAD</a>"; + echo "</center>"; +} else { + LOGError('Error creating the folder for the ZIP file: '. $webcastdir); + MSGError('Error creating the folder for the ZIP file: '.$webcastdir); + ForceLoad("../index.php"); +} +echo "<br><br><br>\n"; +echo "<br><br><br>\n"; +echo "<br><br><br>\n"; +echo "<br><br><br>\n"; +echo "<br><br><br>\n"; +echo "<br><br><br>\n"; +?> +<?php include("$locr/footnote.php"); ?> diff --git a/src/admin/run.php b/src/admin/run.php new file mode 100644 index 0000000..4ec0eca --- /dev/null +++ b/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/src/admin/runedit.php b/src/admin/runedit.php new file mode 100644 index 0000000..fa691e8 --- /dev/null +++ b/src/admin/runedit.php @@ -0,0 +1,320 @@ +<?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"]); +?> +<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 "<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>:</td> + <td width="83%"> + <i> <?php echo $a["language"]; ?></i></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/src/admin/score.php b/src/admin/score.php new file mode 100644 index 0000000..ef9675d --- /dev/null +++ b/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/src/admin/site.php b/src/admin/site.php new file mode 100644 index 0000000..84241f3 --- /dev/null +++ b/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/src/admin/task.php b/src/admin/task.php new file mode 100644 index 0000000..a7a5339 --- /dev/null +++ b/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/src/admin/user.php b/src/admin/user.php new file mode 100644 index 0000000..adde9db --- /dev/null +++ b/src/admin/user.php @@ -0,0 +1,469 @@ +<?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"]) && isset($_POST["passwordo"]) && $_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['permitip'] = htmlspecialchars($_POST["userip"]); + $param['contest'] = $_SESSION["usertable"]["contestnumber"]; + + $passcheck = htmlspecialchars($_POST["passwordo"]); + $a = DBUserInfo($_SESSION["usertable"]["contestnumber"], $_SESSION["usertable"]["usersitenumber"], $_SESSION["usertable"]["usernumber"], null, false); + if(myhash($a['userpassword'] . session_id()) != $passcheck) { + MSGError('Admin password is incorrect'); + } else { + if ($_POST["passwordn1"] == $_POST["passwordn2"]) { + $param['pass'] = bighexsub(htmlspecialchars($_POST["passwordn1"]),$a['userpassword']); + if($param['user'] != 1000) + 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($param['usernumber'] != 1000 && DBNewUser($param)) { + $oklines++; + } else { + unset($userlist[$param['site'] . '-' . $param['usernumber']]); + break; + } + } + } + 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($param['usernumber'] != 1000 && DBNewUser($param)) { + $oklines++; + } else { + unset($userlist[$param['site'] . '-' . $param['usernumber']]); + break; + } + } + } + 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) + if($param['usernumber'] != 1000) 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 = bighexsoma(js_myhash(document.form3.passwordn1.value),js_myhash(document.form3.passwordo.value)); + document.form3.passwordn2.value = bighexsoma(js_myhash(document.form3.passwordn2.value),js_myhash(document.form3.passwordo.value)); + document.form3.passwordo.value = js_myhash(js_myhash(document.form3.passwordo.value)+'<?php echo session_id(); ?>'); +// 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> + <tr> + <td width="35%" align=right>Admin (this user) Password:</td> + <td width="65%"> + <input type="password" name="passwordo" 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/src/balloon.php b/src/balloon.php new file mode 100644 index 0000000..ae5e186 --- /dev/null +++ b/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/src/balloons/index.html b/src/balloons/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/balloons/index.html diff --git a/src/db.php b/src/db.php new file mode 100644 index 0000000..6d437dc --- /dev/null +++ b/src/db.php @@ -0,0 +1,311 @@ +<?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; + } + if(isset($conf["dbclientenc"])) + 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; + } + if(isset($conf["dbencoding"])) + $r = DBExec($conn, "create database ${conf["dbname"]} with encoding = '${conf["dbencoding"]}'", "DBCreateDatabase(create)"); + else + $r = DBExec($conn, "create database ${conf["dbname"]} with encoding = 'UTF8'", "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/src/fanswer.php b/src/fanswer.php new file mode 100644 index 0000000..b689a72 --- /dev/null +++ b/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/src/favicon.ico b/src/favicon.ico Binary files differnew file mode 100644 index 0000000..a64595a --- /dev/null +++ b/src/favicon.ico diff --git a/src/fballoon.php b/src/fballoon.php new file mode 100644 index 0000000..ffe6596 --- /dev/null +++ b/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/src/fbkp.php b/src/fbkp.php new file mode 100644 index 0000000..b5bcd97 --- /dev/null +++ b/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/src/fclar.php b/src/fclar.php new file mode 100644 index 0000000..0a7b439 --- /dev/null +++ b/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, c.clardatediffans as anstime " . + "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=$st, " . + "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/src/fcontest.php b/src/fcontest.php new file mode 100644 index 0000000..a698fd3 --- /dev/null +++ b/src/fcontest.php @@ -0,0 +1,1290 @@ +<?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) + \"userinfo\" varchar(300) DEFAULT '', + \"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]['changepassword']=true; + if(substr($a[$i]['userpassword'],0,1)=='!') { + $a[$i]['userpassword'] = substr($a[$i]['userpassword'],1); + $a[$i]['changepassword']=false; + } + $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, $c=null,$hashpass=true) { + $sql = "select * from usertable where usernumber=$user and usersitenumber=$site and " . + "contestnumber=$contest"; + $a = DBGetRow ($sql, 0, $c); + 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['changepassword']=true; + if(substr($a['userpassword'],0,1)=='!') { + $a['userpassword'] = substr($a['userpassword'],1); + $a['changepassword']=false; + } + if($hashpass) + $a['userpassword'] = myhash($a['userpassword'] . $a['usersessionextra']); + $inst = explode(']',$a['userfullname']); + if(isset($inst[1])) { + $a['userfullname'] = trim($inst[1]); + $inst = explode('[',$inst[0]); + if(isset($inst[1])) + $a['usershortname'] = trim($inst[1]); + } + $inst = explode(']',$a['userdesc']); + if(isset($inst[1])) { + $inst2 = explode('[',$inst[0]); + if(isset($inst2[1])) + $a['usershortinstitution'] = trim($inst2[0]); + if(isset($inst[2])) { + $a['userdesc']=trim($inst[2]); + $inst = explode('[',$inst[1]); + if(isset($inst[1])) { + $a['userinstitution'] = trim($inst[1]); + } + } else { + $a['userdesc']=trim($inst[1]); + } + } + 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, $c=null) { + $sql = "select * from sitetable where contestnumber=$contest"; + if($c==null) + $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; + unset($param['updatetime']); + 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','name', + '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); + } + $chd=false; + 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,$c); + 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; + unset($param['updatetime']); + DBUpdateSite ($param,$c); + + if($startdate > 0) { + $p=array(); + $p['contest']=$number; + $p['site']=$s[$i]["sitenumber"]; + $p['start']=$startdate; + DBRenewSiteTime($p, $c); + } + } + } + $chd=true; + } + if($cw) { + DBExec($c, "commit work", "DBUpdateContest(commit)"); + } + if($chd) + LOGLevel("User " . $_SESSION["usertable"]["username"]."/". $_SESSION["usertable"]["usersitenumber"] . " changed the contest $number settings.",2); + 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); + DBinsertfakeproblem($n,$c); + + 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; + + if(isset($param['sitenumber']) && !isset($param['number'])) $param['number']=$param['sitenumber']; + $ac=array('number','siteip','sitename','sitescorelevel','updatetime','startdate','duration'); + $type=array(); + $type['startdate']=1; + $type['duration']=1; + $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($duration=='') $duration = $ct["contestduration"]; + if($startdate=='') $startdate=$ct["conteststartdate"]; + 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"]. + ", $duration, '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']=$startdate; + 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, null, false); + $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['changepassword']) { + MSGError('Password change is DISABLED'); return; + } + if ($a["userpassword"] == "") $temp = myhash(""); + else $temp = $a["userpassword"]; + $lentmp = strlen($temp); + $temp = bighexsub($passn, $temp); + $newpass = substr($temp, strlen($temp)-$lentmp); + + $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; + } + if($type=='team' && $pass != myhash("")) $pass='!'.$pass; + $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>3600) { + $t = ((int) ($t/360))/10; + return array("> ". $t . " hour(s) to start",$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"]; + $str = ''; + if($t >= 3600) { + $str .= ((int)($t/3600)) . 'h '; + $t = $t % 3600; + } + if ($t>60) { + $t = (int) ($t/60); + return array($str . $t . " min(s) left",$s["currenttime"]); + } else if($str=='') { + 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($str . " left",$s["currenttime"]); + } + else return array("not started",-1000000000); +} +// eof +?> diff --git a/src/fextdata.php b/src/fextdata.php new file mode 100644 index 0000000..2799bec --- /dev/null +++ b/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/src/filedownload.php b/src/filedownload.php new file mode 100644 index 0000000..92de694 --- /dev/null +++ b/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/src/filewindow.php b/src/filewindow.php new file mode 100644 index 0000000..594e483 --- /dev/null +++ b/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/src/flanguage.php b/src/flanguage.php new file mode 100644 index 0000000..120fad2 --- /dev/null +++ b/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/src/flog.php b/src/flog.php new file mode 100644 index 0000000..e52e167 --- /dev/null +++ b/src/flog.php @@ -0,0 +1,229 @@ +<?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; + } + $a = DBUserInfo($b["contestnumber"], $b["contestlocalsite"],$a['usernumber'],null,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("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/src/footnote.php b/src/footnote.php new file mode 100644 index 0000000..062dadd --- /dev/null +++ b/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/src/fproblem.php b/src/fproblem.php new file mode 100644 index 0000000..3214a82 --- /dev/null +++ b/src/fproblem.php @@ -0,0 +1,496 @@ +<?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)"); +} + +function DBinsertfakeproblem($n,$c) { + DBExec($c, "insert into problemtable (contestnumber, problemnumber, problemname, problemfullname, ". + "problembasefilename, probleminputfilename, probleminputfile, fake) values ($n, 0, 'General', 'General', NULL, NULL, ". + "NULL, 't')", "DBNewContest(insert problem)"); +} + +//////////////////////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=null) { + if($c==null) + $c = DBConnect(); + $r = DBExec($c, "select p.problemname as problemname, p.problemfullname as fullname, p.problembasefilename " . + "as basefilename, p.problemnumber as number, " . + "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); + if(isset($_SESSION['locr'])) { + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + $nn = $a[$i]['number']; + $ptmp = $_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds . "contest" . $contestnumber ."-problem" . $nn; + if(is_readable($ptmp . ".name")) { + $a[$i]['descfilename']=trim(file_get_contents($ptmp . ".name")); + if($a[$i]['descfilename'] != '') + $a[$i]['descoid']=-1; + } + } + } + return $a; +} +function DBClearProblemTmp($contestnumber) { + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + $ptmp = $_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds . "contest" . $contestnumber . "-*.name"; + foreach(glob($ptmp) as $file) @unlink($file); + $ptmp = $_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds . "contest" . $contestnumber . "-*.hash"; + foreach(glob($ptmp) as $file) @unlink($file); +} +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.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 order by p.problemnumber", + "DBGetFullProblemData(get problem)"); + // and p.problemfullname !~ '(DEL)' + $n = DBnlines($r); + if ($n == 0) { + LOGLevel("No problems defined in the database ($contestnumber)",1); + } + $cf = globalconf(); + $a = array(); + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + for ($i=0;$i<$n;$i++) { + $a[$i] = array_merge(array(),DBRow($r,$i)); + + if(strpos($a[$i]['fullname'],'(DEL)') !== false) continue; + + $nn=$a[$i]['number']; + $ptmp = $_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds . "contest" . $contestnumber ."-problem" . $nn; + $ck = myshorthash(''); + if(is_readable($ptmp . ".hash")) { + $ck = trim(file_get_contents($ptmp . ".hash")); + } + if($ck != $a[$i]['inputhash']) { + @unlink($ptmp . ".name"); + @unlink($ptmp . ".hash"); + $a[$i]['basefilename']=''; + $a[$i]['descfilename']=''; + $a[$i]['fullname']=''; + } + if($freeproblems && $a[$i]['fake'] != 't') { + if(is_readable($ptmp . ".name")) { + $a[$i]['descfilename']=trim(file_get_contents($ptmp . ".name")); + if($a[$i]['descfilename'] != '') + $a[$i]['descoid']=-1; + } else { + @unlink($ptmp . ".name"); + @unlink($ptmp . ".hash"); + $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=@parse_ini_file($dir . $ds . "description" . $ds . 'problem.info'))===false) { + $failed=2; + } + if(!$failed) { + $descfile=''; + if(isset($info['descfile'])) + $descfile=trim(sanitizeText($info['descfile'])); + $basename=trim(sanitizeText($info['basename'])); + $fullname=trim(sanitizeText($info['fullname'])); + if($basename=='' || $fullname=='') + $failed=3; + } + } else $failed=4; + if(!$failed) { + @mkdir($ptmp); + if($descfile != '') { + 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",$ptmp . $ds . $descfile); + file_put_contents($ptmp . ".hash",$a[$i]['inputhash']); + if(is_readable($ptmp . ".name")) { + $a[$i]['descfilename']=trim(file_get_contents($ptmp . ".name")); + if($a[$i]['descfilename'] != '') + $a[$i]['descoid']=-1; + } + } + } else { + @unlink($ptmp . ".name"); + @unlink($ptmp . ".hash"); + } + if(!$failed) { + 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) { + $a[$i]['basefilename']=''; + $a[$i]['descfilename']=''; + @unlink($ptmp . ".name"); + @unlink($ptmp . ".hash"); + DBExec($c,"update problemtable set problemfullname='', problembasefilename='' where problemnumber=$nn and contestnumber=$contestnumber", + "DBGetFullProblemData(unfree problem)"); + + 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); + if(($pos=strpos($a["problemfullname"],"(DEL)")) !== false) { + $sql="update problemtable set problemfullname='".substr($a["problemfullname"],0,$pos) ."', updatetime=".time(). + " where contestnumber=$contestnumber and problemnumber=$number "; + } else { + $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)"); + $ds = DIRECTORY_SEPARATOR; + if($ds=="") $ds = "/"; + + $ptmp = $_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds . "contest" . $contestnumber ."-problem" . $number; + @unlink($ptmp . ".name"); + @unlink($ptmp . ".hash"); + + 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, problemcolor) values " . + "($contestnumber, $number, '$name','-1')", "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 . "contest" . $contestnumber ."-problem" . $number . '.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 = "/"; + $nn = $a[$i]['number']; + $ptmp = $_SESSION["locr"] . $ds . "private" . $ds . "problemtmp" . $ds . "contest" . $contest ."-problem" . $nn; + if(is_readable($ptmp . ".name")) { + $a[$i]['descfilename']=trim(file_get_contents($ptmp . ".name")); + if($a[$i]['descfilename'] != '') + $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/src/freport.php b/src/freport.php new file mode 100644 index 0000000..6182d42 --- /dev/null +++ b/src/freport.php @@ -0,0 +1,154 @@ +<?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 + if(isset($xuser[$a['user']])) + $xuser[$a['user']]++; + else $xuser[$a['user']]=1; + // # of runs by problem + if(isset($xproblem[$a['problem']])) + $xproblem[$a['problem']]++; + else $xproblem[$a['problem']]=1; + if($a['yes'] == 't') { + if(isset($xuseryes[$a['user']])) + $xuseryes[$a['user']]++; + else $xuseryes[$a['user']]=1; + $xproblemyes[$a['problem']]++; + } + // # of runs by language + if(isset($xlanguage[$a['language']])) + $xlanguage[$a['language']]++; + else $xlanguage[$a['language']]=1; + if($a['yes'] == 't') { + if(isset($xlanguageyes[$a['language']])) + $xlanguageyes[$a['language']]++; + else $xlanguageyes[$a['language']]=1; + } + // # of runs by answer + if(isset( $xanswer[$a['answer']])) + $xanswer[$a['answer']]++; + else $xanswer[$a['answer']]=1; + // time of the runs + array_push($xtimestamp, $a['timestamp']); + if($a['yes'] == 't') + array_push($xtimestampyes, $a['timestamp']); + + // # of runs by answer by problem + if(isset($xpa[$a['problem']][$a['answer']])) + $xpa[$a['problem']][$a['answer']]++; + else $xpa[$a['problem']][$a['answer']]=1; + // # of runs by language by problem + if(isset($xpl[$a['problem']][$a['language']])) + $xpl[$a['problem']][$a['language']]++; + else $xpl[$a['problem']][$a['language']]=1; + // # of runs by answer by language + if(isset($xla[$a['language']][$a['answer']])) + $xla[$a['language']][$a['answer']]++; + else $xla[$a['language']][$a['answer']]=1; + // # of runs by problem by user + // negative sign means team got an yes for the problem + if(!isset($xup[$a['user']][$a['problem']])) + $xup[$a['user']][$a['problem']]=0; + 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/src/frun.php b/src/frun.php new file mode 100644 index 0000000..14395e3 --- /dev/null +++ b/src/frun.php @@ -0,0 +1,1027 @@ +<?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) { + $bw = 0; + if($c==null) { + $bw = 1; + $c = DBConnect(); + DBExec($c, "begin work", "DBUpdateRunC(transaction)"); + } + + $a = DBGetRow("select * from answertable where answernumber=$answer and contestnumber=$contest",0,$c, + "DBUpdateRunC(get answer)"); + if ($a == null) { + DBExec($c, "rollback work", "DBUpdateRunC(rollback)"); + 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') { + DBExec($c, "rollback work", "DBUpdateRunC(rollback)"); + 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, $c); + if ($b == null) { + exit; + } + + $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),$c); + 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),$c); + +// if ($runsite==$usersite) { + if (!$tinhabalao && $tembalao) { + if (($b = DBSiteInfo($contest, $runsite, $c)) == null) + return true; + $ta = $b["currenttime"]; + $tf = $b["sitelastmileanswer"]; + if ($ta < $tf) { + $u = DBUserInfo ($contest, $runsite, $team, $c); + if($u['usertype']=='team') { + $p = DBGetProblemData ($contest, $temp["runproblem"],$c); + 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, $c); + if($u['usertype']=='team') { + $p = DBGetProblemData ($contest, $temp["runproblem"],$c); + 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"],true,$c); + + $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"],true,$c); + if ($tinhabalao && !$tembalao) { + $u = DBUserInfo ($contest, $site, $temp["usernumber"], $c); + if($u['usertype']=='team') { + $p = DBGetProblemData ($contest, $temp["runproblem"],$c); + 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"],true,$c); + + 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"],true,$c); + if ($tinhabalao && !$tembalao) { + $u = DBUserInfo ($contest, $site, $temp["usernumber"], $c); + if($u['usertype']=='team') { + $p = DBGetProblemData ($contest, $temp["runproblem"],$c); + 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.probleminputfilename as inputname, p.probleminputfile as inputoid, " . + "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) { if(!isset($param['allowneg'])) { + 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; +} + +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 (or possible java class name mismatch)"; + } else { + $answer="Unknown autojudge status"; + $retval = 7; + } + return array($retval,$answer); +} + +// eof +?> diff --git a/src/fscore.php b/src/fscore.php new file mode 100644 index 0000000..d2b203e --- /dev/null +++ b/src/fscore.php @@ -0,0 +1,357 @@ +<?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 02/nov/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); + + $scoreitems = glob($_SESSION['locr'] . $ds . "private" .$ds . "remotescores" . $ds . "score*.dat", GLOB_NOSORT); + array_multisort(array_map('filemtime', $scoreitems), SORT_NUMERIC, SORT_DESC, $scoreitems); + + foreach ($scoreitems as $fname) { + $namear=explode('_',$fname); + $overloadsite=-1; + if(isset($namear[3]) && is_numeric($namear[2])) $overloadsite=$namear[2]; + $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($overloadsite>0) $site=$overloadsite; + 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, $c=null) { + if($c==null) + $c = DBConnect(); + if (($b = DBSiteInfo($contest, $site, $c)) == null) + exit; + if ($localsite) { + if (($blocal = DBSiteInfo($contest, $_SESSION["usertable"]["usersitenumber"], $c)) == null) + exit; + } else $blocal = $b; + if (($ct = DBContestInfo($contest,$c)) == null) + exit; + + $t = time(); + $ta = $blocal["currenttime"]; +// if ($verifylastmile) + $tf = $b["sitelastmilescore"]; +// else { +// $tf = $b["siteduration"]; +// } + $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]["anstime"] <= $ta && $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]["anstime"] <= $ta && $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/src/ftask.php b/src/ftask.php new file mode 100644 index 0000000..86417b2 --- /dev/null +++ b/src/ftask.php @@ -0,0 +1,515 @@ +<?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($sys=="t") $u="System"; + else $u = "User $user"; + + if($cw) { + DBExec($c, "commit work", "DBNewTask(commit-insert)"); + 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/src/fzip.php b/src/fzip.php new file mode 100644 index 0000000..2a66722 --- /dev/null +++ b/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/src/globals.php b/src/globals.php new file mode 100755 index 0000000..1d07ba1 --- /dev/null +++ b/src/globals.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 09/nov/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])); + if(trim($ip_arr[1]) != '') { + $x = ip2long(trim($ip_arr[1])); + $mask = long2ip($x) == ((int) trim($ip_arr[1])) ? $x : 0xffffffff << (32 - ((int) trim($ip_arr[1]))); + } else { + $mask=0xffffffff; + } + $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/src/hex.js b/src/hex.js new file mode 100644 index 0000000..9cd3709 --- /dev/null +++ b/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/src/hex.php b/src/hex.php new file mode 100644 index 0000000..4fa4c16 --- /dev/null +++ b/src/hex.php @@ -0,0 +1,150 @@ +<?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 hex1 - hex2 +function bighexsub ($hex1, $hex2) { + $h1 = strlen($hex1); + $h2 = strlen($hex2); + while ($h1 < $h2) { + $hex1 = '0' . $hex1; + $h1++; + } + while ($h2 < $h1) { + $hex2 = '0' . $hex2; + $h2++; + } + + $i=0; + while ($hex1[$i] == $hex2[$i] && $i<$h1) $i++; + if ($i>=$h1) return '0'; + + if ($hex1[$i] > $hex2[$i]) { + $sinal=''; + } else { + $sinal = '-'; + $a = $hex2; + $hex2 = $hex1; + $hex1 = $a; + } + + $sobra = 0; + $resultado = ''; + for($x = $h1-1; $x>=0; $x--) { + $op1 = (int) hexdec(substr($hex1,$x,1)); + $op2 = (int) hexdec(substr($hex2,$x,1)); + + $r = $op1 - $op2 - $sobra; + if ($r < 0) { + $r += 16; + $sobra = 1; + } else $sobra = 0; + if($x > 0 || dechex($r) != '0') + $resultado = dechex($r) . $resultado; + } + return $sinal . $resultado; +} +// eof +?> diff --git a/src/hide.js b/src/hide.js new file mode 100644 index 0000000..6f27fd2 --- /dev/null +++ b/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<999; i++) { + modifyClassName(currentClass,true,"sitehide"+i); + } + modifyClassName(currentClass,false,"sitehide"+n); +} diff --git a/src/images/12x16.ico b/src/images/12x16.ico Binary files differnew file mode 100644 index 0000000..a64595a --- /dev/null +++ b/src/images/12x16.ico diff --git a/src/images/a.png b/src/images/a.png Binary files differnew file mode 100644 index 0000000..67c7dff --- /dev/null +++ b/src/images/a.png diff --git a/src/images/balloon.jpeg b/src/images/balloon.jpeg Binary files differnew file mode 100644 index 0000000..dca9637 --- /dev/null +++ b/src/images/balloon.jpeg diff --git a/src/images/balloon.png b/src/images/balloon.png Binary files differnew file mode 100644 index 0000000..665573c --- /dev/null +++ b/src/images/balloon.png diff --git a/src/images/balloon1.png b/src/images/balloon1.png Binary files differnew file mode 100644 index 0000000..b20a3e3 --- /dev/null +++ b/src/images/balloon1.png diff --git a/src/images/balloon2.png b/src/images/balloon2.png Binary files differnew file mode 100644 index 0000000..50453c0 --- /dev/null +++ b/src/images/balloon2.png diff --git a/src/images/balloon3.png b/src/images/balloon3.png Binary files differnew file mode 100644 index 0000000..2539db5 --- /dev/null +++ b/src/images/balloon3.png diff --git a/src/images/balloon4.png b/src/images/balloon4.png Binary files differnew file mode 100644 index 0000000..198ee7c --- /dev/null +++ b/src/images/balloon4.png diff --git a/src/images/balloon5.bmp b/src/images/balloon5.bmp Binary files differnew file mode 100644 index 0000000..5ace841 --- /dev/null +++ b/src/images/balloon5.bmp diff --git a/src/images/bigballoon.png b/src/images/bigballoon.png Binary files differnew file mode 100644 index 0000000..b2957ea --- /dev/null +++ b/src/images/bigballoon.png diff --git a/src/images/bigballoon2.png b/src/images/bigballoon2.png Binary files differnew file mode 100644 index 0000000..1726be5 --- /dev/null +++ b/src/images/bigballoon2.png diff --git a/src/images/bigballoonboca.png b/src/images/bigballoonboca.png Binary files differnew file mode 100644 index 0000000..83017c3 --- /dev/null +++ b/src/images/bigballoonboca.png diff --git a/src/images/bigballoonboca1.png b/src/images/bigballoonboca1.png Binary files differnew file mode 100644 index 0000000..c62ae5d --- /dev/null +++ b/src/images/bigballoonboca1.png diff --git a/src/images/bigballoontransp-blink.gif b/src/images/bigballoontransp-blink.gif Binary files differnew file mode 100644 index 0000000..29c73ee --- /dev/null +++ b/src/images/bigballoontransp-blink.gif diff --git a/src/images/bigballoontransp-hash.png b/src/images/bigballoontransp-hash.png Binary files differnew file mode 100644 index 0000000..a03f38d --- /dev/null +++ b/src/images/bigballoontransp-hash.png diff --git a/src/images/bigballoontransp-md5.png b/src/images/bigballoontransp-md5.png Binary files differnew file mode 100644 index 0000000..4f2a2cc --- /dev/null +++ b/src/images/bigballoontransp-md5.png diff --git a/src/images/bigballoontransp-md52.png b/src/images/bigballoontransp-md52.png Binary files differnew file mode 100644 index 0000000..cd285f1 --- /dev/null +++ b/src/images/bigballoontransp-md52.png diff --git a/src/images/bigballoontransp.png b/src/images/bigballoontransp.png Binary files differnew file mode 100644 index 0000000..9879a65 --- /dev/null +++ b/src/images/bigballoontransp.png diff --git a/src/images/poweredbyboca.png b/src/images/poweredbyboca.png Binary files differnew file mode 100644 index 0000000..a74d5cc --- /dev/null +++ b/src/images/poweredbyboca.png diff --git a/src/images/smallballoon.png b/src/images/smallballoon.png Binary files differnew file mode 100644 index 0000000..ba04133 --- /dev/null +++ b/src/images/smallballoon.png diff --git a/src/images/smallballoontransp.png b/src/images/smallballoontransp.png Binary files differnew file mode 100644 index 0000000..4f18618 --- /dev/null +++ b/src/images/smallballoontransp.png diff --git a/src/images/tst.php b/src/images/tst.php new file mode 100644 index 0000000..38f5fd0 --- /dev/null +++ b/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/src/index.php b/src/index.php new file mode 100644 index 0000000..af55fab --- /dev/null +++ b/src/index.php @@ -0,0 +1,143 @@ +<?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(!isset($_GET['action']) || $_GET['action'] != 'scoretransfer') { + 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/src/judge/clar.php b/src/judge/clar.php new file mode 100644 index 0000000..a5d56ce --- /dev/null +++ b/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/src/judge/claredit.php b/src/judge/claredit.php new file mode 100644 index 0000000..5408e6b --- /dev/null +++ b/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/src/judge/header.php b/src/judge/header.php new file mode 100644 index 0000000..db2136d --- /dev/null +++ b/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/src/judge/history.php b/src/judge/history.php new file mode 100644 index 0000000..b612f9a --- /dev/null +++ b/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/src/judge/index.php b/src/judge/index.php new file mode 100644 index 0000000..ec74ce9 --- /dev/null +++ b/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/src/judge/option.php b/src/judge/option.php new file mode 100644 index 0000000..81e5879 --- /dev/null +++ b/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/src/judge/run.php b/src/judge/run.php new file mode 100644 index 0000000..9f08851 --- /dev/null +++ b/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/src/judge/runchief.php b/src/judge/runchief.php new file mode 100644 index 0000000..a4cd443 --- /dev/null +++ b/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/src/judge/runedit.php b/src/judge/runedit.php new file mode 100644 index 0000000..e53b3a3 --- /dev/null +++ b/src/judge/runedit.php @@ -0,0 +1,250 @@ +<?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"]); +?> +<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"]); + + echo "<a href=\"../filedownload.php?". filedownload($b[$i]["inputoid"],$b[$i]["inputfilename"]) . "\">"; + echo basename($b[$i]["inputfilename"]) . "</a>"; +} +?> + </td> + </tr> + <tr> + <td width="27%" align=right><b>Language</b>:</td> + <td width="83%"> + <i> <?php echo $a["language"]; ?></i></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/src/judge/runeditchief.php b/src/judge/runeditchief.php new file mode 100644 index 0000000..c538dca --- /dev/null +++ b/src/judge/runeditchief.php @@ -0,0 +1,320 @@ +<?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"]); +?> +<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>:</td> + <td width="83%"><i> <?php echo $a["language"]; ?></i> + </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/src/judge/score.php b/src/judge/score.php new file mode 100644 index 0000000..bea0800 --- /dev/null +++ b/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/src/judge/team.php b/src/judge/team.php new file mode 100644 index 0000000..11d03ad --- /dev/null +++ b/src/judge/team.php @@ -0,0 +1,195 @@ +<?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(strpos($name,' ') === true || strpos($temp,' ') === true) { + MSGError("File name cannot contain spaces."); + 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); + if($runteam=='team.php') $param['allowneg']=1; + 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/src/libchart/COPYING b/src/libchart/COPYING new file mode 100644 index 0000000..2d2d780 --- /dev/null +++ b/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/src/libchart/ChangeLog b/src/libchart/ChangeLog new file mode 100644 index 0000000..fe6e492 --- /dev/null +++ b/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/src/libchart/README b/src/libchart/README new file mode 100644 index 0000000..0d9500e --- /dev/null +++ b/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/src/libchart/classes/Axis.php b/src/libchart/classes/Axis.php new file mode 100644 index 0000000..c80fe97 --- /dev/null +++ b/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/src/libchart/classes/BarChart.php b/src/libchart/classes/BarChart.php new file mode 100644 index 0000000..5b658ca --- /dev/null +++ b/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/src/libchart/classes/Chart.php b/src/libchart/classes/Chart.php new file mode 100644 index 0000000..639eabd --- /dev/null +++ b/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/src/libchart/classes/Color.php b/src/libchart/classes/Color.php new file mode 100644 index 0000000..178435b --- /dev/null +++ b/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/src/libchart/classes/HorizontalChart.php b/src/libchart/classes/HorizontalChart.php new file mode 100644 index 0000000..4b4e069 --- /dev/null +++ b/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/src/libchart/classes/LineChart.php b/src/libchart/classes/LineChart.php new file mode 100644 index 0000000..9d44eba --- /dev/null +++ b/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/src/libchart/classes/PieChart.php b/src/libchart/classes/PieChart.php new file mode 100644 index 0000000..dacbf2b --- /dev/null +++ b/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/src/libchart/classes/Point.php b/src/libchart/classes/Point.php new file mode 100644 index 0000000..5c0d9ec --- /dev/null +++ b/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/src/libchart/classes/Primitive.php b/src/libchart/classes/Primitive.php new file mode 100644 index 0000000..9e5a896 --- /dev/null +++ b/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/src/libchart/classes/Text.php b/src/libchart/classes/Text.php new file mode 100644 index 0000000..7f7177c --- /dev/null +++ b/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/src/libchart/classes/VerticalChart.php b/src/libchart/classes/VerticalChart.php new file mode 100644 index 0000000..cdb4117 --- /dev/null +++ b/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/src/libchart/fonts/DejaVuSansCondensed-Bold.ttf b/src/libchart/fonts/DejaVuSansCondensed-Bold.ttf Binary files differnew file mode 100644 index 0000000..6f4e42e --- /dev/null +++ b/src/libchart/fonts/DejaVuSansCondensed-Bold.ttf diff --git a/src/libchart/fonts/DejaVuSansCondensed.ttf b/src/libchart/fonts/DejaVuSansCondensed.ttf Binary files differnew file mode 100644 index 0000000..12af357 --- /dev/null +++ b/src/libchart/fonts/DejaVuSansCondensed.ttf diff --git a/src/libchart/images/PoweredBy.png b/src/libchart/images/PoweredBy.png Binary files differnew file mode 100644 index 0000000..6c5290c --- /dev/null +++ b/src/libchart/images/PoweredBy.png diff --git a/src/libchart/libchart.php b/src/libchart/libchart.php new file mode 100644 index 0000000..4f359cb --- /dev/null +++ b/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/src/optionlower.php b/src/optionlower.php new file mode 100644 index 0000000..a813700 --- /dev/null +++ b/src/optionlower.php @@ -0,0 +1,122 @@ +<?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"], + $_SESSION["usertable"]["username"], // $username, but users should not change their names + $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/src/php.php b/src/php.php new file mode 100644 index 0000000..147cebc --- /dev/null +++ b/src/php.php @@ -0,0 +1 @@ +<?php phpinfo(); ?> diff --git a/src/private/.htaccess b/src/private/.htaccess new file mode 100644 index 0000000..3a42882 --- /dev/null +++ b/src/private/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/src/private/autojudging.php b/src/private/autojudging.php new file mode 100755 index 0000000..833d702 --- /dev/null +++ b/src/private/autojudging.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 06/aug/2012 by cassio@ime.usp.br +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +if(is_readable('/etc/boca.conf')) { + $pif=parse_ini_file('/etc/boca.conf'); + $bocadir = trim($pif['bocadir']) . $ds . 'src'; +} else { + $bocadir = getcwd(); +} + +if(is_readable($bocadir . $ds . '..' .$ds . 'db.php')) { + require_once($bocadir . $ds . '..' .$ds . 'db.php'); + require_once($bocadir . $ds . '..' .$ds . 'version.php'); +} else { + if(is_readable($bocadir . $ds . 'db.php')) { + require_once($bocadir . $ds . 'db.php'); + require_once($bocadir . $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; +//$dodebug=1; +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; +} +if(!isset($dodebug)) { + if(isset($dir)) cleardir($dir); + if(isset($name)) unlink($name); +} +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["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"; + 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"; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file not defined"); + continue; +} +$c = DBConnect(); +DBExec($c, "begin work", "Autojudging(exporttransaction)"); +if(DB_lo_export($contest,$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"; + 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: " . $cache . $ds . $run["inputoid"] . "." . $run["inputname"] . "\n"; + $s = file_get_contents($cache . $ds . $run["inputoid"] . "." . $run["inputname"]); + file_put_contents($dir . $ds . $run["inputname"], decryptData($s,$key)); + $basename=$basenames[$run['inputoid']. "." . $run["inputname"]]; +} else { + echo "Downloading problem package file from db into: " . $dir . $ds . $run["inputname"] . "\n"; + if(DB_lo_export($contest,$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"; + 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 package file -- please check the problem package (maybe it is encrypted?)\n"; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid (1)"); + cleardir($dir . $ds . "problemdata"); + continue; + } + if(($info=@parse_ini_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 (2)"); + cleardir($dir . $ds . "problemdata"); + continue; + } + if(isset($info['descfile'])) + $descfile=trim(sanitizeText($info['descfile'])); + $basename=trim(sanitizeText($info['basename'])); + $fullname=trim(sanitizeText($info['fullname'])); + 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 (3)"); + cleardir($dir . $ds . "problemdata"); + continue; + } + $basenames[$run['inputoid']. "." . $run["inputname"]]=$basename; + 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 (4)"); + cleardir($dir . $ds . "problemdata"); + continue; + } + chdir($dir . $ds . "problemdata" . $ds . "limits"); + $limits[$basename]=array(); + 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 . " at " . getcwd() . "\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 (5)"); + cleardir($dir . $ds . "problemdata"); + continue; + } + $limits[$basename][basename($file)] = file('stdout',FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES); + } + $cont=false; + 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 . " at " . getcwd() . "\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 (" . $file . ")"); + $cont=true; + break; + } + } + cleardir($dir . $ds . "problemdata"); + if($cont) + continue; + + $s = file_get_contents($dir . $ds . $run["inputname"]); + file_put_contents($cache . $ds . $run["inputoid"] . "." . $run["inputname"], encryptData($s,$key)); +} + +if(!isset($limits[$basename][$run["extension"]][0]) || !is_numeric($limits[$basename][$run["extension"]][0]) || + !isset($limits[$basename][$run["extension"]][1]) || !is_numeric($limits[$basename][$run["extension"]][1]) || + !isset($limits[$basename][$run["extension"]][2]) || !is_numeric($limits[$basename][$run["extension"]][2]) || + !isset($limits[$basename][$run["extension"]][3]) || !is_numeric($limits[$basename][$run["extension"]][3]) ) { + echo "Failed to find proper limits information for the problem -- please check the problem package\n"; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid (6)"); + continue; +} + +// 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, array("compile" . $ds . $run["extension"])); + $zip->close(); +} else { + echo "Failed to unzip the package file -- please check the problem package\n"; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid (7)"); + 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; +} + +chdir($dir); +@unlink('allout'); +system('touch allout'); +@unlink('allerr'); +system('touch allerr'); + +chmod($script, 0700); +$ex = escapeshellcmd($script) ." ". + escapeshellarg($run["sourcename"])." ". + escapeshellarg($basename) . " ". + escapeshellarg(trim($limits[$basename][$run["extension"]][0]))." ". + escapeshellarg(trim($limits[$basename][$run["extension"]][2])); +$ex .= " >stdout 2>stderr"; +echo "Executing " . $ex . " at " . getcwd() . "\n"; +if(system($ex, $retval)===false) $retval=-1; + +if(is_readable('stdout')) { + system('echo ##### COMPILATION STDOUT: >> allerr'); + system('cat stdout >> allerr'); +} +if(is_readable('stderr')) { + system('echo ##### COMPILATION STDERR: >> allerr'); + system('cat stderr >> allerr'); +} + +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 MBytes) +//# $6 maximum allowed output size (in KBytes) + + $zip = new ZipArchive; + $inputlist = array(); + $ninputlist = 0; + $outputlist = array(); + $noutputlist = 0; + if ($zip->open($dir . $ds . $run["inputname"]) === true) { + for($i = 0; $i < $zip->numFiles; $i++) { + $filename = $zip->getNameIndex($i); + $pos = strrpos(dirname($filename),"input"); + if($pos !== false && $pos==strlen(dirname($filename))-5) { + $inputlist[$ninputlist++] = 'input' . $ds . basename($filename); + $outputlist[$noutputlist++] = 'output' . $ds . basename($filename,'.link'); + } + } + $zip->extractTo($dir, array_merge(array("run" . $ds . $run["extension"]),$inputlist)); + $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 (8)"); + continue; + } + $retval = 0; + $script = $dir . $ds . 'run' . $ds . $run["extension"]; + if(!is_file($script)) { + echo "Failed to unzip the run script -- please check the problem package\n"; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid (9)"); + continue; + } + chmod($script, 0700); + mkdir('team', 0755); + if($ninputlist == 0) { + echo "Failed to read input files from ZIP -- please check the problem package\n"; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid (10)"); + continue; + } else { + $errp=0; + foreach($inputlist as $file) { + $file = basename($file); + if(is_file($dir . $ds . "input" . $ds . $file)) { + $file1=basename($file,'.link'); + if($file != $file1) { + $fnam = trim(file_get_contents($dir . $ds . "input" . $ds . $file)); + echo "Input file $file is a link. Trying to read the linked file: ($fnam)\n"; + if(is_readable($fnam)) { + @unlink($dir . $ds . "input" . $ds . $file); + $file = basename($file,".link"); + @copy($fnam,$dir . $ds . "input" . $ds . $file); + } else { + echo "Failed to read input files from link indicated in the ZIP -- please check the problem package\n"; + DBGiveUpRunAutojudging($contest, $site, $number, $ip, "Autojuging error: problem package file is invalid (11) or missing files on the autojudge"); + $errp=1; break; + } + } + + $ex = escapeshellcmd($script) ." ". + escapeshellarg($basename) . " ". + escapeshellarg($dir . $ds . "input" . $ds . $file)." ". + escapeshellarg(trim($limits[$basename][$run["extension"]][0]))." ". + escapeshellarg(trim($limits[$basename][$run["extension"]][1]))." ". + escapeshellarg(trim($limits[$basename][$run["extension"]][2]))." ". + escapeshellarg(trim($limits[$basename][$run["extension"]][3])); + $ex .= " >stdout 2>stderr"; + echo "Executing " . $ex . " at " . getcwd() . " 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; + } + } else { + echo "==> ERROR reading input file " . $dir . $ds . "input" . $ds . $file . " - skipping it!\n"; + } + } + if($errp==1) continue; + } + if($retval==0) { + echo "Processing results\n"; + $zip = new ZipArchive; + if ($zip->open($dir . $ds . $run["inputname"]) === true) { + $zip->extractTo($dir, array_merge(array("compare" . $ds . $run["extension"]),$outputlist)); + $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 (12)"); + continue; + } + $script = $dir . $ds . 'compare' . $ds . $run["extension"]; + $retval = 0; + chmod($script, 0700); + foreach($outputlist as $file) { + $file = basename($file); + if(is_file($dir . $ds . 'output' . $ds . $file)) { + $ex = escapeshellcmd($script) ." ". + escapeshellarg($dir . $ds . "team" . $ds . $file)." ". + escapeshellarg($dir . $ds . "output" . $ds . $file)." ". + escapeshellarg($dir . $ds . "input" . $ds . $file) . " >compout"; + echo "Executing " . $ex . " at " . getcwd() . " for output file $file\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'; + } + } + } else { + echo "==> ERROR reading output file " . $dir . $ds . 'output' . $ds . $file . " - skipping it!\n"; + } + } + } +} +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"; + $answer = "(check output files - unusual code: $retval) " . $anstmp; + // contact staff + $retval = 7; +} + +echo "Sending results to server...\n"; +//echo "out==> "; system("tail -n1 ". $dir.$ds.'allout'); +//echo "err==> "; system("tail -n1 ". $dir.$ds.'allerr'); +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"; +} +?> diff --git a/src/private/conf.php b/src/private/conf.php new file mode 100644 index 0000000..9ad1a80 --- /dev/null +++ b/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/src/private/createdb.php b/src/private/createdb.php new file mode 100644 index 0000000..34eedb5 --- /dev/null +++ b/src/private/createdb.php @@ -0,0 +1,77 @@ +#!/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 06/aug/2012 by cassio@ime.usp.br +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +if(is_readable('/etc/boca.conf')) { + $pif=parse_ini_file('/etc/boca.conf'); + $bocadir = trim($pif['bocadir']) . $ds . 'src'; +} else { + $bocadir = getcwd(); +} + +if(is_readable($bocadir . $ds . '..' .$ds . 'db.php')) { + require_once($bocadir . $ds . '..' .$ds . 'db.php'); + @include_once($bocadir . $ds . '..' .$ds . 'version.php'); +} else { + if(is_readable($bocadir . $ds . 'db.php')) { + require_once($bocadir . $ds . 'db.php'); + @include_once($bocadir . $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/src/private/createproblemzip.php b/src/private/createproblemzip.php new file mode 100755 index 0000000..a78c30f --- /dev/null +++ b/src/private/createproblemzip.php @@ -0,0 +1,111 @@ +#!/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 06/aug/2012 by cassio@ime.usp.br +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +if(is_readable('/etc/boca.conf')) { + $pif=parse_ini_file('/etc/boca.conf'); + $bocadir = trim($pif['bocadir']) . $ds . 'src'; +} else { + if(is_readable('boca.conf')) { + $pif=parse_ini_file('boca.conf'); + $bocadir = trim($pif['bocadir']) . $ds . 'src'; + } + else + $bocadir = getcwd(); +} + +if(is_readable($bocadir . $ds . '..' .$ds . 'db.php')) { + require_once($bocadir . $ds . '..' .$ds . 'db.php'); + @include_once($bocadir . $ds . '..' .$ds . 'version.php'); +} else { + if(is_readable($bocadir . $ds . 'db.php')) { + require_once($bocadir . $ds . 'db.php'); + @include_once($bocadir . $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); + if($encdata=='') + $encdata=file_get_contents(trim($argv[2])); +} else { + $encdata=encryptData(file_get_contents(trim($argv[1])),'#####'.$password1,true); + if($encdata=='') + $encdata=file_get_contents(trim($argv[1])); +} + +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/src/private/index.html b/src/private/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/private/index.html diff --git a/src/private/insertlanguages.php b/src/private/insertlanguages.php new file mode 100644 index 0000000..c969841 --- /dev/null +++ b/src/private/insertlanguages.php @@ -0,0 +1,57 @@ +#!/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 06/aug/2012 by cassio@ime.usp.br +$ds = DIRECTORY_SEPARATOR; +if($ds=="") $ds = "/"; + +if(is_readable('/etc/boca.conf')) { + $pif=parse_ini_file('/etc/boca.conf'); + $bocadir = trim($pif['bocadir']) . $ds . 'src'; +} else { + $bocadir = getcwd(); +} + +if(is_readable($bocadir . $ds . '..' .$ds . 'db.php')) { + require_once($bocadir . $ds . '..' .$ds . 'db.php'); + require_once($bocadir . $ds . '..' .$ds . 'version.php'); +} else { + if(is_readable($bocadir . $ds . 'db.php')) { + require_once($bocadir . $ds . 'db.php'); + require_once($bocadir . $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/src/private/problemtmp/.htaccess b/src/private/problemtmp/.htaccess new file mode 100644 index 0000000..3a42882 --- /dev/null +++ b/src/private/problemtmp/.htaccess @@ -0,0 +1 @@ +Deny from all diff --git a/src/private/remotescores/otherservers b/src/private/remotescores/otherservers new file mode 100644 index 0000000..9db80da --- /dev/null +++ b/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/src/private/runtmp/index.html b/src/private/runtmp/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/private/runtmp/index.html diff --git a/src/private/score.sep b/src/private/score.sep new file mode 100644 index 0000000..fb45aae --- /dev/null +++ b/src/private/score.sep @@ -0,0 +1,23 @@ +General 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 100 9999 +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 +Site_9999 9999 diff --git a/src/private/scoretmp/index.html b/src/private/scoretmp/index.html new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/private/scoretmp/index.html diff --git a/src/reload.js b/src/reload.js new file mode 100644 index 0000000..a6eb426 --- /dev/null +++ b/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/src/score/header.php b/src/score/header.php new file mode 100644 index 0000000..69cf6e5 --- /dev/null +++ b/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/src/score/index.php b/src/score/index.php new file mode 100644 index 0000000..ef9675d --- /dev/null +++ b/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/src/score/score.php b/src/score/score.php new file mode 100644 index 0000000..ef9675d --- /dev/null +++ b/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/src/scorelower.php b/src/scorelower.php new file mode 100644 index 0000000..7ee78e8 --- /dev/null +++ b/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/src/scoretable.php b/src/scoretable.php new file mode 100644 index 0000000..ef11ee6 --- /dev/null +++ b/src/scoretable.php @@ -0,0 +1,387 @@ +<?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 02/nov/2012 by cassio@ime.usp.br +require_once("db.php"); + +if(isset($_SESSION["locr"])) + $locr=$_SESSION["locr"]; +else + $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"] = 2; +$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($_SESSION["usertable"]["usertype"]=='score' || $_SESSION["usertable"]["usertype"]=='admin' || (isset($_GET["remote"]) && is_numeric($_GET["remote"]))) { + $privatedir = $_SESSION['locr'] . $ds . "private"; + $remotedir = $_SESSION['locr'] . $ds . "private" . $ds . "remotescores"; + $destination = $remotedir . $ds ."scores.zip"; + if(is_writable($remotedir)) { + 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"], 0, -1); + } + $ct=DBGetActiveContest(); + $localsite=$ct['contestlocalsite']; + $fname = $privatedir . $ds . "score_localsite_" . $localsite . "_" . md5($_SERVER['HTTP_HOST']); + @file_put_contents($fname . ".tmp",base64_encode(serialize($data0))); + @rename($fname . ".tmp",$fname . ".dat"); + + $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 . "_" . $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'),$fname . ".tmp") != 1) { + LOGError("Cannot create score zip file"); + if(@create_zip($remotedir,array(),$fname . ".tmp") == 1) + @rename($fname . ".tmp",$destination); + } else { + @rename($fname . ".tmp",$destination); + } + } + } +} + +if(isset($_GET["remote"])) { + if(is_numeric($_GET["remote"])) { + if($_GET["remote"]==-42) { + 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++; + } + else if(strpos($grname[$k],'/') >= 1) { + $u1 = explode('/',$grname[$k]); + if(isset($u1[1]) && $score[$e]['user'] >= $u1[0] && $score[$e]['user'] <= $u1[1]) { + if(!isset($u1[2]) || $u1[2]==$score[$e]['site']) { + $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/src/sha256.js b/src/sha256.js new file mode 100644 index 0000000..1c6b7e7 --- /dev/null +++ b/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/src/site/get.php b/src/site/get.php new file mode 100644 index 0000000..81ede0d --- /dev/null +++ b/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/src/site/header.php b/src/site/header.php new file mode 100644 index 0000000..f1b47b3 --- /dev/null +++ b/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/src/site/index.php b/src/site/index.php new file mode 100644 index 0000000..3b066ab --- /dev/null +++ b/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/src/site/putfile.php b/src/site/putfile.php new file mode 100644 index 0000000..8a1d89a --- /dev/null +++ b/src/site/putfile.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 updated 03/nov/2012 by cassio@ime.usp.br +// +//PC^2 integration developed by Fabio Antonio Avellaneda Pachon +// +//Now it is also the integration of scores of BOCA +// +$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']; + + if($_SESSION["usertable"]["usericpcid"] != '' && $_SESSION["usertable"]["usericpcid"] > 0) + { + $arr = unserialize(base64_decode($total)); + $arr['site']=$_SESSION["usertable"]["usericpcid"]; + $total=base64_encode(serialize($arr)); + } + + $fn = tempnam($_SESSION["locr"] . $remotedir,"score_"); + $fout = fopen($fn,"wb"); + fwrite($fout,$total,10000000); + fclose($fout); + + // test the format of the file + $fc=file_get_contents($fn); + if(($arr = unserialize(base64_decode($fc)))===false || + !is_array($arr) || !isset($arr['site'])) { + echo "FAILED: File " . $fn . " is not compatible\n"; + } else { + + if(@rename($fn, $_SESSION["locr"] . $remotedir . $ds . "score_" . $_SESSION["usertable"]["username"] . + "_" . $_SESSION["usertable"]["usericpcid"] . "_" . 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/src/staff/header.php b/src/staff/header.php new file mode 100644 index 0000000..27119a6 --- /dev/null +++ b/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/src/staff/index.php b/src/staff/index.php new file mode 100644 index 0000000..ec74ce9 --- /dev/null +++ b/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/src/staff/option.php b/src/staff/option.php new file mode 100644 index 0000000..81e5879 --- /dev/null +++ b/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/src/staff/score.php b/src/staff/score.php new file mode 100644 index 0000000..ef9675d --- /dev/null +++ b/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/src/staff/task.php b/src/staff/task.php new file mode 100644 index 0000000..640eae1 --- /dev/null +++ b/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/src/system/contest.php b/src/system/contest.php new file mode 100644 index 0000000..2d4d788 --- /dev/null +++ b/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/src/system/header.php b/src/system/header.php new file mode 100644 index 0000000..75d0fca --- /dev/null +++ b/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/src/system/importxml.php b/src/system/importxml.php new file mode 100644 index 0000000..5fcaef3 --- /dev/null +++ b/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/src/system/index.php b/src/system/index.php new file mode 100644 index 0000000..ec74ce9 --- /dev/null +++ b/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/src/system/option.php b/src/system/option.php new file mode 100644 index 0000000..81e5879 --- /dev/null +++ b/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/src/team/clar.php b/src/team/clar.php new file mode 100644 index 0000000..a1e3972 --- /dev/null +++ b/src/team/clar.php @@ -0,0 +1,113 @@ +<?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"); +} +$_SESSION["popuptime"] = time(); +?> +<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 (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/src/team/files.php b/src/team/files.php new file mode 100644 index 0000000..42fba28 --- /dev/null +++ b/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/src/team/getfile.php b/src/team/getfile.php new file mode 100644 index 0000000..8c594d0 --- /dev/null +++ b/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/src/team/header.php b/src/team/header.php new file mode 100644 index 0000000..ec7352a --- /dev/null +++ b/src/team/header.php @@ -0,0 +1,143 @@ +<?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"; + } +} + +if(!isset($_SESSION["popuptime"]) || $_SESSION["popuptime"] < time()-120) { + $_SESSION["popuptime"] = time(); + + if(($st = DBSiteInfo($_SESSION["usertable"]["contestnumber"],$_SESSION["usertable"]["usersitenumber"])) != null) { + $clar = DBUserClars($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"]); + for ($i=0; $i<count($clar); $i++) { + if ($clar[$i]["anstime"]>$_SESSION["usertable"]["userlastlogin"]-$st["sitestartdate"] && + $clar[$i]["anstime"] < $st['siteduration'] && + trim($clar[$i]["answer"])!='' && !isset($_SESSION["popups"]['clar' . $i . '-' . $clar[$i]["anstime"]])) { + $_SESSION["popups"]['clar' . $i . '-' . $clar[$i]["anstime"]] = "(Clar for problem ".$clar[$i]["problem"]." answered)\n"; + } + } + $run = DBUserRuns($_SESSION["usertable"]["contestnumber"], + $_SESSION["usertable"]["usersitenumber"], + $_SESSION["usertable"]["usernumber"]); + for ($i=0; $i<count($run); $i++) { + 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"] . ')\n'; + } + } + } + + $str = ''; + if(isset($_SESSION["popups"])) { + foreach($_SESSION["popups"] as $key => $value) { + if($value != '') { + $str .= $value; + $_SESSION["popups"][$key] = ''; + } + } + if($str != '') { + MSGError('YOU GOT NEWS:\n' . $str . '\n'); + } + } +} + +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/src/team/index.php b/src/team/index.php new file mode 100644 index 0000000..ec74ce9 --- /dev/null +++ b/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/src/team/option.php b/src/team/option.php new file mode 100644 index 0000000..81e5879 --- /dev/null +++ b/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/src/team/problem.php b/src/team/problem.php new file mode 100644 index 0000000..2627990 --- /dev/null +++ b/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 && isset($prob[$i]["descfilename"])) { + 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/src/team/run.php b/src/team/run.php new file mode 100644 index 0000000..270a672 --- /dev/null +++ b/src/team/run.php @@ -0,0 +1,196 @@ +<?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(strpos($name,' ') === true || strpos($temp,' ') === true) { + MSGError("File name cannot contain spaces."); + 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["popuptime"] = time(); + $_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"; + } +$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'); +$strtmp .= "<option value=\"-1\"></option>\n"; +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"]); +$strtmp .= "<option value=\"-1\"></option>\n"; +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 (document.form1.problem.value != '-1' && document.form1.language.value != '-1') {\n". +" if (confirm(\"Confirm submission?\")) {\n". +" document.form1.confirmation.value='confirm';\n". +" }\n". +" } else {\n". +" alert('Invalid problem and/or language');\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/src/team/score.php b/src/team/score.php new file mode 100644 index 0000000..ef9675d --- /dev/null +++ b/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/src/team/task.php b/src/team/task.php new file mode 100644 index 0000000..b23605c --- /dev/null +++ b/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/src/test.php b/src/test.php new file mode 100644 index 0000000..694120a --- /dev/null +++ b/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/src/version b/src/version new file mode 100644 index 0000000..56c3c4d --- /dev/null +++ b/src/version @@ -0,0 +1 @@ +boca-1.5.2 diff --git a/src/version.php b/src/version.php new file mode 100644 index 0000000..8a8cfef --- /dev/null +++ b/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/src/versionnum.php b/src/versionnum.php new file mode 100644 index 0000000..1da16cb --- /dev/null +++ b/src/versionnum.php @@ -0,0 +1,5 @@ +<?php +$BOCAVERSION='boca-1.5.2'; +$YEAR='2012'; +?> + |