diff --git a/_DEFAULTconfig.yml b/_DEFAULTconfig.yml index 481788fc..5ca7315a 100644 --- a/_DEFAULTconfig.yml +++ b/_DEFAULTconfig.yml @@ -17,6 +17,7 @@ JUDGE: CONTEST: MODE: false SUBMIT_LIMIT: 15 + VALID_CLASS: ["4"] VALID_IP: ["::ffff:140.112.16.155", "::ffff:140.112.16.156", "::ffff:140.112.16.158", "::1"] # DATABASE Setting, MySQL diff --git a/lib/components/RedisClient.js b/lib/components/RedisClient.js index 0df99fd2..d0bf7dc7 100644 --- a/lib/components/RedisClient.js +++ b/lib/components/RedisClient.js @@ -66,6 +66,32 @@ class RedisClient { }); }); } + scanKeys(pattern) { + return new Promise((resolve, reject) => { + let cursor = '0'; + let keys = []; + + const scan = () => { + this.client.scan(cursor, 'MATCH', pattern, (err, res) => { + if (err) { + reject(err); + return; + } + + cursor = res[0]; + keys = keys.concat(res[1]); + + if (cursor === '0') { + resolve(keys); + } else { + scan(); + } + }); + }; + + scan(); + }); + } } -module.exports = { redisClient: new RedisClient() }; +module.exports = { redisClient: new RedisClient() }; \ No newline at end of file diff --git a/package.json b/package.json index 0b01c924..125f3cd0 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.0.0", "private": true, "scripts": { - "start": "ulimit -n 4096 && NODE_PATH=./ nodejs ./bin/www", + "start": "ulimit -n 4096 && NODE_PATH=./ node ./bin/www", "flush-redis": "redis-cli flushall", "fresh-start": "redis-cli flushall && ulimit -n 4096 && NODE_PATH=./ nodejs ./bin/www", "test": "NODE_PATH=./ NODE_ENV=test mocha --recursive --exit", @@ -11,6 +11,7 @@ "build": "node ./node_modules/gulp/bin/gulp.js build" }, "dependencies": { + "archiver": "^7.0.1", "body-parser": "^1.18.3", "bower": "^1.8.4", "child_process": "^1.0.2", diff --git a/public/runTest.sh b/public/runTest.sh new file mode 100755 index 00000000..d5473cce --- /dev/null +++ b/public/runTest.sh @@ -0,0 +1,29 @@ +#!/bin/bash + +if [ -z "$1" ]; then + echo "Usage: $0 " + exit 1 +fi + +PROGRAM="$1" +EXECUTABLE="${PROGRAM%.c}" + +gcc -std=c99 -O2 -o $EXECUTABLE $PROGRAM +if [ $? -ne 0 ]; then + echo "Compilation failed" + exit 1 +fi + +for infile in *.in; do + outfile="${infile%.in}.out" + my_output="my_${infile%.in}.out" + + ./$EXECUTABLE < $infile > $my_output + + diff -Z $outfile $my_output + if [ $? -eq 0 ]; then + echo "Test $infile: PASS" + else + echo "Test $infile: FAIL" + fi +done diff --git a/routes/index.js b/routes/index.js index 7fe036ab..58c77731 100644 --- a/routes/index.js +++ b/routes/index.js @@ -83,7 +83,7 @@ router.post('/login', function(req, res, next) { let logger = loggerFactory.getLogger(module.id); logger.info(`Login request: (${user["lgn"]}, ${ip})`); - dblink.user.login(user, req.session, function(status) { + dblink.user.login(user, req.session, async function(status) { /* login fail */ if (status == 0) { logger.info('Wrong password.'); @@ -99,8 +99,27 @@ router.post('/login', function(req, res, next) { var filter_ip = iplist.filter(function(valid_ip) { return ip == valid_ip; }); + logger.info(`previous IP : ${filter_ip}`); var isAdmin = req.session['class'] == null; var isValidClass = classlist.includes(req.session['class']); + + const { redisClient } = require('../lib/components/RedisClient'); + + logger.info(`${redisClient.getClient()}`); + const sessionKeys = await redisClient.scanKeys('sess:*'); + + for (const key of sessionKeys) { + const sessionData = await redisClient.getValue(key); + if (sessionData) { + const session = JSON.parse(sessionData); + if (session.uid === uid && session.ip && session.ip !== ip) { + await redisClient.deleteKey(key); + logger.info(`Terminated session from previous IP. Session key: ${key}`); + } + } + } + + req.session.ip = ip; /** enter judge privilege: 1. contest not running diff --git a/routes/submit.js b/routes/submit.js index 8e57b601..32f1a4a6 100644 --- a/routes/submit.js +++ b/routes/submit.js @@ -31,12 +31,8 @@ function submitStep(req, res, uid, pid, cid, lng) { let file_size = 0; if (req.files['code' + i] == null || req.files['code' + i] == undefined || req.files['code' + i][0] == null || req.files['code' + i][0] == undefined) { - if (req.body['paste_code' + i].length > 65536 || req.body['paste_code' + i].trim().length == 0) { - loggerFactory.getLogger(module.id).debug('NOT FOUND FILE ' + i); - return res.redirect(utils.url_for('/')); - } else { - file_size = req.body['paste_code' + i].length; - } + loggerFactory.getLogger(module.id).debug('NOT FOUND FILE ' + i); + return res.redirect(req.headers.referer); } else { file_size = req.files['code' + i][0].size; } diff --git a/routes/testdata.js b/routes/testdata.js index ad240769..1255dfd4 100644 --- a/routes/testdata.js +++ b/routes/testdata.js @@ -1,6 +1,10 @@ var express = require('express'); var router = express.Router(); +const archiver = require('archiver'); +const fs = require('fs'); +const path = require('path'); var dblink = require('../lib/components/dblink'); +var _config = require('../lib/config').config; router.get('/download/:pid', function(req, res, next) { var pid = req.params.pid; @@ -19,6 +23,46 @@ router.get('/download/:pid', function(req, res, next) { }); }); +router.get('/download-all/:pid', (req, res) => { + const pid = req.params.pid; + const testdataDir = path.join(_config.RESOURCE.public.testdata, pid); + const publicDir = path.join(__dirname, '../public'); // Adjust this path if needed + + // Ensure the directory exists + if (!fs.existsSync(testdataDir)) { + return res.status(404).send('Testdata not found.'); + } + + const zipFileName = `p${pid}_testdata.zip`; + const testScriptName = 'runTest.sh'; + + // Set headers to trigger download in browser + res.setHeader('Content-Disposition', `attachment; filename=${zipFileName}`); + res.setHeader('Content-Type', 'application/zip'); + + const archive = archiver('zip', { + zlib: { level: 9 } + }); + + archive.on('error', function(err) { + res.status(500).send({ error: err.message }); + }); + + archive.pipe(res); + + dblink.problemManager.downloadList(pid, function(file_list) { + file_list.forEach(file => { + const filePath = path.join(testdataDir, file); + archive.file(filePath, { name: file }); + }); + if (!fs.existsSync(path.join(testdataDir, testScriptName))) { + archive.file(path.join(publicDir, testScriptName), {name: testScriptName}); + } + archive.finalize(); + }); + +}); + // router.get('/manage', function(req, res, next) { // var uid = req.session.uid; // dblink.helper.isAdmin(uid, function(isadmin) { diff --git a/views/_partial/_problem/problem.ejs b/views/_partial/_problem/problem.ejs index 82badd97..74263afc 100644 --- a/views/_partial/_problem/problem.ejs +++ b/views/_partial/_problem/problem.ejs @@ -226,8 +226,20 @@

Testdata Set

+ + Download All Testdata + + + + +