The ClamAVScanner class is a Spring service that provides functionality to scan files for viruses using a ClamAV server.

It connects to a ClamAV server (configurable host/port, with optional SSL) and streams file data for virus scanning.

It is used to ensure uploaded files are safe and do not contain viruses

 public VirusScanDto scan(final InputStream inputStream) throws IOException {

    Socket socket = null;
    InputStream inStream = null;
    OutputStream outStream = null;
    try {
        if (secureScan)
            socket = SSLSocketFactory.getDefault().createSocket();
        else {
            socket = new Socket();
        }
        socket.connect(new InetSocketAddress(host, port), connectionTimeout);
        socket.setSoTimeout(readTimeout);

        outStream = new BufferedOutputStream(socket.getOutputStream());
        outStream.write("zINSTREAM\0".getBytes(StandardCharsets.UTF_8));
        outStream.flush();

        byte[] buffer = new byte[chunkSize];
        inStream = socket.getInputStream();
        int read = inputStream.read(buffer);

        while (read >= 0) {
            byte[] chunkSize = ByteBuffer.allocate(4).putInt(read).array();
            outStream.write(chunkSize);
            outStream.write(buffer, 0, read);

            if (inStream.available() > 0) {
                byte[] reply = IOUtils.toByteArray(inStream);
                throw new IOException(
                        "Reply from server: " + new String(reply, StandardCharsets.UTF_8));
            }
            read = inputStream.read(buffer);
        }
        outStream.write(new byte[]{0, 0, 0, 0});
        outStream.flush();
        logger.debug("Time require to process file " + (System.currentTimeMillis() - startTime) + " milli sec");

        return populateVirusScanResult(new String(IOUtils.toByteArray(inStream)).trim());
    } catch (IOException e) {
        return new VirusScanDto("CONNECTION_FAILED", e.getMessage());
    } finally {
        try {
            if (Objects.nonNull(inStream)) {
                inStream.close();
            }
            if (Objects.nonNull(outStream)) {
                outStream.flush();
                outStream.close();
            }
            if (socket != null && socket.isConnected()) {
                socket.close();
            }
        } catch (Exception e) {
           System.out.println("Error closing instance, " + e.getMessage());
        }
    }
}

private VirusScanDto populateVirusScanResult(final String result) {
    VirusScanDto scanResult = new VirusScanDto();
    scanResult.setStatus("FAILED");
    scanResult.setResult(result);

    if (result == null || result.isEmpty()) {
        scanResult.setStatus("ERROR");
    } else if (responseOk.equals(result)) {
        scanResult.setStatus("PASSED");
    } else if (result.endsWith(foundSuffix)) {
        scanResult.setSignature(
                result.substring(streamPrefix.length(), result.lastIndexOf(foundSuffix) - 1).trim());
    } else if (result.endsWith(errorSuffix)) {
        scanResult.setStatus("ERROR");
    }
    return scanResult;
}

2 Replies 2

Is there a question here somewhere?

Did you mean to post this on codereview?

Your Reply

By clicking “Post Your Reply”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.