8000 Streaming, and resolved file ref should (only) be file by deboer-tim · Pull Request #1142 · icpctools/icpctools · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Streaming, and resolved file ref should (only) be file #1142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 8 additions & 21 deletions CDS/src/org/icpc/tools/cds/service/ContestRESTService.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.icpc.tools.cds.service;

import io.sentry.Sentry;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
Expand All @@ -20,7 +18,6 @@
import org.icpc.tools.cds.CDSConfig.Auth;
import org.icpc.tools.cds.ConfiguredContest;
import org.icpc.tools.cds.util.HttpHelper;
import org.icpc.tools.cds.video.ReactionVideoRecorder;
import org.icpc.tools.contest.Trace;
import org.icpc.tools.contest.model.IAccount;
import org.icpc.tools.contest.model.IContest;
Expand All @@ -47,6 +44,7 @@
import org.icpc.tools.contest.model.internal.Deletion;
import org.icpc.tools.contest.model.internal.account.IFilteredContest;

import io.sentry.Sentry;
import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
Expand Down Expand Up @@ -422,29 +420,18 @@ protected static boolean doDownload(HttpServletRequest request, HttpServletRespo
}
}

Object ext = obj.resolveFileReference(url);
if (ext == null) {
File f = obj.resolveFileReference(url);
if (f == null) {
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Could not resolve");
return true;
}

if (ext instanceof File) {
cc.incrementDownload();
HttpHelper.sendFile(request, response, (File) ext);
return true;
} else if (ext instanceof String) {
String s = (String) ext;
if ("reaction".equals(s) && obj instanceof ISubmission) {
ISubmission sub = (ISubmission) obj;
cc.incrementDownload();
ReactionVideoRecorder.streamReaction(cc, sub, request, response);
return true;
}

return false;
cc.incrementDownload();
if (obj instanceof ISubmission && url != null && url.contains("reaction")) {
HttpHelper.streamFile(request, response, f);
} else {
HttpHelper.sendFile(request, response, f);
}

response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return true;
}

Expand Down
< 10000 div id="diff-e8b6b7473a218b11981da87ccb2c2077e7951db5c74ebbeb4ffb6851f12dfc87" data-details-container-group="file" class="file js-file js-details-container js-targetable-element show-inline-notes Details Details--on open " data-file-type=".java" data-file-deleted="false" data-tagsearch-path="CDS/src/org/icpc/tools/cds/util/HttpHelper.java" data-targets="diff-file-filter.diffEntries" >
72 changes: 61 additions & 11 deletions CDS/src/org/icpc/tools/cds/util/HttpHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,21 +54,11 @@ public static void sendFile(HttpServletRequest request, HttpServletResponse resp
// ignore, send anyway
}

String name = f.getName();
if (name.endsWith(".jpg") || name.endsWith(".jpeg"))
response.setContentType("image/jpeg");
else if (name.endsWith(".txt") || name.endsWith(".tsv") || name.endsWith(".yaml") || name.endsWith(".xml"))
response.setContentType("text/plain");
else if (name.endsWith(".png"))
response.setContentType("image/png");
else if (name.endsWith(".svg"))
response.setContentType("image/svg+xml");
setCommonHeaders(f.getName(), response);

response.setContentLength((int) f.length());
response.setDateHeader("Last-Modified", lastModified);
response.setHeader("ETag", "e" + lastModified);
response.setHeader("Cache-Control", "max-age=1800"); // 30 minutes
response.setHeader("Content-Disposition", "inline; filename=\"" + name + "\"");

ServletOutputStream out = response.getOutputStream();
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(f));
Expand All @@ -83,6 +73,66 @@ else if (name.endsWith(".svg"))
out.flush();
}

public static void streamFile(HttpServletRequest request, HttpServletResponse response, File f) throws IOException {
if (f == null || !f.exists()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}

File tempFile = new File(f.getParentFile(), f.getName() + "-temp");
if (!tempFile.exists()) {
// not streaming anymore, we can just send the file
sendFile(request, response, f);
return;
}

setCommonHeaders(f.getName(), response);

long start = System.currentTimeMillis();
boolean streaming = true;

ServletOutputStream out = response.getOutputStream();
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(f));
byte[] b = new byte[1024 * 8];
while (streaming) {
if (!tempFile.exists()) {
streaming = false;
try {
Thread.sleep(400);
} catch (Exception e) {
// ignore
}
}

int n = bin.read(b);
while (n != -1) {
out.write(b, 0, n);
n = bin.read(b);
}

// give up after 240s
if (start + 240000L < System.currentTimeMillis())
streaming = false;
}

bin.close();
out.flush();
}

private static void setCommonHeaders(String name, HttpServletResponse response) {
if (name.endsWith(".jpg") || name.endsWith(".jpeg"))
response.setContentType("image/jpeg");
else if (name.endsWith(".txt") || name.endsWith(".tsv") || name.endsWith(".yaml") || name.endsWith(".xml"))
response.setContentType("text/plain");
else if (name.endsWith(".png"))
response.setContentType("image/png");
else if (name.endsWith(".svg"))
response.setContentType("image/svg+xml");

response.setHeader("Cache-Control", "max-age=1800"); // 30 minutes
response.setHeader("Content-Disposition", "inline; filename=\"" + name + "\"");
}

