diff options
Diffstat (limited to 'toj/php')
-rw-r--r-- | toj/php/_json.php | 3 | ||||
-rw-r--r-- | toj/php/_test.php | 20 | ||||
-rw-r--r-- | toj/php/common.inc.php | 7 | ||||
-rw-r--r-- | toj/php/connect.inc.php | 40 | ||||
-rw-r--r-- | toj/php/event.inc.php | 71 | ||||
-rw-r--r-- | toj/php/event.php | 24 | ||||
-rw-r--r-- | toj/php/event_exec.cpp | 89 | ||||
-rw-r--r-- | toj/php/event_exec.h | 12 | ||||
-rw-r--r-- | toj/php/notice.inc.php | 244 | ||||
-rw-r--r-- | toj/php/notice.php | 110 | ||||
-rw-r--r-- | toj/php/problem.inc.php | 252 | ||||
-rw-r--r-- | toj/php/problem.php | 140 | ||||
-rw-r--r-- | toj/php/pzreadtest.php | 9 | ||||
-rw-r--r-- | toj/php/sqlib.inc.php | 5 | ||||
-rw-r--r-- | toj/php/sqlib_scoreboard.inc.php | 239 | ||||
-rw-r--r-- | toj/php/square.inc.php | 229 | ||||
-rw-r--r-- | toj/php/square.php | 350 | ||||
-rw-r--r-- | toj/php/status.inc.php | 133 | ||||
-rw-r--r-- | toj/php/status.php | 70 | ||||
-rw-r--r-- | toj/php/step.inc.php | 17 | ||||
-rw-r--r-- | toj/php/step.php | 64 | ||||
-rw-r--r-- | toj/php/teamt.php | 28 | ||||
-rw-r--r-- | toj/php/test.php | 32 | ||||
-rw-r--r-- | toj/php/user.inc.php | 212 | ||||
-rw-r--r-- | toj/php/user.php | 160 |
25 files changed, 2560 insertions, 0 deletions
diff --git a/toj/php/_json.php b/toj/php/_json.php new file mode 100644 index 0000000..b3c443e --- /dev/null +++ b/toj/php/_json.php @@ -0,0 +1,3 @@ +<?php +echo json_encode("#include <stdio.h>\nint main(){while(scanf(\"%d%d\", &a, &b)==2)printf(\"%d\n\", a+b); return 0;}\n"); +?> diff --git a/toj/php/_test.php b/toj/php/_test.php new file mode 100644 index 0000000..5ce8271 --- /dev/null +++ b/toj/php/_test.php @@ -0,0 +1,20 @@ +<form action="notice.php" method=post> + <input type='hidden' value='{"uid":111}' name='data'> + <input type='hidden' value='count' name='action'> + <input type='submit' value='ti jiao count'> +</form> +<form action="notice.php" method=post> + <input type='text' value='{"uid":111}' name='data'> + <input type='hidden' value='get' name='action'> + <input type='submit' value='ti jiao get'> +</form> +<form action="notice.php" method=post> + <input type='hidden' value='{"uid":111}' name='data'> + <input type='hidden' value='clear' name='action'> + <input type='submit' value='ti jiao clear'> +</form> +<form action="notice.php" method=post> + <input type='text' value='{"uid":111,"type":1,"value":111,"context":"aaaaaa"}' name='data'> + <input type='hidden' value='add' name='action'> + <input type='submit' value='ti jiao add'> +</form> diff --git a/toj/php/common.inc.php b/toj/php/common.inc.php new file mode 100644 index 0000000..d31a596 --- /dev/null +++ b/toj/php/common.inc.php @@ -0,0 +1,7 @@ +<?php + +date_default_timezone_set('Asia/Taipei'); + +require('connect.inc.php'); + +?> diff --git a/toj/php/connect.inc.php b/toj/php/connect.inc.php new file mode 100644 index 0000000..3eebe89 --- /dev/null +++ b/toj/php/connect.inc.php @@ -0,0 +1,40 @@ +<?php + +define('DB_NAME','xxxxx'); +define('DB_USER','xxxxx'); +define('DB_PASSWORD','xxxxx'); +define('SEC_SALT','xxxxx'); + +define('SMTP_HOST','xxxxx'); +define('SMTP_USER','xxxxx'); +define('SMTP_PASS','xxxxx'); + +const CENTER_SOCKET_PORT = 2501; + +function sec_is_login() +{ + if(!isset($_COOKIE['uid']) || !isset($_COOKIE['usec'])){ + return false; + } + + $userid = $_COOKIE['uid']; + $usersec = $_COOKIE['usec']; + + if($userid == '' || $usersec == '' || strval(intval($userid)) != $userid || hash('sha512',$userid.SEC_SALT) != $usersec){ + return false; + } + + return true; +} + +function db_connect($dbn = DB_NAME) +{ + return pg_connect('host=localhost port=5432 dbname='.$dbn.' user='.DB_USER.' password='.DB_PASSWORD); +} + +function db_close($sqlcx) +{ + pg_close($sqlcx); +} + +?> diff --git a/toj/php/event.inc.php b/toj/php/event.inc.php new file mode 100644 index 0000000..9d2a23c --- /dev/null +++ b/toj/php/event.inc.php @@ -0,0 +1,71 @@ +<?php +class event +{ + private static $white_list; + + private static function init() + { + event::$white_list = array('10.8.0.2'); + } + + // execute function $name in file $fname + // if want to call a function of a class, have 2 choice: + // 1. pass an array as $name, put every level of class in it, like: + // A::B::C() should be passed like array("A", "B", "C"). + // 2. pass a string with :: directly, it will be automatically + // translated. + // return value will be FALSE on failure, return value of target + // function otherwise. NULL when no return value. + public static function exec_func($fname, $name, $arg) + { + if(!file_exists($fname)) + { + return false; + } + require_once($fname); + if(is_string($name) && strpos($name, ":") !== FALSE) + { + $name = preg_split("/::/", $name); + } + if(is_string($name) && !is_callable($name)) + { + return false; + } + if(is_array($name) && !is_callable(join($name, "::"))) + { + return false; + } + if($arg == NULL) + { + $res = call_user_func($name); + } + else + { + $res = call_user_func_array($name, $arg); + } + if($res === false) + { + return false; + } + return $res; + } + + public static function validate_ip() + { + event::init(); + if (!empty($_SERVER['HTTP_CLIENT_IP'])) + { + $ip=$_SERVER['HTTP_CLIENT_IP']; + } + else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) + { + $ip=$_SERVER['HTTP_X_FORWARDED_FOR']; + } + else + { + $ip=$_SERVER['REMOTE_ADDR']; + } + return in_array($ip, event::$white_list); + } +} +?> diff --git a/toj/php/event.php b/toj/php/event.php new file mode 100644 index 0000000..e121287 --- /dev/null +++ b/toj/php/event.php @@ -0,0 +1,24 @@ +<?php + require_once('event.inc.php'); + if (!empty($_SERVER['HTTP_CLIENT_IP'])) + $ip=$_SERVER['HTTP_CLIENT_IP']; + else if (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) + $ip=$_SERVER['HTTP_X_FORWARDED_FOR']; + else + $ip=$_SERVER['REMOTE_ADDR']; + if(!event::validate_ip()) + { + exit; + } + $fname = $_POST['fname']; + $name = $_POST['name']; + $arg = json_decode($_POST['arg']); + if(event::exec_func($fname, $name, $arg) === false) + { + echo "false"; + } + else + { + echo "true"; + } +?> diff --git a/toj/php/event_exec.cpp b/toj/php/event_exec.cpp new file mode 100644 index 0000000..25d7944 --- /dev/null +++ b/toj/php/event_exec.cpp @@ -0,0 +1,89 @@ +#include "event_exec.h" + +#define EVENT_BUFLEN 1005 +#define EVENT_URL "http://10.8.0.2/toj/php/event.php" + +struct event_handle +{ + int init, plen, blen; + char *post, *buf; + pthread_mutex_t mutex; + CURL *handle; +}; + +static struct event_handle conn; + +size_t event_write_cb(void *in, size_t siz, size_t nb, void *buf) +{ + int len; + len = siz*nb+1; + if(len > conn.blen) + { + len = conn.blen-1; + } + memcpy(buf, in, len); + ((char*)buf)[len] = 0; + return siz*nb; +} + +int event_init() +{ + if(conn.init) + { + return 0; + } + conn.plen = conn.blen = EVENT_BUFLEN; + conn.post = (char*)malloc(EVENT_BUFLEN); + conn.buf = (char*)malloc(EVENT_BUFLEN); + curl_global_init(CURL_GLOBAL_ALL); + conn.handle = curl_easy_init(); + curl_easy_setopt(conn.handle, CURLOPT_URL, EVENT_URL); + curl_easy_setopt(conn.handle, CURLOPT_WRITEFUNCTION, event_write_cb); + curl_easy_setopt(conn.handle, CURLOPT_WRITEDATA, conn.buf); + pthread_mutex_init(&conn.mutex, NULL); + conn.init = 1; + return 1; +} + +int event_exec(const char *fname, const char *name, const char *arg) +{ + int res, len; + char *t; + event_init(); + if(pthread_mutex_lock(&conn.mutex) == 0) + { + len = 0; + len += strlen(fname)+6; + len += strlen(name)+6; + len += strlen(arg)+6; + if(len > conn.plen) + { + t = (char*)malloc(len); + if(!t) + { + pthread_mutex_unlock(&conn.mutex); + return 0; + } + free(conn.post); + conn.post = t; + conn.plen = len; + } + sprintf(conn.post, "fname=%s&name=%s&arg=%s", fname, name, arg); + curl_easy_setopt(conn.handle, CURLOPT_POSTFIELDS, conn.post); + res = curl_easy_perform(conn.handle); + if(res) + { + pthread_mutex_unlock(&conn.mutex); + return 0; + } + fprintf(stderr, "%s\n", conn.buf); + if(!strcmp(conn.buf, "true")) + { + pthread_mutex_unlock(&conn.mutex); + return 1; + } + + pthread_mutex_unlock(&conn.mutex); + } + return 0; +} diff --git a/toj/php/event_exec.h b/toj/php/event_exec.h new file mode 100644 index 0000000..aec1acb --- /dev/null +++ b/toj/php/event_exec.h @@ -0,0 +1,12 @@ +#ifndef EVENT_EXEC +#define EVENT_EXEC + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <curl/curl.h> +#include <pthread.h> + +int event_exec(const char *fname, const char *name, const char *arg); + +#endif diff --git a/toj/php/notice.inc.php b/toj/php/notice.inc.php new file mode 100644 index 0000000..dbf47cc --- /dev/null +++ b/toj/php/notice.inc.php @@ -0,0 +1,244 @@ +<?php +require_once('common.inc.php'); +require_once('user.inc.php'); + +const NOTICE_DEF_LIM = 5; +const NOTICE_MAX_LIM = 30; + +const NOTICE_ACT_CNT = 1; +const NOTICE_ACT_NEW = 2; +const NOTICE_ACT_OLD = 4; + +const NOTICE_TYP_USR = 1; +const NOTICE_TYP_PRO = 2; +const NOTICE_TYP_SQR = 3; +const NOTICE_TYP_ALL = 255; + +class notice +{ + private static function ins_uid($sqlc, $uid) + { + $sqlstr = 'INSERT INTO "notice_cache" ("uid", "tim", "cnt", "tmp", "rsv") VALUES ($1, $2, $3, $4, $5) RETURNING *;'; + $sqlarr = array($uid, date("Y-m-d H:i:s"), 0, "0", "0"); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_object($sqlr); + pg_free_result($sqlr); + return $ret; + } + + public static function is_match($sqlc, $uid, &$not) + { + if($not->typ == NOTICE_TYP_ALL) + { + return true; + } + if($not->typ == NOTICE_TYP_USR) + { + return $uid == intval($not->val); + } + require_once('event.inc.php'); + if($not->typ == NOTICE_TYP_PRO) + { + if(!event::exec_func('problem.inc.php', 'problem::is_available', array($sqlc, $not->val, $uid))) + { + return false; + } + return true; + } + else if($not->typ == NOTICE_TYP_SQR) + { + $ret = event::exec_func('square.inc.php', 'square::get_user_relationship', array($sqlc, $uid, $not->val)); + if($ret >= SQUARE_USER_ACTIVE) + { + return true; + } + return false; + } + return false; + } + + private static function update($sqlc, $uid, &$tar, &$arr) + { + if(count($arr) <= 0) + { + return false; + } + $sqlstr = 'UPDATE "notice_cache" SET "tmp"=$1, "cnt"=$2, "tim"=$4 WHERE "uid"=$3 RETURNING *;'; + $sqlarr = array($arr[0], intval($tar->cnt)+count($arr), $uid, date('Y-m-d H:i:s')); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_object($sqlr); + pg_free_result($sqlr); + foreach($arr as $it) + { + $sqlstr = 'INSERT INTO "user_notice" ("uid", "nid") VALUES ($1, $2);'; + $sqlarr = array(intval($uid), intval($it)); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + pg_free_result($sqlr); + } + return $ret; + } + + private static function check_new($sqlc, $uid) + { + $sqlstr = 'SELECT * FROM "notice_cache" WHERE "uid"=$1;'; + $sqlarr = array($uid); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_object($sqlr); + if($ret === false) + { + $ret = notice::ins_uid($sqlc, $uid); + } + pg_free_result($sqlr); + $sqlstr = 'SELECT * FROM "notice" WHERE "nid" > $1 ORDER BY "tim";'; + $sqlarr = array(intval($ret->tmp)); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $buf = array(); + while($row = pg_fetch_object($sqlr)) + { + if(self::is_match($sqlc, $uid, $row)) + { + array_unshift($buf, $row->nid); + } + } + pg_free_result($sqlr); + if(count($buf) > 0) + { + return self::update($sqlc, $uid, $ret, $buf); + } + return $ret; + } + + // **warning**: this function will clear notice count of uid!! + public static function get($sqlc, $uid, $typ, $arg1, $arg2) + { + $uid = intval($uid); + if(!$uid || !$sqlc) + { + return false; + } + $ret = self::check_new($sqlc, $uid); + if($typ == NOTICE_ACT_CNT) + { + return intval($ret->cnt); + } + else if($typ == NOTICE_ACT_NEW) + { + if($ret->cnt == 0) + { + return array(); + } + $sqlstr = 'SELECT "nid" FROM "user_notice" WHERE "uid"=$1 AND "nid">$2 ORDER BY "nid" DESC'; + $sqlarr = array($uid, intval($ret->rsv)); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $nids = array(); + while($it=pg_fetch_array($sqlr)) + { + $nids[] = $it[0]; + } + $sqlstr = 'SELECT * FROM "notice" WHERE "nid" IN ('.join($nids, ",").') ORDER BY "tim";'; + $sqlr = pg_query($sqlc, $sqlstr); + $buf = array(); + while($it = pg_fetch_object($sqlr)) + { + $it->nid = intval($it->nid); + $it->typ = intval($it->typ); + $buf[] = $it; + } + pg_free_result($sqlr); + $sqlstr = 'UPDATE "notice_cache" SET "cnt"=0, "rsv"=$2 WHERE "uid"=$1;'; + $sqlarr = array($uid, $nids[0]); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + return $buf; + } + else if($typ == NOTICE_ACT_OLD) + { + if($arg2 <= 0) + { + $arg2 = 1; + } + if($arg2 > NOTICE_MAX_LIM) + { + $arg2 = NOTICE_MAX_LIM; + } + $sqlstr = 'SELECT "nid" FROM "user_notice" WHERE "uid"=$1 AND "nid"<$2 ORDER BY "nid" DESC LIMIT $3'; + $sqlarr = array($uid, $arg1, $arg2); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $nids = array(); + while($it=pg_fetch_array($sqlr)) + { + $nids[] = $it[0]; + } + $sqlstr = 'SELECT * FROM "notice" WHERE "nid" IN ('.join($nids, ",").') ORDER BY "tim";'; + $sqlr = pg_query($sqlc, $sqlstr); + $buf = array(); + while($it = pg_fetch_object($sqlr)) + { + $it->nid = intval($it->nid); + $it->typ = intval($it->typ); + $buf[] = $it; + } + pg_free_result($sqlr); + return $buf; + } + return false; + } + + public static function clr($sqlc, $uid, $lim=NOTICE_DEF_LIM) + { + return false; + if($lim < 0) + { + $lim = 0; + } + $ret = self::check_new($sqlc, $uid); + $buf = preg_split("/[,]/", $ret->tmp); + $buf = array_slice($buf, 0, $ret->cnt+$lim); + $sqlstr = 'UPDATE "notice_cache" SET "tmp"=$1 WHERE "uid"=$2;'; + $sqlarr = array(join($buf, ","), $uid); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + if($sqlr) + { + return count($buf); + } + return false; + } + + // you can add notice by calling it. + public static function add($sqlc, $typ, $val, $txt) + { + if(!is_string($val)) + { + $val = json_encode($val); + } + $sqlstr = 'INSERT INTO "notice" ("typ", "val", "txt", "tim") VALUES ($1, $2, $3, $4) RETURNING *;'; + $sqlarr = array($typ, $val, $txt, date('Y-m-d H:i:s')); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_object($sqlr); + if($ret === false) + { + return false; + } + return json_encode($ret); + } + + public static function del($sqlc, $cond) + { + $sqlstr = 'DELETE FROM "notice" WHERE 0'; + if(isset($cond['nid'])) + { + $sqlstr .= ' OR "nid"=$1'; + } + if(isset($cond['tim'])) + { + $sqlstr .= ' OR "tim" >= $2'; + } + $sqlarr = array($cond['nid'], $cond['tim']); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + if(!$sqlr) + { + return false; + } + return true; + } +} +?> diff --git a/toj/php/notice.php b/toj/php/notice.php new file mode 100644 index 0000000..a0f984a --- /dev/null +++ b/toj/php/notice.php @@ -0,0 +1,110 @@ +<?php +//ini_set("display_errors", "On"); +//error_reporting(E_ALL & ~E_NOTICE); + +require_once('notice.inc.php'); + +/* usage: + * action count(uid): update notice count of uid, return value: integer + * action get(uid): update notice of uid, return notice data limited to notice count, + * and clear notice count. format: object array, see table "notice" + * action clear(uid, [limit]): clear cache number to notice_count+limit, + * does not affect notice, only user cache. return remain number as int. + * action add(type, value, context): add a notice, need admin permission now. + * **attention**: this is only for web, use notice::add with your own code, + * that function does not require any user permission. + * type is an integer, see "notice.inc.php" NOTICE_TYP_*. + * value are paired with type, like proid, sqid, uid, .., meaning nothing + * with NOTICE_TYP_ALL, but cannot be NULL. + * context is what you want. treat as string data so its format + * depends on your own. + * return 'S' when success. + */ + +$sqlc = db_connect(); +$action = $_POST['action']; +$data = json_decode($_POST['data']); + +if(strlen($action) == 0) +{ + die('Eno_action'); +} +if(!sec_is_login()) +{ + die('Eno_login'); +} +$uid = intval($_COOKIE['uid']); +$usr = user::get_from_uid($sqlc, $uid); +if(!$usr) +{ + die('Eno_such_user'); +} + +if($action == 'count') +{ + $cnt = notice::get($sqlc, $uid, NOTICE_ACT_CNT); + echo $cnt; +} +else if($action == 'get') +{ + $nid = intval($data->nid); + if($nid > 0) + { + $cnt = intval($data->count); + $res = notice::get($sqlc, $uid, NOTICE_ACT_OLD, $nid, $cnt); + if($res === false) + { + die('Eno_such_nid'); + } + echo json_encode($res); + } + else + { + $res = notice::get($sqlc, $uid, NOTICE_ACT_NEW); + echo json_encode($res); + } +} +else if($action == 'clear') +{ + $lim = NOTICE_DEF_LIM; + if(isset($data->limit)) + { + $lim = intval($data->limit); + } + if($lim > NOTICE_MAX_LIM) + { + $lim = NOTICE_MAX_LIM; + } + $ret = notice::clr($sqlc, $uid, $lim); + echo $ret; +} +else if($action == 'add') +{ + if(!sec_check_level($sqlc, USER_LEVEL_SUPERADMIN) && $uid != 111) + //if(!sec_check_level($sqlc, USER_LEVEL_SUPERADMIN)) + { + die('Epermission_denied'); + } + if(!isset($data->type)) + { + die('Etype_is_empty'); + } + if(!isset($data->value)) + { + die('Evalue_is_empty'); + } + if(!isset($data->context)) + { + die('Econtext_is_empty'); + } + $res = notice::add($sqlc, $data->type, $data->value, $data->context); + if(!$res) + { + die('Efail'); + } + echo 'S'; +} + +db_close($sqlc); + +?> diff --git a/toj/php/problem.inc.php b/toj/php/problem.inc.php new file mode 100644 index 0000000..e41e633 --- /dev/null +++ b/toj/php/problem.inc.php @@ -0,0 +1,252 @@ +<?php +require_once('common.inc.php'); +require_once('user.inc.php'); +require_once('square.inc.php'); + +const PRONAME_LEN_MAX = 100; + +const CODE_LEN_MIN = 1; +const CODE_LEN_MAX = 102400; + +const SUBMIT_MIN_INTERVAL = 10; + +$LANGUAGE = array(0x1=>'C/C++', 0x2=>'JAVA', 0x4=>'Pascal'); +$EXTENSION = array(0x1=>'cpp', 0x2=>'java', 0x4=>'pas'); + +class problem +{ + public $proid; + public $modid; + public $proname; + public $hidden; + + public static function getmod($sqlc, $modid) + { + //return pmodname, smodname, jmodname for specified $modid. + //False if not found. + $result = pg_query_params($sqlc, 'SELECT * FROM "mod" WHERE "modid"=$1 LIMIT 1;', array($modid)); + $mret = pg_fetch_object($result); + pg_free_result($result); + if(!$mret) + return false; + return $mret; + } + public static function get($sqlc, $proid) + { + //return problem data: proid, modid, proname, pmodname, smodname, jmodname + //False if not found. + $result = pg_query_params($sqlc, 'SELECT * FROM "problem" WHERE "proid"=$1 LIMIT 1;', array(intval($proid))) or die ("Eerror_get_problem"); + $ret = pg_fetch_object($result, null, 'problem'); + pg_free_result($result); + if(!$ret) + return false; + + $ret->proid = intval($ret->proid); + $ret->modid = intval($ret->modid); + $ret->admin_uid = intval($ret->admin_uid); + + $mret = problem::getmod($sqlc, $ret->modid); + if(!$mret) + return false; + + $ret->pmodname = $mret->pmodname; + $ret->smodname = $mret->smodname; + $ret->jmodname = $mret->jmodname; + + return $ret; + } + + public static function is_available($sqlc, $proid, $uid = null) + { + //return whether the problem is available for user $_COOKIE['uid'] or not. + //USER_PER_PROADMIN always OK + //admin of problem always OK + //if HIDDEN , then NOT OK except admins + //in sqid=1 always OK , even if not login + //otherwise must exist at least one common square with relationship >= SQUARE_USER_ACTIVE + $uidnull = false; + if($uid == null) + { + $uid = intval($_COOKIE['uid']); + $uidnull = true; + } + $sqlr = pg_query_params('SELECT "hidden", "admin_uid" FROM "problem" WHERE "proid"=$1;', array($proid)); + $obj = pg_fetch_object($sqlr); + $hdn = $obj->hidden; + if($hdn == null) + return false; // no such problem + + if(sec_check_level($sqlc, USER_PER_PROADMIN, $uidnull?null:$uid)) + return true; + + if((!$uidnull || sec_is_login()) && $uid == intval($obj->admin_uid)) + return true; + + if($hdn == "t") + return false; + + $sqlstr = 'SELECT COUNT(*) FROM "pro_sq" WHERE "proid"=$1 AND "sqid"=$2;'; + $sqlarr = array($proid, 1); + $sqlr = pg_query_params($sqlstr, $sqlarr); + $ret = intval(pg_fetch_result($sqlr, 0)); + if($ret > 0) + return true; + + if($uidnull && !sec_is_login()) + return false; + + $sqlstr = 'SELECT COUNT("pro_sq"."sqid") FROM "pro_sq" INNER JOIN "us_sq" ON "pro_sq"."sqid"="us_sq"."sqid" WHERE "pro_sq"."proid"=$1 AND "us_sq"."uid"=$2 AND "us_sq"."relationship">=$3;'; + $sqlarr = array($proid, $uid, SQUARE_USER_ACTIVE); + $sqlr = pg_query_params($sqlstr, $sqlarr); + $ret = intval(pg_fetch_result($sqlr, 0)); + if($ret > 0) + return true; + + return false; + } + + public static function submit($sqlc, $proid, $uid, $lang, $code) + { + //Submit code(or data) : $proid, $uid, $lang, $code + //Return subid. False if failed. + + ////$submit_time = date('Y-m-d H:i:s'); + ////$last_update = $submit_time; + $sqlstr = 'INSERT INTO "submit" ("proid", "uid", "lang") VALUES ($1, $2, $3) RETURNING subid;'; + $sqlarr = array($proid, $uid, $lang); + $sqlr = pg_query_params($sqlstr, $sqlarr); + $subid = intval(pg_fetch_result($sqlr, 0)); + if(!$subid) + return false; + + global $EXTENSION; + $ext = $EXTENSION[intval($lang)]; + if($ext == null) + die('Ewrong_extension'); + + $parnum = $subid - ($subid%1000); + $pardir = '../center/submit/'.$parnum.'/'; + if(!is_dir($pardir)) + mkdir($pardir, 0755) or die('Ecannot_mkdir'); + mkdir($pardir.$subid, 0755) or die('Ecannot_mkdir'); + mkdir($pardir.$subid.'/data', 0755) or die('Ecannot_mkdir'); + mkdir($pardir.$subid.'/result', 0755) or die('Ecannot_mkdir'); + + //$file = fopen($pardir.$subid.'/data/'.$subid.'.'.$ext,'w'); + //20130205 tmp change + $file = fopen($pardir.$subid.'/data/main.'.$ext,'w'); + if(!$file) + die('Ewrite_file_failed'); + fwrite($file, $code); + fclose($file); + + return $subid; + } + + public static function add($sqlc, $pro) + { + //Add a new problem $pro into problem table. + //Return the inserted object. False if failed. + + $sqlstr = 'INSERT INTO "problem" ("modid", "proname", "hidden", "admin_uid") VALUES ($1, $2, $3, $4) RETURNING *;'; + $sqlarr = array($pro->modid, $pro->proname, $pro->hidden, $pro->admin_uid); + $sqlr = pg_query_params($sqlstr, $sqlarr); + if(!$sqlr) + return false; + $obj = pg_fetch_object($sqlr, null, 'problem'); + pg_free_result($sqlr); + if(!$obj) + return false; + + $obj->proid = intval($obj->proid); + $obj->modid = intval($obj->modid); + $obj->admin_uid = intval($obj->admin_uid); + + return $obj; + } + + public static function mod_get_lang($sqlc, $modid) + { + //get available language code (OR) format + //return language code + + $sqlstr = 'SELECT "lang" FROM "mod" WHERE "modid"=$1;'; + $sqlarr = array($modid); + $sqlr = pg_query_params($sqlstr, $sqlarr); + $ret = pg_fetch_result($sqlr, 0); + pg_free_result($sqlr); + if(!$ret) + return false; + return intval($ret); + } + + public static function recent_submit($sqlc, $uid, $time) + { + //return submission number in recent $time seconds. + $lasttime = date('Y-m-d H:i:s', time()-$time); + $sqlstr = 'SELECT COUNT(*) FROM "submit" WHERE "uid"=$1 AND "submit_time" >= $2;'; + $sqlarr = array($uid, $lasttime); + $sqlr = pg_query_params($sqlstr, $sqlarr); + $ret = pg_fetch_result($sqlr, 0); + if(!$ret) + return false; + return intval($ret); + } + + public static function send_socket($subid, $proid) + { + ///send socket to center. + //Return true if success, false if failed. + + $socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); + $sconn = socket_connect($socket, '127.0.0.1', CENTER_SOCKET_PORT); + + if(!$sconn) + return false; + + $wret = socket_write($socket, $subid.chr(0).'{}'.chr(0)); + if($wret === false) + return false; + + + $cret = socket_read($socket, 1024); + if($cret === false) + return false; + if($cret[0] != 'S') + return false; + return true; + } + + public static function get_pro_stat($sqlc, $proid, $uid) + { + //get $uid 's score and is_ac of problem $proid. + + $ret = new stdClass(); + + $sqlstr = 'SELECT COUNT(*) FROM "submit" WHERE "proid"=$1 AND "uid"=$2 AND "result"=0;'; + $sqlarr = array($proid, $uid); + $res = pg_query_params($sqlc, $sqlstr, $sqlarr); + $acct = pg_fetch_result($res, 0); + $ret->is_ac = ($acct > 0); + + $sqlstr = 'SELECT "score" FROM "submit" WHERE "proid"=$1 AND "uid"=$2 ORDER BY "score" DESC LIMIT 1;'; + $sqlarr = array($proid, $uid); + $res = pg_query_params($sqlc, $sqlstr, $sqlarr); + $score = pg_fetch_result($res, 0); + if($score === false) + { + $ret->tried = false; + $ret->score = 0; + } + else + { + $ret->tried = true; + $ret->score = $score; + } + + return $ret; + } +} + + +?> diff --git a/toj/php/problem.php b/toj/php/problem.php new file mode 100644 index 0000000..be79ecb --- /dev/null +++ b/toj/php/problem.php @@ -0,0 +1,140 @@ +<?php +ini_set("display_errors", "On"); +error_reporting(E_ALL & ~E_NOTICE); + +require_once('problem.inc.php'); +require_once('user.inc.php'); + +$sqlc = db_connect(); + +$action = $_POST['action']; +$data = $_POST['data']; + +if(strlen($action)==0) + die('Eno_action'); +if($action == 'get_pro') +{ + //get problem data: proid, modid, name, pmodname, smodname, jmodname + //only USER_LEVEL_SUPERADMIN or is_available + //data : proid + + $dt = json_decode($data); + + $proid = intval($dt->proid); + + $ret = problem::get($sqlc, $proid); + if(!$ret) + die('Eget_problem'); + + if(!problem::is_available($sqlc, $proid)) + die('Epermission_denied'); + + unset($ret->proid); + //unset($ret->hidden); + + echo(json_encode($ret)); +} +if($action == 'add_pro') +{ + //Add problem + //need SUPERADMIN + //data: modid, proname, [hidden] + if(!sec_is_login()) + die('Enot_login'); + if(!sec_check_level($sqlc, USER_PER_PROCREATOR)) + die('Epermission_denied'); + + $dt = json_decode($data); + + if(strlen($dt->proname) == 0) + die('Eproname_too_short'); + if(strlen($dt->proname) > PRONAME_LEN_MAX) + die('Eproname_too_long'); + + if(!problem::getmod($sqlc, $dt->modid)) + die('Ewrong_modid'); + + if($dt->hidden != 't' && $dt->hidden != 'f') + die('Ewrong_hidden_value'); + + /*CHECK OTHER DATA, TESTDATA ETC*/ + + $dt->admin_uid = intval($_COOKIE['uid']); + + $pro = problem::add($sqlc, $dt); + if(!$pro) + die('Eadd_problem'); + + echo(json_encode($pro)); +} +if($action == 'submit_code') +{ + //Submit code + //Need problem available + //data: proid, lang, code + if(!sec_is_login()) + die('Enot_login'); + + $uid = intval($_COOKIE['uid']); + $dt = json_decode($data); + + $proid = intval($dt->proid); + + if(!problem::is_available($sqlc, $proid)){ + die('Epermission_denied'); + } + + $obj = problem::get($sqlc, $proid); + $lang = intval($dt->lang); + $oklang = problem::mod_get_lang($sqlc, $obj->modid); + if($LANGUAGE[$lang] == null || (($lang & $oklang) == 0)) + die('Ewrong_language'); + + if(strlen($dt->code) < CODE_LEN_MIN) + die('Ecode_too_short'); + if(strlen($dt->code) > CODE_LEN_MAX) + die('Ecode_too_long'); + + //if(problem::recent_submit($sqlc, $uid, SUBMIT_MIN_INTERVAL) > 0) + // die('Esubmit_too_frequently'); + + $subid = problem::submit($sqlc, $proid, $uid, $lang, $dt->code); + if(!$subid) + die('Esubmit_code_failed'); + + /*ASSOCIATED SQUARE : CALL SQUARE MODULE TO GET EXTRA JUDGE OPTION*/ + + if(!problem::send_socket($subid, $proid)) + die('Esend_socket_failed'); + + echo(json_encode($subid)); +} +if($action == 'get_pro_stat') +{ + //Get score and is_ac for specified proid. + //Need login and problem available. + //data : proid + + if(!sec_is_login()) + die('Enot_login'); + + $uid = intval($_COOKIE['uid']); + $dt = json_decode($data); + + $proid = intval($dt->proid); + + if(!problem::is_available($sqlc, $proid)){ + die('Epermission_denied'); + } + + $ret = problem::get_pro_stat($sqlc, $proid, $uid); + if(!$ret) + die('Eerror_get_pro_stat'); + + echo(json_encode($ret)); +} + +db_close($sqlc); + + +?> diff --git a/toj/php/pzreadtest.php b/toj/php/pzreadtest.php new file mode 100644 index 0000000..b67ae9e --- /dev/null +++ b/toj/php/pzreadtest.php @@ -0,0 +1,9 @@ +<?php + require_once('notice.inc.php'); + + function center_result_event($uid,$msg){ + $db = db_connect(); + notice::add($db,NOTICE_TYP_USR,$uid,json_encode($msg)); + db_close($db); + } +?> diff --git a/toj/php/sqlib.inc.php b/toj/php/sqlib.inc.php new file mode 100644 index 0000000..154bcbd --- /dev/null +++ b/toj/php/sqlib.inc.php @@ -0,0 +1,5 @@ +<?php + + require_once('sqlib_scoreboard.inc.php'); + +?> diff --git a/toj/php/sqlib_scoreboard.inc.php b/toj/php/sqlib_scoreboard.inc.php new file mode 100644 index 0000000..84a71ef --- /dev/null +++ b/toj/php/sqlib_scoreboard.inc.php @@ -0,0 +1,239 @@ +<?php + + /* + Square mod library : Scoreboard + 2013/02/10 By TOJTeam + + Get scoreboard by rank : + sqlib_scoreboard::get_scoreboard($sqlc, $msqlc, $sqid, $sboard_id, $score_func, $start_time, $end_time, $start_rank, $number) + + Get scoreboard of specific user : + sqlib_scoreboard::get_scoreboard_uid($sqlc, $msqlc, $sqid, $sboard_id, $score_func, $start_time, $end_time, $uid) + + $sqlc : sql connection to database 'toj' + $msqlc : sql connection to database 'toj_mod' + $sqid : square id number + $sboard_id : scoreboard id number (of square) + $score_func : function to determine rank_score + $start_time : start timestamp + $end_time : end timestamp + $start_rank : display from which rank + $number : number to display + $uid : user id number + + Parameter format of $score_func: + func($sqid, $proid, $best_score, $best_time, $is_ac, $ac_time, $tries_before_ac, $last_score, $last_status, $tries); + + */ + + require_once('common.inc.php'); + + class sqlib_scoreboard + { + public static function def_func($sqid, $proid, $best_score, $best_time, $is_ac, $ac_time, $tries_before_ac, $last_score, $last_status, $tries) + { + return $best_score; + } + + public static function get_last_update($msqlc, $sqid, $sboard_id) + { + $sqlstr = 'SELECT "last_update" FROM "sqlib_scoreboard_last_update" WHERE "sqid"=$1 AND "sboard_id"=$2;'; + $sqlarr = array($sqid, $sboard_id); + $res = pg_query_params($msqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_result($res, 0); + return $ret; + } + + public static function set_last_update($msqlc, $sqid, $sboard_id, $new) + { + $now = date('Y-m-d H:i:s+08'); + $sqlstr = 'UPDATE "sqlib_scoreboard_last_update" SET "last_update"=$3 WHERE "sqid"=$1 AND "sboard_id"=$2;'; + if($new) + { + $sqlstr = 'INSERT INTO "sqlib_scoreboard_last_update" ("sqid", "sboard_id", "last_update") VALUES ($1, $2, $3);'; + } + $sqlarr = array($sqid, $sboard_id, $now); + $res = pg_query_params($msqlc, $sqlstr, $sqlarr); + } + + public static function get_scoreboard($sqlc, $msqlc, $sqid, $sboard_id, $score_func, $start_time = null, $end_time = null, $start_offset, $number, $uid = null) + { + if(!$start_time)$start_time = '1900-01-01 01:01:01+08'; + if(!$end_time)$end_time = '2222-01-01- 01:01:01+08'; + sqlib_scoreboard::update($sqlc, $msqlc, $sqid, $sboard_id, $score_func, $start_time, $end_time); + + //display + $sqlstr = 'SELECT "a1"."uid", "a1"."rank_score", COUNT(*) AS "rank" FROM "sqlib_scoreboard_main" "a1", "sqlib_scoreboard_main" "a2" WHERE "a1"."sqid"=$1 AND "a1"."sboard_id"=$2 AND "a2"."sqid"=$1 AND "a2"."sboard_id"=$2 AND ("a2"."rank_score">"a1"."rank_score" OR "a2"."uid"="a1"."uid") GROUP BY "a1"."uid", "a1"."rank_score" ORDER BY "a1"."rank_score" DESC, "a1"."uid" LIMIT $4 OFFSET $3;'; + $sqlarr = array($sqid, $sboard_id, $start_offset-1, $number); + if($uid) + { + $sqlstr = 'SELECT "a1"."uid", "a1"."rank_score", COUNT(*) AS "rank" FROM "sqlib_scoreboard_main" "a1", "sqlib_scoreboard_main" "a2" WHERE "a1"."sqid"=$1 AND "a1"."sboard_id"=$2 AND "a1"."uid"=$3 AND "a2"."sqid"=$1 AND "a2"."sboard_id"=$2 AND ("a2"."rank_score">"a1"."rank_score" OR "a2"."uid"="a1"."uid") GROUP BY "a1"."uid", "a1"."rank_score";'; + $sqlarr = array($sqid, $sboard_id, $uid); + } + + $res = pg_query_params($msqlc, $sqlstr, $sqlarr); + $arr = pg_fetch_all($res); + + $ret_obj = array(); + foreach($arr as $item) + { + $obj = new stdClass(); + $obj->uid = intval($item['uid']); + $obj->rank_score = doubleval($item['rank_score']); + $obj->rank = intval($item['rank']); + $obj->problem = array(); + + $sqlstr = 'SELECT "proid", "best_score", "best_time", "is_ac", "ac_time", "tries_before_ac", "last_score", "last_status", "last_time", "tries", "rank_score" FROM "sqlib_scoreboard_pro" WHERE "sqid"=$1 AND "sboard_id"=$2 AND "uid"=$3;'; + $sqlarr = array($sqid, $sboard_id, $obj->uid); + $res = pg_query_params($msqlc, $sqlstr, $sqlarr); + $data = pg_fetch_all($res); + foreach($data as $pro) + { + $pobj = new stdClass(); + $pobj->proid = intval($pro['proid']); /// + $pobj->best_score = doubleval($pro['best_score']); + $pobj->best_time = $pro['best_time']; + $pobj->is_ac = ($pro['is_ac']=='t'); + $pobj->ac_time = $pro['ac_time']; + $pobj->tries_before_ac = intval($pro['tries_before_ac']); + $pobj->last_score = doubleval($pro['last_score']); + $pobj->last_status = intval($pro['last_status']); + $pobj->last_time = $pro['last_time']; + $pobj->tries = intval($pro['tries']); + $pobj->rank_score = doubleval($pro['rank_score']); + + $proid = intval($pro['proid']); + $obj->problem[$proid] = $pobj; + } + array_push($ret_obj, $obj); + } + return $ret_obj; + } + + public static function get_scoreboard_uid($sqlc, $msqlc, $sqid, $sboard_id, $score_func, $start_time = null, $end_time = null, $uid) + { + return sqlib_scoreboard::get_scoreboard($sqlc, $msqlc, $sqid, $sboard_id, $score_func, $start_time, $end_time, null, null, $uid); + } + + public static function update($sqlc, $msqlc, $sqid, $sboard_id, $score_func, $start_time, $end_time) + { + $last_update = sqlib_scoreboard::get_last_update($msqlc, $sqid, $sboard_id); + $last_update_time = strtotime($last_update); + if(!$last_update)$last_update_time = 0; + if($last_update_time <= time()-2) + { + sqlib_scoreboard::set_last_update($msqlc, $sqid, $sboard_id, !$last_update); + } + else return; + $last_update = date('Y-m-d H:i:s+08', $last_update_time); + + //echo ('update!!'.$last_update.'<br>'); + $sqlstr = 'SELECT DISTINCT "uid" FROM "submit" WHERE "last_update">=$4 AND "proid" IN (SELECT "proid" FROM "pro_sq" WHERE "sqid"=$1) AND "submit_time">=$2 AND "submit_time"<=$3;'; + $sqlarr = array($sqid, $start_time, $end_time, $last_update); + $res = pg_query_params($sqlc, $sqlstr, $sqlarr); + $uid_list = pg_fetch_all_columns($res); + foreach($uid_list as $item) + { + //echo($item.', '); + $uid = intval($item); + sqlib_scoreboard::update_user($sqlc, $msqlc, $sqid, $sboard_id, $score_func, $start_time, $end_time, $uid); + } + } + + public static function update_user($sqlc, $msqlc, $sqid, $sboard_id, $score_func, $start_time, $end_time, $uid) + { + $sqlstr = 'SELECT "proid" FROM "pro_sq" WHERE "sqid"=$1;'; + $sqlarr = array($sqid); + $res = pg_query_params($sqlc, $sqlstr, $sqlarr); + $proid_list = pg_fetch_all_columns($res, 0); + + $total_rank_score = 0.0; + foreach($proid_list as $item) + { + $proid = intval($item); + $sqlstr = 'SELECT "result", "score", "submit_time" FROM "submit" WHERE "uid"=$1 AND "proid"=$2 AND "submit_time">=$3 AND "submit_time"<=$4 ORDER BY "submit_time";'; + $sqlarr = array($uid, $proid, $start_time, $end_time); + $res = pg_query_params($sqlc, $sqlstr, $sqlarr); + $sub_list = pg_fetch_all($res); + + $best_score = -1.0; + $best_time = '1900-01-01 01:01:01+08'; + + $is_ac = false; + $ac_time = null; + $tries_before_ac = 0; + + $tries = count($sub_list); + $last_score = null; + $last_status = null; + $last_time = null; + if($sub_list) + { + $last_score = doubleval($sub_list[$tries-1]['score']); + $last_status = intval($sub_list[$tries-1]['result']); + $last_time = $sub_list[$tries-1]['submit_time']; + + foreach($sub_list as $obj) + { + $score = doubleval($obj['score']); + $status = intval($obj['result']); + $stime = $obj['submit_time']; + if($score > $best_score) + { + $best_score = $score; + $best_time = $stime; + } + if(!$is_ac) + { + if($status == 0) // JUDGE_AC + { + $is_ac = true; + $ac_time = $stime; + } + else + { + $tries_before_ac += 1; + } + } + } + } + else + { + $tries = 0; + $best_score = null; + $best_time = null; + } + + if($score_func == null)$score_func = array('sqlib_scoreboard', 'def_func'); + $rank_score = $score_func($sqid, $proid, $best_score, $best_time, $is_ac, $ac_time, $tries_before_ac, $last_score, $last_status, $last_time, $tries); + $sqlstr = 'SELECT COUNT(*) FROM "sqlib_scoreboard_pro" WHERE "sqid"=$1 AND "sboard_id"=$3 AND "proid"=$2 AND "uid"=$4;'; + $sqlarr = array($sqid, $proid, $sboard_id, $uid); + $res = pg_query_params($msqlc, $sqlstr, $sqlarr); + $cnt = intval(pg_fetch_result($res, 0)); + + $sqlstr = 'UPDATE "sqlib_scoreboard_pro" SET "best_score"=$5, "best_time"=$6, "is_ac"=$7, "ac_time"=$8, "tries_before_ac"=$9, "last_score"=$10, "last_status"=$11, "last_time"=$12, "tries"=$13, "rank_score"=$14 WHERE "sqid"=$1 AND "sboard_id"=$2 AND "proid"=$3 AND "uid"=$4;'; + if($cnt==0) + { + $sqlstr = 'INSERT INTO "sqlib_scoreboard_pro" ("sqid", "sboard_id", "proid", "uid", "best_score", "best_time", "is_ac", "ac_time", "tries_before_ac", "last_score", "last_status", "last_time", "tries", "rank_score") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14);'; + } + $sqlarr = array($sqid, $sboard_id, $proid, $uid, $best_score, $best_time, $is_ac?'t':'f', $ac_time, $tries_before_ac, $last_score, $last_status, $last_time, $tries, $rank_score); + $res = pg_query_params($msqlc, $sqlstr, $sqlarr); + //var_dump($sqlarr); + $total_rank_score += $rank_score; + } + + $sqlstr = 'SELECT COUNT(*) FROM "sqlib_scoreboard_main" WHERE "sqid"=$1 AND "sboard_id"=$2 AND "uid"=$3;'; + $sqlarr = array($sqid, $sboard_id, $uid); + $res = pg_query_params($msqlc, $sqlstr, $sqlarr); + $cnt = intval(pg_fetch_result($res, 0)); + + $sqlstr = 'UPDATE "sqlib_scoreboard_main" SET "rank_score"=$4 WHERE "sqid"=$1 AND "sboard_id"=$2 AND "uid"=$3;'; + if($cnt == 0) + { + $sqlstr = 'INSERT INTO "sqlib_scoreboard_main" ("sqid", "sboard_id", "uid", "rank_score") VALUES ($1, $2, $3, $4);'; + } + $sqlarr = array($sqid, $sboard_id, $uid, $total_rank_score); + $res = pg_query_params($msqlc, $sqlstr, $sqlarr); + } + } +?> diff --git a/toj/php/square.inc.php b/toj/php/square.inc.php new file mode 100644 index 0000000..784490d --- /dev/null +++ b/toj/php/square.inc.php @@ -0,0 +1,229 @@ +<?php + +require_once('common.inc.php'); +require_once('user.inc.php'); +require_once('problem.inc.php'); + +const SQUARE_USER_PENDING = 1; +const SQUARE_USER_ACTIVE = 2; +const SQUARE_USER_ADMIN = 3; + +const SQUARE_PUBLIC = 3; +const SQUARE_AUTH = 2; +const SQUARE_PRIVATE = 1; + +const SQUARE_NAME_LEN_MAX = 100; + +class square +{ + public $sqid; + public $publicity; + public $start_time; + public $end_time; + public $sqname; + public $sqmodname; + + public static function get($sqlc, $sqid) + { + //get square object from sqid + //return the object found. False if no such record + $sqlr = pg_query_params($sqlc, 'SELECT * FROM "square" WHERE "sqid"=$1 LIMIT 1;', array($sqid)); + $ret = pg_fetch_object($sqlr, null, 'square'); + pg_free_result($sqlr); + if($ret)$ret->sqid = intval($ret->sqid); + return $ret; + } + + public static function add($sqlc, $sq) + { + //add a square object + //required member of sq : publicity, start_time, end_time, sqname, sqmodname + //publicity : SQUARE_PUBLIC, SQUARE_AUTH, SQUARE_PRIVATE + //return the object . False if failed. + $sqlstr = 'INSERT INTO "square" ("publicity", "start_time", "end_time", "sqname", "sqmodname") VALUES ($1, $2, $3, $4, $5) RETURNING *;'; + $sqlarr = array($sq->publicity, $sq->start_time, $sq->end_time, $sq->sqname, $sq->sqmodname); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_object($sqlr, null, 'square'); + pg_free_result($sqlr); + if($ret)$ret->sqid = intval($ret->sqid); + return $ret; + } + + public static function edit($sqlc, $sqid, $sq) + { + //edit exist square data + //required member of sq : publicity, start_time, end_time, sqname, sqmodname + //publicity : SQUARE_PUBLIC, SQUARE_AUTH, SQUARE_PRIVATE + //return edited object . False if failed. + // + //if puhlicity change SQUARE_AUTH => SQUARE_PUBLIC, + //set all SQUARE_USER_PENDING users to SQUARE_USER_ACTIVE. + $oldsq = square::get($sqlc, $sqid); + if($oldsq->publicity==SQUARE_AUTH && $sq->publicity==SQUARE_PUBLIC) + { + $sqlstr = 'UPDATE "us_sq" SET "relationship"=$1 WHERE "sqid"=$2 AND "relationship"=$3;'; + $sqlarr = array(SQUARE_USER_ACTIVE, $sqid, SQUARE_USER_PENDING); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + } + $sqlstr = 'UPDATE "square" SET "publicity"=$1, "start_time"=$2, "end_time"=$3, "sqname"=$4, "sqmodname"=$5 WHERE "sqid"=$6 RETURNING *;'; + $sqlarr = array($sq->publicity, $sq->start_time, $sq->end_time, $sq->sqname, $sq->sqmodname, $sqid); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_object($sqlr, null, 'square'); + pg_free_result($sqlr); + if($ret)$ret->sqid = intval($ret->sqid); + return $ret; + } + + public static function del($sqlc, $sqid) + { + //Delete the square $sqid. Also delete the user-square relation involves this square. + //return false if failed. + $sqlstr = 'DELETE FROM "square" WHERE "sqid"=$1;'; + $sqlstr2 = 'DELETE FROM "us_sq" WHERE "sqid"=$1;'; + $sqlr = pg_query_params($sqlc, $sqlstr, array($sqid)); + if(!$sqlr)return false; + $sqlr = pg_query_params($sqlc, $sqlstr2, array($sqid)); + if(!$sqlr)return false; + else return true; + } + + public static function add_user($sqlc, $uid, $sqid, $relationship) + { + //add user into user-square relation. + //return false if failed. + $sqlstr = 'INSERT INTO "us_sq" ("uid", "sqid", "relationship") VALUES ($1, $2, $3) RETURNING *;'; + $sqlarr = array($uid, $sqid, $relationship); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_object($sqlr); + pg_free_result($sqlr); + if(!$ret)return false; + else return true; + } + + public static function del_user($sqlc, $uid, $sqid) + { + //delete user from user-square relation. + //return false if failed. + $sqlstr = 'DELETE FROM "us_sq" WHERE "uid"=$1 AND "sqid"=$2;'; + $sqlarr = array($uid, $sqid); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + if(!$sqlr)return false; + else return true; + } + + public static function set_user_relationship($sqlc, $uid, $sqid, $relationship) + { + //update user relationship. + //relationship: SQUARE_USER_PENDING, SQUARE_USER_ACTIVE, SQUARE_USER_ADMIN + //return false if failed. + $sqlr = pg_query_params($sqlc, 'UPDATE "us_sq" SET "relationship"=$3 WHERE "uid"=$1 AND "sqid"=$2;', array($uid, $sqid, $relationship)); + if(!$sqlr)return false; + else return true; + } + + public static function get_user_relationship($sqlc, $uid, $sqid) + { + //get the relationship of uid,sqid from user-square relation. + //Return the relationship. SQUARE_USER_PENDING, SQUARE_USER_ACTIVE, SQUARE_USER_ADMIN + //return false if no record in the table; + $sqlr = pg_query_params($sqlc, 'SELECT "relationship" FROM "us_sq" WHERE "uid"=$1 AND "sqid"=$2;', array($uid, $sqid)); + $ret = pg_fetch_result($sqlr, 0); + if(!$ret)return false; + else return intval($ret); + } + + public static function get_available_sq($sqlc, $uid, $minpub) + { + //get all available square for given uid and publicity at least minpub. (not includes entered ones) + //Return array of object, which contains each sqid, start_time, end_time, publicity, sqname, sqmodname + //return empty array if no record in the table; + $sqlstr = 'SELECT "sqid", "start_time", "end_time", "publicity", "sqname", "sqmodname" FROM "square" WHERE "sqid" NOT IN (SELECT "sqid" FROM "us_sq" WHERE "uid"=$1) AND "publicity" >= $2 ORDER BY (CASE WHEN "square"."end_time" IS NULL THEN "square"."sqid" ELSE 0 END), "square"."start_time", "square"."sqid";'; + $sqlarr = array($uid, $minpub); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = array(); + while($row = pg_fetch_object($sqlr)) + { + array_push($ret, $row); + } + return $ret; + } + + public static function get_entered_sq($sqlc, $uid) + { + //gel all entered square for given uid. + //Return array of object, which contains each sqid, start_time, end_time, publicity, sqname, sqmodname, relationship + //return empty array if no record in the table; + $sqlstr = 'SELECT "square"."sqid", "square"."start_time", "square"."end_time", "square"."publicity", "square"."sqname", "square"."sqmodname", "us_sq"."relationship" FROM "us_sq" INNER JOIN "square" ON "us_sq"."sqid"="square"."sqid" WHERE "us_sq"."uid"=$1 ORDER BY (CASE WHEN "square"."end_time" IS NULL THEN "square"."sqid" ELSE 0 END), "square"."start_time", "square"."sqid";'; + $sqlarr = array($uid); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = array(); + while($row = pg_fetch_object($sqlr)) + { + array_push($ret, $row); + } + return $ret; + } + + public static function del_pro($sqlc, $proid, $sqid) + { + //Delete $proid from square $sqid. + //Return true if success, false if failed. + $sqlstr = 'DELETE FROM "pro_sq" WHERE "proid"=$1 AND "sqid"=$2;'; + $sqlarr = array($proid, $sqid); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + if(!$sqlr) + return false; + return true; + } + + public static function add_pro($sqlc, $proid, $sqid) + { + //Add problem $proid into square $sqid. + //Return true if success, false if failed. + $sqlstr = 'INSERT INTO "pro_sq" ("proid", "sqid") VALUES ($1, $2) RETURNING *;'; + $sqlarr = array($proid, $sqid); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_result($sqlr, 0); + if(!$ret) + return false; + return true; + } + + public static function is_pro_in_sq($sqlc, $proid, $sqid) + { + //Return whether problem $proid is in square $sqid or not. + $sqlstr = 'SELECT COUNT(*) FROM "pro_sq" WHERE "proid"=$1 AND "sqid"=$2;'; + $sqlarr = array($proid, $sqid); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = intval(pg_fetch_result($sqlr, 0)); + return $ret > 0; + } + + public static function get_sqmod($sqlc, $sqid) + { + //Return the sqmodname of square $sqid. + $sqlstr = 'SELECT "sqmodname" FROM "square" WHERE "sqid"=$1;'; + $sqlarr = array($sqid); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_result($sqlr, 0); + return $ret; + } + + public static function get_pro_list($sqlc, $sqid) + { + //get problem list of square $sqid. + $sqlstr = 'SELECT "problem"."proid", "problem"."proname", "problem"."hidden" FROM "problem" INNER JOIN "pro_sq" ON "problem"."proid"="pro_sq"."proid" WHERE "pro_sq"."sqid"=$1 ORDER BY "problem"."proid";'; + $sqlarr = array($sqid); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = array(); + while($obj = pg_fetch_object($sqlr)) + { + $obj->proid = intval($obj->proid); + $obj->hidden = ($obj->hidden=='t'); + array_push($ret, $obj); + } + return $ret; + } +} + +?> diff --git a/toj/php/square.php b/toj/php/square.php new file mode 100644 index 0000000..4880ab3 --- /dev/null +++ b/toj/php/square.php @@ -0,0 +1,350 @@ +<?php +//ini_set("display_errors", "On"); + +require_once('square.inc.php'); + +$sqlc = db_connect(); + +$action = $_POST['action']; +$data = $_POST['data']; + +if(strlen($action)==0) + die('Eno_action'); +if($action == 'add_sq') +{ + //Add new square. level USER_LEVEL_SUPERADMIN or above required. + //data: sqname, publicity, [start_time, end_time], sqmodname + + $sq = json_decode($data); + + if(!sec_is_login()) + die('Eno_login'); + if(!sec_check_level($sqlc, USER_LEVEL_SUPERADMIN)) + die('Epermission_denied'); + + if($sq->publicity != SQUARE_PUBLIC && $sq->publicity != SQUARE_AUTH && $sq->publicity != SQUARE_PRIVATE) + die('Ewrong_publicity'); + + if(!($sq->start_time)) + $sq->start_time = date('Y-m-d H:i:s'); + if(!($sq->end_time)) + $sq->start_time = null; + if(strlen($sq->sqname)==0) + die('Esqname_too_short'); + if(strlen($sq->sqname)>SQUARE_NAME_LEN_MAX) + die('Esqname_too_long'); + if(strlen($sq->sqmodname)==0) + die('Esqmodname_empty'); + + $res = square::add($sqlc, $sq); + if(!$res) + die('Eadd_sq_failed'); + + $res2 = square::add_user($sqlc, $_COOKIE['uid'], $res->sqid, SQUARE_USER_ADMIN); + if(!$res2) + die('Eadd_admin_failed'); + + echo('S'); +} +if($action == 'delete_sq') +{ + //Delete exist square. level USER_LEVEL_SUPERADMIN or above required. + //data : sqid + + $sq = json_decode($data); + + if(!sec_is_login()) + die('Eno_login'); + if(!sec_check_level($sqlc, USER_LEVEL_SUPERADMIN)) + die('Epermission_denied'); + + $sqid = intval($sq->sqid); + if(!square::get($sqlc, $sqid)) + die('Eno_such_sq'); + + $res = square::del($sqlc, $sqid); + if(!$res) + die('Edelete_failed'); + + echo('S'); +} +if($action == 'edit_sq') +{ + //edit exist square. level USER_LEVEL_SUPERADMIN / SQUARE_USER_ADMIN or above required. + //data: sqid, sqname, publicity, [start_time, end_time], sqmodname + + $sq = json_decode($data); + + if(!sec_is_login()) + die('Eno_login'); + + $sqid = intval($sq->sqid); + if(!square::get($sqlc, $sqid)) + die('Eno_such_sq'); + + if(!sec_check_level($sqlc, USER_LEVEL_SUPERADMIN) && !(square::get_user_relationship($sqlc, $_COOKIE['uid'], $sqid)>=SQUARE_USER_ADMIN)) + die('Epermission_denied'); + + if($sq->publicity != SQUARE_PUBLIC && $sq->publicity != SQUARE_AUTH && $sq->publicity != SQUARE_PRIVATE) + die('Ewrong_publicity'); + + if(!($sq->start_time) && $sq->end_time) + $sq->start_time = date('Y-m-d H:i:s'); + if(strlen($sq->sqname)==0) + die('Esqname_too_short'); + if(strlen($sq->sqname)>SQUARE_NAME_LEN_MAX) + die('Esqname_too_long'); + if(strlen($sq->sqmodname)==0) + die('Esqmodname_empty'); + + $res = square::edit($sqlc, $sqid, $sq); + if(!$res) + die('Eedit_failed'); + + echo('S'); +} +if($action == 'get_sq') +{ + //get exist square data + //data: sqid + $sq = json_decode($data); + + $sqid = intval($sq->sqid); + + $ret = square::get($sqlc, $sqid); + if(!$ret) + die('Eno_such_sq'); + + echo(json_encode($ret)); +} +if($action == 'add_user') +{ + //add user to exist square + //data: uid, sqid + $dt = json_decode($data); + + if(!sec_is_login()) + die('Eno_login'); + + $uid = intval($dt->uid); + $sqid = intval($dt->sqid); + + $usr = user::get_from_uid($sqlc, $uid); + if(!$usr) + die('Eno_such_user'); + + $sq = square::get($sqlc, $sqid); + if(!$sq) + die('Eno_such_sq'); + + $adm = sec_check_level($sqlc, USER_LEVEL_SUPERADMIN) || (square::get_user_relationship($sqlc, $_COOKIE['uid'], $sqid)>=SQUARE_USER_ADMIN); + + if($uid != intval($_COOKIE['uid']) && !$adm) + die('Epermission_denied'); + + $rela = SQUARE_USER_ACTIVE; + if(!$adm) + { + if($sq->publicity == SQUARE_AUTH) + $rela = SQUARE_USER_PENDING; + if($sq->publicity == SQUARE_PRIVATE) + die('Eprivate_square'); + } + + if(square::get_user_relationship($sqlc, $uid, $sqid)) + die('Ealready_entered'); + + $ret = square::add_user($sqlc, $uid, $sqid, $rela); + if(!$ret) + die('Eadd_user_failed'); + + echo('S'); +} +if($action == 'delete_user') +{ + //delete user from user-square relation + //data : uid, sqid + $dt = json_decode($data); + + if(!sec_is_login()) + die('Eno_login'); + + $uid = intval($dt->uid); + $sqid = intval($dt->sqid); + + $usr = user::get_from_uid($sqlc, $uid); + if(!$usr) + die('Eno_such_user'); + + $sq = square::get($sqlc, $sqid); + if(!$sq) + die('Eno_such_sq'); + + $adm = sec_check_level($sqlc, USER_LEVEL_SUPERADMIN) || (square::get_user_relationship($sqlc, $_COOKIE['uid'], $sqid)>=SQUARE_USER_ADMIN); + + if($uid != intval($_COOKIE['uid']) && !$adm) + die('Epermission_denied'); + + if(!square::get_user_relationship($sqlc, $uid, $sqid)) + die('Enot_entered'); + + $ret = square::del_user($sqlc, $uid, $sqid); + if(!$ret) + die('Edelete_user_failed'); + + echo('S'); +} +if($action == 'edit_user_relationship') +{ + //edit user relationship. + //data: uid, sqid, relationship + $dt = json_decode($data); + + if(!sec_is_login()) + die('Eno_login'); + + $uid = intval($dt->uid); + $sqid = intval($dt->sqid); + $rel = intval($dt->relationship); + + $usr = user::get_from_uid($sqlc, $uid); + if(!$usr) + die('Eno_such_user'); + + $sq = square::get($sqlc, $sqid); + if(!$sq) + die('Eno_such_sq'); + + $adm = sec_check_level($sqlc, USER_LEVEL_SUPERADMIN) || (square::get_user_relationship($sqlc, $_COOKIE['uid'], $sqid)>=SQUARE_USER_ADMIN); + + if(!$adm) + die('Epermission_denied'); + + if(!square::get_user_relationship($sqlc, $uid, $sqid)) + die('Enot_entered'); + + if($rel!=SQUARE_USER_PENDING && $rel!=SQUARE_USER_ACTIVE && $rel!=SQUARE_USER_ADMIN) +die('Ewrong_relationship'); + + $ret = square::set_user_relationship($sqlc, $uid, $sqid, $rel); + if(!$ret) + die('Eedit_user_relationship_failed'); + + echo('S'); +} +if($action == 'get_available_sq') +{ + //get all available square data: sqid, start_time, end_time, publicity, sqname for given uid. + //only USER_LEVEL_SUPERADMIN can see SQUARE_PRIVATE squares. + //data: (no) + + if(!sec_is_login()) + die('Eno_login'); + + $uid = intval($_COOKIE['uid']); + + $usr = user::get_from_uid($sqlc, $uid); + if(!$usr) + die('Eno_such_user'); + + $adm = sec_check_level($sqlc, USER_LEVEL_SUPERADMIN); + + $pub = 2; + if($adm) + $pub = 1; + + $list = square::get_available_sq($sqlc, $uid, $pub); + + $ret->list = $list; + $ret->timestamp = date('Y-m-d H:i:s'); + + echo(json_encode($ret)); +} +if($action == 'get_entered_sq') +{ + + //get all entered square data: sqid, start_time, end_time, publicity, sqname, relationship for given uid. + //data: (no) + + if(!sec_is_login()) + die('Eno_login'); + + $uid = intval($_COOKIE['uid']); + + $usr = user::get_from_uid($sqlc, $uid); + if(!$usr) + die('Eno_such_user'); + + $list = square::get_entered_sq($sqlc, $uid); + + $ret->list = $list; + $ret->timestamp = date('Y-m-d H:i:s'); + + echo(json_encode($ret)); +} +if($action == 'add_pro_into_sq') +{ + if(!sec_is_login()) + die('Eno_login'); + + $uid = intval($_COOKIE['uid']); + + $usr = user::get_from_uid($sqlc, $uid); + if(!$usr) + die('Eno_such_user'); + + $dt = json_decode($data); + if(!problem::is_available($sqlc, $dt->proid)) + die('Ewrong_proid'); + + if(!square::get($sqlc, $dt->sqid)) + die('Ewrong_sqid'); + + $adm = sec_check_level($sqlc, USER_LEVEL_SUPERADMIN) || square::get_user_relationship($sqlc, $uid, $dt->sqid) >= SQUARE_USER_ADMIN; + + if(!$adm) + die('Enot_square_admin'); + + if(square::is_pro_in_sq($sqlc, $dt->proid, $dt->sqid)) + die('Ealready_in_square'); + + $ret = square::add_pro($sqlc, $dt->proid, $dt->sqid); + if(!$ret) + die('Eadd_problem_into_square_failed'); + + echo('S'); +} +if($action == 'delete_pro_from_sq') +{ + if(!sec_is_login()) + die('Eno_login'); + + $uid = intval($_COOKIE['uid']); + + $usr = user::get_from_uid($sqlc, $uid); + if(!$usr) + die('Eno_such_user'); + + $dt = json_decode($data); + + if(!square::get($sqlc, $dt->sqid)) + die('Ewrong_sqid'); + + $adm = sec_check_level($sqlc, USER_LEVEL_SUPERADMIN) || square::get_user_relationship($sqlc, $uid, $dt->sqid) >= SQUARE_USER_ADMIN; + + if(!$adm) + die('Enot_square_admin'); + + if(!square::is_pro_in_sq($sqlc, $dt->proid, $dt->sqid)) + die('Enot_in_square'); + + $ret = square::del_pro($sqlc, $dt->proid, $dt->sqid); + if(!$ret) + die('Edelete_problem_from_square_failed'); + + echo('S'); +} + +db_close($sqlc); + +?> diff --git a/toj/php/status.inc.php b/toj/php/status.inc.php new file mode 100644 index 0000000..d9f4f7d --- /dev/null +++ b/toj/php/status.inc.php @@ -0,0 +1,133 @@ +<?php +require_once('common.inc.php'); +require_once('user.inc.php'); +require_once('problem.inc.php'); + +const SUBMIT_COUNT_MAX = 100; +const SUBMIT_SLEEP_TIME = 2; +const SUBMIT_WAIT_MAX = 10; + +class status +{ + public static function get_submit($sqlc, $filter, $sort, $count, $last_update, $admin) + { + //get submit from submit table. + //return an array with every entry an object of submission. + $condstr = ''; + $ordstr = ''; + + if($admin != true) + { + $uid = $_COOKIE['uid']; + if(!sec_is_login()) + $uid = 0; + $condstr = $condstr.'("problem"."admin_uid"='.intval($uid).' OR "problem"."hidden"=\'f\') AND '; + } + + if($last_update != null) + { + $condstr = $condstr.'"last_update">\''.pg_escape_string($last_update).'\' AND '; + } + + if($filter->userid != null) + { + $condstr = $condstr.'"uid"='.pg_escape_string($filter->userid).' AND '; + } + if($filter->result != null) + { + $condstr = $condstr.'"result"='.pg_escape_string($filter->result).' AND '; + } + if($filter->proid != null) + { + $condstr = $condstr.'"proid"='.pg_escape_string($filter->proid).' AND '; + } + if($filter->lang != null) + { + $condstr = $condstr.'"lang"='.pg_escape_string($filter->lang).' AND '; + } + if($sort->score != null) + { + $relstr = $sort->score[0]==0 ? '<=' : '>='; + $condstr = $condstr.'"score"'.$relstr.pg_escape_string($sort->score[1]).' AND '; + $ordstr = $ordstr.'"score" '.($sort->score[0]==0 ? 'DESC' : 'ASC').' ,'; + } + if($sort->runtime != null) + { + $relstr = $sort->runtime[0]==0 ? '<=' : '>='; + $condstr = $condstr.'"runtime"'.$relstr.pg_escape_string($sort->runtime[1]).' AND '; + $ordstr = $ordstr.'"runtime" '.($sort->runtime[0]==0 ? 'DESC' : 'ASC').' ,'; + } + if($sort->maxmem != null) + { + $relstr = $sort->maxmem[0]==0 ? '<=' : '>='; + $condstr = $condstr.'"memory"'.$relstr.pg_escape_string($sort->maxmem[1]).' AND '; + $ordstr = $ordstr.'"memory" '.($sort->maxmem[0]==0 ? 'DESC' : 'ASC').' ,'; + } + if($sort->subid != null) + { + $relstr = $sort->subid[0]==0 ? '<' : '>'; + $condstr = $condstr.'"subid"'.$relstr.pg_escape_string($sort->subid[1]); + $ordstr = $ordstr.'"subid" '.($sort->subid[0]==0 ? 'DESC' : 'ASC'); + } + + + $sqlstr = 'SELECT "submit".*, "user"."nickname" FROM ("submit" INNER JOIN "user" ON "submit"."uid"="user"."uid") INNER JOIN "problem" ON "submit"."proid"="problem"."proid" WHERE '.$condstr.' ORDER BY '.$ordstr.' LIMIT '.pg_escape_string($count).';'; + + //echo($sqlstr.'<br>'); + $sqlr = pg_query($sqlc, $sqlstr); + //return pg_fetch_object($sqlr); + $ret = array(); + while($obj = pg_fetch_object($sqlr)) + { + $obj->subid = intval($obj->subid); + $obj->uid = intval($obj->uid); + $obj->proid = intval($obj->proid); + $obj->result = intval($obj->result); + $obj->runtime = intval($obj->runtime); + $obj->memory = intval($obj->memory); + $obj->score = intval($obj->score); + $obj->lang = intval($obj->lang); + + array_push($ret, $obj); + } + + return $ret; + } + + public static function get_by_subid($sqlc, $subid) + { + //get submit information by subid. + //return submit information. + + $sqlstr = 'SELECT "submit".*, "mod"."smodname" FROM ("submit" INNER JOIN "problem" ON "submit"."proid"="problem"."proid") INNER JOIN "mod" ON "problem"."modid"="mod"."modid" WHERE "subid"=$1;'; + $sqlarr = array($subid); + $sqlr = pg_query_params($sqlstr, $sqlarr); + $ret = pg_fetch_object($sqlr); + if(!$ret) + die('Eno_such_subid'); + $ret->subid = intval($ret->subid); + $ret->proid = intval($ret->proid); + $ret->uid = intval($ret->uid); + $ret->result = intval($ret->result); + $ret->memory = intval($ret->memory); + $ret->score = intval($ret->score); + $ret->lang = intval($ret->lang); + + return $ret; + } + + public static function subid_is_available($sqlc, $subid) + { + //decide whether subid is visible or not. + //Return true if OK, false if permission denied or failed. + $sub = status::get_by_subid($sqlc, $subid); + if(!$sub) + return false; + $ret = problem::is_available($sqlc, $sub->proid); + if(!$ret) + return false; + return true; + } +} + +?> diff --git a/toj/php/status.php b/toj/php/status.php new file mode 100644 index 0000000..5c00580 --- /dev/null +++ b/toj/php/status.php @@ -0,0 +1,70 @@ +<?php +ini_set("display_errors", "On"); +error_reporting(E_ALL & ~E_NOTICE); + +require_once('status.inc.php'); + +$sqlc = db_connect(); + +$action = $_POST['action']; +$data = $_POST['data']; + +if(strlen($action)==0) + die('Eno_action'); +if($action == 'get_submit') +{ + //get submit from submit table + //data: sort, sort->subid, count, [wait, filter, last_update] + $dt = json_decode($data); + if($dt->sort->subid == null) + die('Eno_sort_subid'); + if($dt->count == null) + die('Eno_count'); + $cnt = intval($dt->count); + if($cnt <= 0) + die('Etoo_few_count'); + if($cnt > SUBMIT_COUNT_MAX) + die('Etoo_many_count'); + + $wait = intval($dt->wait); + if($wait > SUBMIT_WAIT_MAX) + die('Etoo_many_wait'); + + $nowwait = $wait; + $isadm = sec_check_level($sqlc, USER_PER_PROADMIN); + + while(1) + { + $ret = status::get_submit($sqlc, $dt->filter, $dt->sort, $cnt, $dt->last_update, $isadm); + if($ret != null) + { + /* OUTPUT */ + echo(json_encode($ret)); + exit(0); + } + //die('Efail'); + $nowwait--; + if($nowwait<0)break; + sleep(SUBMIT_SLEEP_TIME); + } + die('Eno_result'); +} +if($action == 'get_by_subid') +{ + //get submission data and smodname by subid. + //problem must be available for the user. + //data: subid + $dt = json_decode($data); + $subid = intval($dt->subid); + if(!$subid) + die('Eno_subid'); + $obj = status::get_by_subid($sqlc, $subid); + + if(!problem::is_available($sqlc, $obj->proid)) + die('Epermission_denied'); + + echo(json_encode($obj)); +} + +db_close($sqlc); +?> diff --git a/toj/php/step.inc.php b/toj/php/step.inc.php new file mode 100644 index 0000000..a116a64 --- /dev/null +++ b/toj/php/step.inc.php @@ -0,0 +1,17 @@ +<?php + +require_once('common.inc.php'); +require_once('square.inc.php'); +require_once('sqlib_scoreboard.inc.php'); + +function get_prob_stat_uid($sqlc, $msqlc, $sqid, $sboard_id, $uid) +{ + $sq = square::get($sqlc, $sqid); + if(!$sq)die('Eno_such_sq'); + + $data = sqlib_scoreboard::get_scoreboard_uid($sqlc, $msqlc, $sqid, $sboard_id, null, $sq->start_time, $sq->end_time, $uid); + + return $data[0]; +} + +?> diff --git a/toj/php/step.php b/toj/php/step.php new file mode 100644 index 0000000..6425ae1 --- /dev/null +++ b/toj/php/step.php @@ -0,0 +1,64 @@ +<?php +//ini_set("display_errors", "On"); + +require_once('common.inc.php'); +require_once('step.inc.php'); +require_once('teamt.php'); + +$sqlc = db_connect(); +$msqlc = db_connect('toj_mod'); + +if(strlen($action)==0) + die('Eno_action'); +if($action == '') +{ +} + +$uid = $_GET['uid']; +$dat = get_prob_stat_uid($sqlc, $msqlc, 1, 2, $uid); + +//var_dump($dat); +echo('uid : '.$dat->uid.'<br>'); +foreach($dat->problem as $prob) +{ + echo('problem '.$prob->proid.' : '); + if(!$prob->tries) + { + echo('--<br>'); + continue; + } + echo($prob->best_score.' '); + if($prob->is_ac)echo('AC'); + echo('<br>'); +} + +$term = 1; +$teamid = get_teamid($msqlc, $term, $uid); +echo('<br>Team : '.$teamid.'<br>Members : <br>'); +$members = get_team_member($msqlc, $term, $teamid); +foreach($members as $mem) +{ + echo('<br>Uid : '.$mem->uid.' ( Level '.$mem->level.' )<br>'); + $uid = intval($mem->uid); + if($uid == intval($_GET['uid']))continue; + $dat = get_prob_stat_uid($sqlc, $msqlc, 1, 2, $uid); + + foreach($dat->problem as $prob) + { + echo('problem '.$prob->proid.' : '); + if(!$prob->tries) + { + echo('--<br>'); + continue; + } + echo($prob->best_score.' '); + if($prob->is_ac)echo('AC'); + echo('<br>'); + } +} + + +db_close($sqlc); +db_close($msqlc); + +?> diff --git a/toj/php/teamt.php b/toj/php/teamt.php new file mode 100644 index 0000000..ca1cd4b --- /dev/null +++ b/toj/php/teamt.php @@ -0,0 +1,28 @@ +<?php + +require_once('common.inc.php'); + +function get_teamid($msqlc, $term, $uid) +{ + $sqlstr = 'SELECT "teamid" FROM "sqmod_sprout_team" WHERE "term"=$1 AND "uid"=$2;'; + $sqlarr = array($term, $uid); + $res = pg_query_params($sqlstr, $sqlarr); + $teamid = pg_fetch_result($res, 0); + return $teamid; +} + +function get_team_member($msqlc, $term, $teamid) +{ + $sqlstr = 'SELECT "uid", "level" FROM "sqmod_sprout_team" WHERE "term"=$1 AND "teamid"=$2 ORDER BY "level" DESC, "uid";'; + $sqlarr = array($term, $teamid); + $res = pg_query_params($sqlstr, $sqlarr); + $ret = array(); + while($obj = pg_fetch_object($res)) + { + array_push($ret, $obj); + } + return $ret; +} + + +?> diff --git a/toj/php/test.php b/toj/php/test.php new file mode 100644 index 0000000..a38a8a8 --- /dev/null +++ b/toj/php/test.php @@ -0,0 +1,32 @@ +<?php +ini_set("display_errors", "On"); +error_reporting(E_ALL & ~E_NOTICE); + +require_once('common.inc.php'); +require_once('sqlib.inc.php'); +require_once('user.inc.php'); + +$msqlc = db_connect('toj_mod'); +$sqlc = db_connect(); + +function func($sqid, $proid, $best_score, $best_time, $is_ac, $ac_time, $tries_before_ac, $last_score, $last_status, $last_time, $tries) +{ + return $best_score; +} + +//$a = intval($_GET['a']); +//sqlib_scoreboard::set_last_update($msqlc, 1, 4, false); +//$scb = sqlib_scoreboard::get_scoreboard($sqlc, $msqlc, 1, $a, func, null, null, 1, 20); +//var_dump($scb); +//echo(json_encode($scb)); +//$test = sqlib_scoreboard::get_last_update($msqlc, 1, $a); +//echo($test.'<br>'); +//echo(strtotime($test).'<br>'); +//echo(time()); + +$res = user::reset_password($sqlc, 130); +var_dump($res); + +db_close($sqlc); +db_close($msqlc); +?> diff --git a/toj/php/user.inc.php b/toj/php/user.inc.php new file mode 100644 index 0000000..1a3eaef --- /dev/null +++ b/toj/php/user.inc.php @@ -0,0 +1,212 @@ +<?php + +require_once('common.inc.php'); +require_once('/srv/http/phpmailer/class.phpmailer.php'); + +const USERNAME_LEN_MIN = 5; +const USERNAME_LEN_MAX = 20; +const PASSWORD_LEN_MIN = 5; +const PASSWORD_LEN_MAX = 32; +const NICKNAME_LEN_MIN = 1; +const NICKNAME_LEN_MAX = 32; +const EMAIL_LEN_MAX = 100; + +const USER_PER_USER = 0x00000001; +const USER_PER_PROCREATOR = 0x00000002; +const USER_PER_PROADMIN = 0x00000004; + +const USER_LEVEL_USER = 0x00000001; +const USER_LEVEL_PROCREATOR = 0x00000003; +const USER_LEVEL_PROADMIN = 0x00000007; +const USER_LEVEL_ADMIN = 0x0000ffff; +const USER_LEVEL_SUPERADMIN = 0xffffffff; + +class user +{ + public $uid; + public $username; + public $password; + public $nickname; + public $aboutme; + public $avatar; + public $level; + public $email; + + public static function get_from_uid($sqlc, $uid) + { + //return user object of specified uid. False if user doesn't exists. + + $result = pg_query_params($sqlc, 'SELECT * FROM "user" WHERE "uid"=$1 LIMIT 1;', array(intval($uid))) or die ("Eerror_get_user"); + $ret = pg_fetch_object($result, null, 'user'); + pg_free_result($result); + if(!$ret) + return false; + $ret->uid = intval($ret->uid); + $ret->level = intval($ret->level); + return $ret; + } + + public static function get_from_username($sqlc, $username) + { + //return user object of specified username. False if user doesn't exists. + + $result = pg_query_params($sqlc, 'SELECT * FROM "user" WHERE "username"=$1 LIMIT 1;', array($username)); + $ret = pg_fetch_object($result, null, 'user'); + pg_free_result($result); + if(!$ret) + return false; + $ret->uid = intval($ret->uid); + $ret->level = intval($ret->level); + + return $ret; + } + + public static function add($sqlc, $user) + { + //add user to database , with $user the user data object + //return inserted user object. False if failed. + //Assume the insertion is valid!! + //requires member: string username, string nickname, string password, stirng aboutme, string avatar, string email + + $sqlstr = 'INSERT INTO "user" ("username", "nickname", "password", "aboutme", "avatar", "email") VALUES ($1, $2, $3, $4, $5, $6) RETURNING *;'; + $sqlarr = array($user->username, $user->nickname, $user->password, '', '', $user->email); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + if(!$sqlr)return false; + //$sqlr = pg_query($sqlc, 'SELECT SCOPE_IDENTITY();'); + $obj = pg_fetch_object($sqlr, null, 'user'); + pg_free_result($sqlr); + if($obj)$obj->uid = intval($obj->uid); + return $obj; + } + + public static function update($sqlc, $user) + { + //update user data into database, with $user the user data object + //return updated object. False if failed. + //Assume the update is valid!! + //requires member: string nickname, string password, string aboutme, string avatar, string email, int uid + + $sqlstr = 'UPDATE "user" SET "nickname"=$1, "password"=$2, "aboutme"=$3, "avatar"=$4, "email"=$5 WHERE "uid"=$6 RETURNING *;'; + $sqlarr = array($user->nickname, $user->password, $user->aboutme, $user->avatar, $user->email, intval($user->uid)); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + if(!$sqlr)return false; + $obj = pg_fetch_object($sqlr, null, 'user'); + pg_free_result($sqlr); + if($obj)$obj->uid = intval($obj->uid); + return $obj; + } + + /*public static function update_property($sqlc, $user) + { + //update property of given user. + //return updated object. False if failed. + //Assume the update is valid!! + //requires member: int[] property, int uid; + + $sqlstr = 'UPDATE "user" SET "property"=$1 WHERE "uid"=$2 RETURNING *;'; + $sqlarr = array($user->property, intval($user->uid)); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + if(!$sqlr)return false; + $obj = pg_fetch_object($sqlr, null, 'user'); + pg_free_result($sqlr); + if($obj)$obj->uid = intval($obj->uid); + return $obj; + }*/ + + public static function get_username($sqlc, $uid) + { + //return username of given uid. False if not found. + + $sqlstr = 'SELECT "username" FROM "user" WHERE "uid"=$1 LIMIT 1;'; + $sqlarr = array(intval($uid)); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_result($sqlr, 0); + pg_free_result($sqlr); + return $ret; + } + + public static function get_nickname($sqlc, $uid) + { + //return nickname of given uid. False if not found. + + $sqlstr = 'SELECT "nickname" FROM "user" WHERE "uid"=$1 LIMIT 1;'; + $sqlarr = array(intval($uid)); + $sqlr = pg_query_params($sqlc, $sqlstr, $sqlarr); + $ret = pg_fetch_result($sqlr, 0); + pg_free_result($sqlr); + return $ret; + } + + public static function reset_password($sqlc, $uid) + { + //reset password for given uid. False if not found. + + $user = user::get_from_uid($sqlc, $uid); + if(!$user)return false; + $email = $user->email; + if(!$email)return false; + + $passlen = 8; + $newpass = ''; + for($i = 0; $i < $passlen; $i++) + { + $v = rand()%62; + $c = null; + if($v<10)$c = chr(48 + $v); + else if($v<36)$c = chr(65 + $v - 10); + else $c = chr(97 + $v - 36); + $newpass = $newpass.$c; + } + echo($newpass.'<br>'); + + //email + + $cmail = new PHPMailer(); + $cmail->IsSMTP(); + + $cmail->SMTPAuth = true; + $cmail->SMTPSecure = 'SSL'; + $cmail->Host = 'ssl://'.SMTP_HOST; + $cmail->Port = 465; + $cmail->Username = SMTP_USER; + $cmail->Password = SMTP_PASS; + $cmail->From = 'sprout@csie.ntu.edu.tw'; + $cmail->FromName = 'Taiwan Online Judge'; + + $cmail->AddAddress($email, $user->nickname); + $cmail->WordWrap = 70; + $cmail->Subject = 'TOJ Password Reset Notice'; + $cmail->IsHTML = true; + $cmail->Body = 'Hi '.$user->nickname.' ('.$user->username.') , your new password is '.$newpass.' .'; + if(!$cmail->Send()) + { + echo($cmail->ErrorInfo.'<br>'); + return false; + } + + + return true; + + $user->password = hash('sha512', $newpass); + $nuser = user::update($sqlc, $user); + if(!$nuser)return false; + + return true; + } +} + +function sec_check_level($sqlc, $lv, $uid = null) +{ + $uidnull = false; + if($uid == null) + { + $uid = intval($_COOKIE['uid']); + $uidnull = true; + } + if($uidnull && !sec_is_login()) + return false; + $user = user::get_from_uid($sqlc, $uid); + return (($user->level & $lv) == $lv); +} + +?> diff --git a/toj/php/user.php b/toj/php/user.php new file mode 100644 index 0000000..4570700 --- /dev/null +++ b/toj/php/user.php @@ -0,0 +1,160 @@ +<?php +//ini_set("display_errors", "On"); +//error_reporting(E_ALL & ~E_NOTICE); + +require_once('user.inc.php'); + +$sqlc = db_connect(); + +$action = $_POST['action']; +$data = $_POST['data']; + +if(strlen($action)==0) + die('Eno_action'); +if($action == 'register') +{ + //Add new user. + //Data: username, password, nickname, email, [aboutme, avatar] + + $user = json_decode($data); + + if(strlen($user->username)<USERNAME_LEN_MIN) + die('Eusername_too_short'); + if(strlen($user->username)>USERNAME_LEN_MAX) + die('Eusername_too_long'); + if(strlen($user->password)<PASSWORD_LEN_MIN) + die('Epassword_too_short'); + if(strlen($user->password)>PASSWORD_LEN_MAX) + die('Epassword_too_long'); + if(strlen($user->nickname)<NICKNAME_LEN_MIN) + die('Enickname_too_short'); + if(strlen($user->nickname)>NICKNAME_LEN_MAX) + die('Enickname_too_long'); + if(strlen($user->email)==0) + die('Eempty_email'); + if(strlen($user->email)>EMAIL_LEN_MAX) + die('Eemail_too_long'); + //if($user->password != $user->passconf) + // die('Epassword_not_match'); + + if(user::get_from_username($sqlc, $user->username) != false) + die('Eusername_exists'); + + $user->password = hash('sha512', $user->password); + + $res = user::add($sqlc, $user); + + if(!$res) + die('Einsert_failed'); + + setcookie('uid', $res->uid, time() + 31536000, '/toj/'); + setcookie('usec', hash('sha512', $res->uid.SEC_SALT), time() + 31536000, '/toj/'); + + echo('S'); +} +if($action == 'update') +{ + //Update exist user + //data: nickname, [aboutme, avatar], [oldpw, password] + + $user = json_decode($data); + + if(!sec_is_login()) + die('Enot_login'); + + $user->uid = $_COOKIE['uid']; + + $olduser = user::get_from_uid($sqlc, $user->uid); + if(!$olduser) + die('Eget_user_failed'); + + if(strlen($user->oldpw)>0) + { + if(strlen($user->password)<PASSWORD_LEN_MIN) + die('Epassword_too_short'); + if(strlen($user->password)>PASSWORD_LEN_MAX) + die('Epassword_too_long'); + //if($user->password != $user->passconf) + // die('Epassword_not_match'); + + $oldhash = hash('sha512', $user->oldpw); + + if($olduser->password != $oldhash) + die('Eold_password_not_match'); + + $user->password = hash('sha512', $user->password); + } + else + { + $user->password = $olduser->password; + } + + if(strlen($user->nickname)<NICKNAME_LEN_MIN) + die('Enickname_too_short'); + if(strlen($user->nickname)>NICKNAME_LEN_MAX) + die('Enickname_too_long'); + if(strlen($user->email)==0) + die('Eempty_email'); + if(strlen($user->email)>EMAIL_LEN_MAX) + die('Eemail_too_long'); + + $res = user::update($sqlc, $user); + if(!$res) + die('Eupdate_failed'); + + echo('S'); +} +if($action == 'view') +{ + //View user data + //data: uid + + $cls = json_decode($data); + + if($cls->uid == null) + { + if(!sec_is_login()) + die('Enot_login_or_please_set_uid'); + $cls->uid = intval($_COOKIE['uid']); + } + $user = user::get_from_uid($sqlc, $cls->uid); + if(!$user) + die('Eget_user_failed'); + + unset($user->password); + if(intval($_COOKIE['uid']) != $user->uid) + unset($user->email); + + echo(json_encode($user)); +} +if($action == 'login') +{ + //Login. + //data: username, password + $login = json_decode($data); + + if(strlen($login->username)==0) + die('Eno_username'); + if(strlen($login->username)>USERNAME_LEN_MAX) + die('Eusername_too_long'); + if(strlen($login->password)==0) + die('Eno_password'); + if(strlen($login->password)>PASSWORD_LEN_MAX) + die('Epassword_too_long'); + + $user = user::get_from_username($sqlc, $login->username); + if(!$user) + die('Euser_not_exist'); + + if(hash('sha512', $login->password) != $user->password) + die('Ewrong_password'); + + setcookie('uid', $user->uid, time() + 31536000, '/toj/'); + setcookie('usec', hash('sha512', $user->uid.SEC_SALT), time() + 31536000, '/toj/'); + + echo('S'); +} + +db_close($sqlc); + +?> |