/**
* Sanitize a string to avoid cross-site scripting attacks.
*
Expand Down
116 changes: 0 additions & 116 deletions CDS/src/org/icpc/tools/cds/video/ReactionVideoRecorder.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package org.icpc.tools.cds.video;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
Expand All @@ -27,10 +24,6 @@
import org.icpc.tools.contest.model.internal.FileReferenceList;
import org.icpc.tools.contest.model.internal.Submission;

import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

/**
* Reaction video recorder. Will record webcam and desktop video from when a submission is received
* until 30 seconds after the corresponding judgement. If there is no judgement, recording will be
Expand Down Expand Up @@ -288,113 +281,4 @@ public void run() {
}
}, time, TimeUnit.SECONDS);
}

public static void streamReaction(ConfiguredContest cc, ISubmission submission, HttpServletRequest request,
HttpServletResponse response) throws IOException {
String rootFolder = cc.getPath();
if (rootFolder == null) {
response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
return;
}

if (submission == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}

// security - reject after freeze
final IContest contest = cc.getContest();
if (!cc.isStaff(request) && !contest.isBeforeFreeze(submission)) {
response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
return;
}

VideoHandler handler = VideoAggregator.handler;
String extension = handler.getFileExtension();
File submissionDir = new File(rootFolder, "submissions" + File.separator + submission.getId());
File file = new File(submissionDir, "reaction" + "." + extension); // TODO 3 per team
if (!file.exists()) {
if (cc.isTesting())
file = new File(CDSConfig.getFolder(), "test" + File.separator + "reaction." + extension);

// otherwise, fail
if (!file.exists()) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
}

response.setContentType(handler.getMimeType());
response.setHeader("Content-Disposition",
"inline; filename=\"reaction" + submission.getId() + "." + extension + "\"");

final File tempFile = new File(submissionDir, file.getName() + "-temp");
if (!tempFile.exists()) {
long lastModified = file.lastModified() / 1000 * 1000;
try {
long ifModifiedSince = request.getDateHeader("If-Modified-Since");
if (ifModifiedSince != -1 && ifModifiedSince >= lastModified) {
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
return;
}
} catch (Exception e) {
// ignore, send anyway
}

response.setContentLength((int) file.length());
response.setDateHeader("Last-Modified", lastModified);
}

ServletOutputStream out = response.getOutputStream();
BufferedInputStream bin = new BufferedInputStream(new FileInputStream(file));
byte[] b = new byte[8096];

try {
if (!tempFile.exists()) {
int n = bin.read(b);
while (n != -1) {
out.write(b, 0, n);
n = bin.read(b);
}
} else {
// still recording - stream the file instead
long start = System.currentTimeMillis();
boolean recording = true;
while (recording) {
int n = bin.read(b);
while (n != -1) {
out.write(b, 0, n);
out.flush();
n = bin.read(b);
}

try {
Thread.sleep(400);
} catch (Exception e) {
// ignore
}

if (!tempFile.exists()) {
// try one last time
n = bin.read(b);
while (n != -1) {
out.write(b, 0, n);
n = bin.read(b);
}
recording = false;
}

// give up after 240s
if (start + 240000L < System.currentTimeMillis())
recording = false;
}
}
} finally {
try {
bin.close();
} catch (Exception e) {
// ignore
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.icpc.tools.contest.model;

import java.io.File;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -126,7 +127,7 @@ static IContestObject createByType(ContestType type) {
*/
List<String> validate(IContest contest);

default Object resolveFileReference(String url) {
default File resolveFileReference(String url) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.icpc.tools.contest.model.internal;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
Expand Down Expand Up @@ -81,13 +82,11 @@ public Iterator<FileReference> iterator() {
return refs.iterator();
}

public Object resolve(String url) {
public File resolve(String url) {
for (FileReference ref : refs) {
if (ref.getURL().endsWith(url)) {
if (ref.file != null && ref.file.exists())
return ref.file;

return ref.data;
}
}
return null;
Expand All @@ -111,12 +110,12 @@ public String[] getRefs() {
return s;
}

public static Object resolve(String url, FileReferenceList... lists) {
public static File resolve(String url, FileReferenceList... lists) {
for (FileReferenceList list : lists) {
if (list != null) {
Object obj = list.resolve(url);
if (obj != null)
return obj;
File f = list.resolve(url);
if (f != null)
return f;
}
}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public void setLogo(FileReferenceList list) {
}

@Override
public Object resolveFileReference(String url2) {
public File resolveFileReference(String url2) {
return FileReferenceList.resolve(url2, logo);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ public BufferedImage getBannerImage(int width, int height, boolean forceLoad, bo
}

@Override
public Object resolveFileReference(String url) {
public File resolveFileReference(String url) {
return FileReferenceList.resolve(url, logo, banner);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ public void setCountrySubdivisionFlag(FileReferenceList list) {
}

@Override
public Object resolveFileReference(String url2) {
public File resolveFileReference(String url2) {
return FileReferenceList.resolve(url2, logo, countryFlag);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ public void setPhoto(FileReferenceList list) {
}

@Override
public Object resolveFileReference(String url) {
public File resolveFileReference(String url) {
return FileReferenceList.resolve(url, photo);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ public List<String> validate(IContest c) {
}

@Override
public Object resolveFileReference(String url2) {
public File resolveFileReference(String url2) {
return FileReferenceList.resolve(url2, statement, package_);
}
}
Loading
0