Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
2302632f11 | |||
a8c36a64b7 | |||
a810338cc4 | |||
c5049d5155 | |||
6ddcfc8d90 | |||
a2d8d1cbfd | |||
6adfcc2201 | |||
6300843616 |
BIN
.serena/cache/typescript/document_symbols_cache_v23-06-25.pkl
vendored
Normal file
BIN
.serena/cache/typescript/document_symbols_cache_v23-06-25.pkl
vendored
Normal file
Binary file not shown.
35
.serena/memories/code_style_conventions.md
Normal file
35
.serena/memories/code_style_conventions.md
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Code Style and Conventions
|
||||||
|
|
||||||
|
## Naming Conventions
|
||||||
|
- **Interfaces**: Prefix with `I` (e.g., `IUserData`)
|
||||||
|
- **Types**: Prefix with `T` (e.g., `TResponseType`)
|
||||||
|
- **Files**: Always lowercase (e.g., `classes.clamavservice.ts`)
|
||||||
|
- **Classes**: PascalCase (e.g., `ClamAvService`)
|
||||||
|
- **Methods/Functions**: camelCase (e.g., `scanBuffer`)
|
||||||
|
- Avoid ENums when possible
|
||||||
|
|
||||||
|
## TypeScript Patterns
|
||||||
|
- TypeScript-first approach with full type safety
|
||||||
|
- ES modules (type: "module" in package.json)
|
||||||
|
- Import dependencies in `ts/plugins.ts`
|
||||||
|
- Reference with full path: `plugins.myModule.myClass()`
|
||||||
|
|
||||||
|
## File Organization
|
||||||
|
- Source code in `ts/` directory
|
||||||
|
- Tests in `test/` directory
|
||||||
|
- Distribution in `dist_ts/` directory
|
||||||
|
- Use `.js` extensions in imports for ES modules
|
||||||
|
|
||||||
|
## Testing Patterns
|
||||||
|
- Use @git.zone/tstest framework
|
||||||
|
- Import expect from @push.rocks/tapbundle
|
||||||
|
- Test files end with `export default tap.start()`
|
||||||
|
- Test naming: `*.both.ts`, `*.node.ts`, `*.browser.ts`
|
||||||
|
- EICAR test string for antivirus verification
|
||||||
|
|
||||||
|
## General Principles
|
||||||
|
- Make RAZOR SHARP changes - every modification must be goal-oriented
|
||||||
|
- Improve elegance - changes should enhance clarity and maintainability
|
||||||
|
- Preserve necessary complexity - don't oversimplify
|
||||||
|
- Keep async patterns - maintain Promises where they add value
|
||||||
|
- Remove redundancy carefully while preserving functionality
|
31
.serena/memories/project_overview.md
Normal file
31
.serena/memories/project_overview.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# SmartAntivirus Project Overview
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
SmartAntivirus (@push.rocks/smartantivirus) is a Node.js/TypeScript library that provides enterprise-grade antivirus scanning capabilities by integrating with ClamAV. It allows developers to scan files, buffers, strings, and streams for viruses in their applications.
|
||||||
|
|
||||||
|
## Tech Stack
|
||||||
|
- TypeScript (primary language)
|
||||||
|
- Node.js (runtime)
|
||||||
|
- ClamAV (antivirus engine)
|
||||||
|
- Docker (for containerized ClamAV deployment)
|
||||||
|
- Testing: @git.zone/tstest with @push.rocks/tapbundle
|
||||||
|
- Build: @git.zone/tsbuild
|
||||||
|
|
||||||
|
## Architecture
|
||||||
|
- **ClamAvService**: High-level interface for virus scanning operations
|
||||||
|
- Scan strings, buffers, Node.js streams, and Web Streams
|
||||||
|
- Auto-manages Docker container if needed
|
||||||
|
- Connects to ClamAV daemon on port 3310
|
||||||
|
|
||||||
|
- **ClamAVManager**: Low-level Docker container management
|
||||||
|
- Handles container lifecycle (start/stop)
|
||||||
|
- Updates virus definitions
|
||||||
|
- Provides log monitoring
|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
- In-memory scanning without disk I/O
|
||||||
|
- Stream processing for large files
|
||||||
|
- TypeScript-first with full type safety
|
||||||
|
- Zero-config with sensible defaults
|
||||||
|
- Auto-updating virus definitions
|
||||||
|
- Docker-based or direct daemon connection
|
31
.serena/memories/suggested_commands.md
Normal file
31
.serena/memories/suggested_commands.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
# Suggested Commands for SmartAntivirus Development
|
||||||
|
|
||||||
|
## Build & Test Commands
|
||||||
|
- `pnpm test` - Run test suite with tapbundle
|
||||||
|
- `pnpm build` - Build TypeScript to JavaScript (uses tsbuild)
|
||||||
|
- `pnpm run buildDocs` - Generate documentation (tsdoc)
|
||||||
|
|
||||||
|
## Development Tools
|
||||||
|
- `tsbuild check test/**/* --skiplibcheck` - Type-check test files
|
||||||
|
- `tsx test/test.ts` - Run individual test file directly
|
||||||
|
|
||||||
|
## Version Control
|
||||||
|
- `git mv <old> <new>` - Move/rename files preserving history
|
||||||
|
- `git status` - Check current changes
|
||||||
|
- `git diff` - View uncommitted changes
|
||||||
|
|
||||||
|
## Package Management
|
||||||
|
- `pnpm install` - Install dependencies
|
||||||
|
- `pnpm install --save-dev <package>` - Add dev dependency
|
||||||
|
- `pnpm add <package>` - Add production dependency
|
||||||
|
|
||||||
|
## File Operations
|
||||||
|
- `ls` - List directory contents
|
||||||
|
- `cat <file>` - View file contents
|
||||||
|
- `find . -name "*.ts"` - Find TypeScript files
|
||||||
|
- `rg <pattern>` - Search codebase with ripgrep
|
||||||
|
|
||||||
|
## Docker Management (if testing locally)
|
||||||
|
- `docker ps` - List running containers
|
||||||
|
- `docker logs clamav` - View ClamAV container logs
|
||||||
|
- `docker stop clamav` - Stop ClamAV container
|
44
.serena/memories/task_completion_workflow.md
Normal file
44
.serena/memories/task_completion_workflow.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# Task Completion Workflow
|
||||||
|
|
||||||
|
## Required Steps After Making Code Changes
|
||||||
|
|
||||||
|
1. **Build the Project**
|
||||||
|
```bash
|
||||||
|
pnpm build
|
||||||
|
```
|
||||||
|
Ensures TypeScript compiles without errors
|
||||||
|
|
||||||
|
2. **Run Tests**
|
||||||
|
```bash
|
||||||
|
pnpm test
|
||||||
|
```
|
||||||
|
Verifies functionality with test suite
|
||||||
|
|
||||||
|
3. **Type Check Test Files** (if tests were modified)
|
||||||
|
```bash
|
||||||
|
tsbuild check test/**/* --skiplibcheck
|
||||||
|
```
|
||||||
|
|
||||||
|
## Quality Checks
|
||||||
|
- Verify no TypeScript compilation errors
|
||||||
|
- Ensure all tests pass
|
||||||
|
- Check that new code follows existing patterns
|
||||||
|
- Verify imports use `.js` extensions for ES modules
|
||||||
|
- Confirm no hardcoded values that should be configurable
|
||||||
|
|
||||||
|
## Documentation Updates
|
||||||
|
- Update readme.md if API changes
|
||||||
|
- Add JSDoc comments for new public methods
|
||||||
|
- Update changelog.md for version changes
|
||||||
|
|
||||||
|
## Before Committing
|
||||||
|
- NEVER commit without explicit user approval
|
||||||
|
- Use `git status` to review changes
|
||||||
|
- Use `git diff` to verify modifications
|
||||||
|
- Create focused commits with clear messages
|
||||||
|
- Never commit secrets or API keys
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
- The project uses pnpm exclusively (not npm or yarn)
|
||||||
|
- Always read documentation before using unfamiliar APIs
|
||||||
|
- Check existing code patterns before implementing new features
|
68
.serena/project.yml
Normal file
68
.serena/project.yml
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
# language of the project (csharp, python, rust, java, typescript, go, cpp, or ruby)
|
||||||
|
# * For C, use cpp
|
||||||
|
# * For JavaScript, use typescript
|
||||||
|
# Special requirements:
|
||||||
|
# * csharp: Requires the presence of a .sln file in the project folder.
|
||||||
|
language: typescript
|
||||||
|
|
||||||
|
# whether to use the project's gitignore file to ignore files
|
||||||
|
# Added on 2025-04-07
|
||||||
|
ignore_all_files_in_gitignore: true
|
||||||
|
# list of additional paths to ignore
|
||||||
|
# same syntax as gitignore, so you can use * and **
|
||||||
|
# Was previously called `ignored_dirs`, please update your config if you are using that.
|
||||||
|
# Added (renamed) on 2025-04-07
|
||||||
|
ignored_paths: []
|
||||||
|
|
||||||
|
# whether the project is in read-only mode
|
||||||
|
# If set to true, all editing tools will be disabled and attempts to use them will result in an error
|
||||||
|
# Added on 2025-04-18
|
||||||
|
read_only: false
|
||||||
|
|
||||||
|
|
||||||
|
# list of tool names to exclude. We recommend not excluding any tools, see the readme for more details.
|
||||||
|
# Below is the complete list of tools for convenience.
|
||||||
|
# To make sure you have the latest list of tools, and to view their descriptions,
|
||||||
|
# execute `uv run scripts/print_tool_overview.py`.
|
||||||
|
#
|
||||||
|
# * `activate_project`: Activates a project by name.
|
||||||
|
# * `check_onboarding_performed`: Checks whether project onboarding was already performed.
|
||||||
|
# * `create_text_file`: Creates/overwrites a file in the project directory.
|
||||||
|
# * `delete_lines`: Deletes a range of lines within a file.
|
||||||
|
# * `delete_memory`: Deletes a memory from Serena's project-specific memory store.
|
||||||
|
# * `execute_shell_command`: Executes a shell command.
|
||||||
|
# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced.
|
||||||
|
# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type).
|
||||||
|
# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type).
|
||||||
|
# * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes.
|
||||||
|
# * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file.
|
||||||
|
# * `initial_instructions`: Gets the initial instructions for the current project.
|
||||||
|
# Should only be used in settings where the system prompt cannot be set,
|
||||||
|
# e.g. in clients you have no control over, like Claude Desktop.
|
||||||
|
# * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol.
|
||||||
|
# * `insert_at_line`: Inserts content at a given line in a file.
|
||||||
|
# * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol.
|
||||||
|
# * `list_dir`: Lists files and directories in the given directory (optionally with recursion).
|
||||||
|
# * `list_memories`: Lists memories in Serena's project-specific memory store.
|
||||||
|
# * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building).
|
||||||
|
# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context).
|
||||||
|
# * `read_file`: Reads a file within the project directory.
|
||||||
|
# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store.
|
||||||
|
# * `remove_project`: Removes a project from the Serena configuration.
|
||||||
|
# * `replace_lines`: Replaces a range of lines within a file with new content.
|
||||||
|
# * `replace_symbol_body`: Replaces the full definition of a symbol.
|
||||||
|
# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen.
|
||||||
|
# * `search_for_pattern`: Performs a search for a pattern in the project.
|
||||||
|
# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase.
|
||||||
|
# * `switch_modes`: Activates modes by providing a list of their names
|
||||||
|
# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information.
|
||||||
|
# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task.
|
||||||
|
# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed.
|
||||||
|
# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store.
|
||||||
|
excluded_tools: []
|
||||||
|
|
||||||
|
# initial prompt for the project. It will always be given to the LLM upon activating the project
|
||||||
|
# (contrary to the memories, which are loaded on demand).
|
||||||
|
initial_prompt: ""
|
||||||
|
|
||||||
|
project_name: "smartantivirus"
|
31
changelog.md
31
changelog.md
@@ -1,5 +1,36 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 2025-08-16 - 1.3.2 - fix(build)
|
||||||
|
Bump dependencies, improve test/build scripts, expand documentation and add project metadata
|
||||||
|
|
||||||
|
- Updated devDependencies: bumped @git.zone/tsbuild, @git.zone/tsbundle, @git.zone/tstest, @push.rocks/tapbundle, @types/node and typescript to newer versions.
|
||||||
|
- Updated runtime dependencies: bumped @push.rocks/smartfile, @push.rocks/smartpath and axios; tar version updated.
|
||||||
|
- Adjusted npm scripts: test now runs with '(tstest test/ --web --verbose --logfile --timeout 120)'; build and docs scripts unchanged in behavior.
|
||||||
|
- Added packageManager entry (pnpm) and a pnpm-workspace.yaml with onlyBuiltDependencies configured.
|
||||||
|
- Expanded and rewrote README with detailed quick start, examples, API reference and troubleshooting guidance.
|
||||||
|
- Added local assistant/IDE metadata and memories (.claude/settings.local.json and .serena/*) to aid development tooling and project onboarding.
|
||||||
|
|
||||||
|
## 2025-02-07 - 1.3.1 - fix(core)
|
||||||
|
Updated descriptions and keywords in package.json and npmextra.json. Improved README content for usage clarity.
|
||||||
|
|
||||||
|
- Revised package.json description and keywords to better represent the project's features.
|
||||||
|
- Enhanced npmextra.json with updated module attributes.
|
||||||
|
- Improved README with clearer instructions and examples for using ClamAVManager and ClamAvService.
|
||||||
|
- Fixed incorrect import path in test.clamav.manager.ts.
|
||||||
|
|
||||||
|
## 2025-02-05 - 1.3.0 - feat(ClamAvService)
|
||||||
|
Add support for enhanced streaming methods in ClamAvService
|
||||||
|
|
||||||
|
- Add methods to ClamAvService: scanStream for NodeJS streams, scanWebStream for Web API streams, and scanFileFromWebAsStream for fetching and scanning files from URLs.
|
||||||
|
- Update usage examples in readme for new streaming methods.
|
||||||
|
|
||||||
|
## 2025-02-05 - 1.2.0 - feat(ClamAvService)
|
||||||
|
Add stream scanning methods to ClamAvService
|
||||||
|
|
||||||
|
- Added scanStream method to support scanning NodeJS streams directly.
|
||||||
|
- Introduced scanWebStream method for scanning web resources as streams.
|
||||||
|
- Integrated stream scanning into existing ClamAvService class.
|
||||||
|
|
||||||
## 2025-02-03 - 1.1.2 - fix(documentation)
|
## 2025-02-03 - 1.1.2 - fix(documentation)
|
||||||
Update readme with additional legal and trademark information
|
Update readme with additional legal and trademark information
|
||||||
|
|
||||||
|
@@ -5,21 +5,23 @@
|
|||||||
"githost": "code.foss.global",
|
"githost": "code.foss.global",
|
||||||
"gitscope": "push.rocks",
|
"gitscope": "push.rocks",
|
||||||
"gitrepo": "smartantivirus",
|
"gitrepo": "smartantivirus",
|
||||||
"description": "A Node.js package for integrating antivirus scanning capabilities using ClamAV, allowing in-memory file and data scanning.",
|
"description": "A Node.js package providing integration with ClamAV for anti-virus scanning, facilitating both Docker containerized management and direct connection to a ClamAV daemon.",
|
||||||
"npmPackagename": "@push.rocks/smartantivirus",
|
"npmPackagename": "@push.rocks/smartantivirus",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"projectDomain": "push.rocks",
|
"projectDomain": "push.rocks",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"antivirus",
|
"antivirus",
|
||||||
"ClamAV",
|
|
||||||
"Node.js",
|
"Node.js",
|
||||||
|
"ClamAV",
|
||||||
"virus scanning",
|
"virus scanning",
|
||||||
"security",
|
"security",
|
||||||
"buffer scanning",
|
"Docker",
|
||||||
|
"in-memory scanning",
|
||||||
|
"file scanning",
|
||||||
|
"stream scanning",
|
||||||
"data protection",
|
"data protection",
|
||||||
"HTTP requests",
|
"network security",
|
||||||
"file handling",
|
"buffer scanning",
|
||||||
"network communication",
|
|
||||||
"software testing"
|
"software testing"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
40
package.json
40
package.json
@@ -1,31 +1,32 @@
|
|||||||
{
|
{
|
||||||
"name": "@push.rocks/smartantivirus",
|
"name": "@push.rocks/smartantivirus",
|
||||||
"version": "1.1.2",
|
"version": "1.3.2",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "A Node.js package for integrating antivirus scanning capabilities using ClamAV, allowing in-memory file and data scanning.",
|
"description": "A Node.js package providing integration with ClamAV for anti-virus scanning, facilitating both Docker containerized management and direct connection to a ClamAV daemon.",
|
||||||
"main": "dist_ts/index.js",
|
"main": "dist_ts/index.js",
|
||||||
"typings": "dist_ts/index.d.ts",
|
"typings": "dist_ts/index.d.ts",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"author": "Task Venture Capital GmbH",
|
"author": "Task Venture Capital GmbH",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"test": "(tstest test/ --web)",
|
"test": "(tstest test/ --web --verbose --logfile --timeout 120)",
|
||||||
"build": "(tsbuild --web --allowimplicitany)",
|
"build": "(tsbuild --web --allowimplicitany)",
|
||||||
"buildDocs": "(tsdoc)"
|
"buildDocs": "(tsdoc)"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@git.zone/tsbuild": "^2.1.25",
|
"@git.zone/tsbuild": "^2.6.4",
|
||||||
"@git.zone/tsbundle": "^2.0.5",
|
"@git.zone/tsbundle": "^2.5.1",
|
||||||
"@git.zone/tsrun": "^1.2.46",
|
"@git.zone/tsrun": "^1.2.46",
|
||||||
"@git.zone/tstest": "^1.0.44",
|
"@git.zone/tstest": "^2.3.4",
|
||||||
"@push.rocks/tapbundle": "^5.0.15",
|
"@push.rocks/tapbundle": "^6.0.3",
|
||||||
"@types/node": "^20.8.7",
|
"@types/node": "^24.3.0",
|
||||||
"typescript": "^5.7.3"
|
"typescript": "^5.9.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@push.rocks/smartfile": "^11.1.5",
|
"@push.rocks/smartfile": "^11.2.5",
|
||||||
"@push.rocks/smartpath": "^5.0.18",
|
"@push.rocks/smartpath": "^6.0.0",
|
||||||
"axios": "^1.7.9",
|
"@push.rocks/smartstream": "^3.2.5",
|
||||||
|
"axios": "^1.11.0",
|
||||||
"tar": "^7.4.3"
|
"tar": "^7.4.3"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
@@ -50,15 +51,18 @@
|
|||||||
],
|
],
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"antivirus",
|
"antivirus",
|
||||||
"ClamAV",
|
|
||||||
"Node.js",
|
"Node.js",
|
||||||
|
"ClamAV",
|
||||||
"virus scanning",
|
"virus scanning",
|
||||||
"security",
|
"security",
|
||||||
"buffer scanning",
|
"Docker",
|
||||||
|
"in-memory scanning",
|
||||||
|
"file scanning",
|
||||||
|
"stream scanning",
|
||||||
"data protection",
|
"data protection",
|
||||||
"HTTP requests",
|
"network security",
|
||||||
"file handling",
|
"buffer scanning",
|
||||||
"network communication",
|
|
||||||
"software testing"
|
"software testing"
|
||||||
]
|
],
|
||||||
|
"packageManager": "pnpm@10.14.0+sha512.ad27a79641b49c3e481a16a805baa71817a04bbe06a38d17e60e2eaee83f6a146c6a688125f5792e48dd5ba30e7da52a5cda4c3992b9ccf333f9ce223af84748"
|
||||||
}
|
}
|
||||||
|
5000
pnpm-lock.yaml
generated
5000
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
4
pnpm-workspace.yaml
Normal file
4
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
onlyBuiltDependencies:
|
||||||
|
- esbuild
|
||||||
|
- mongodb-memory-server
|
||||||
|
- puppeteer
|
430
readme.md
430
readme.md
@@ -1,226 +1,306 @@
|
|||||||
# @push.rocks/smartantivirus
|
# @push.rocks/smartantivirus 🛡️
|
||||||
|
|
||||||
A package for performing antivirus testing with ClamAV, featuring both direct daemon communication and Docker container management.
|
**Enterprise-grade antivirus scanning for Node.js applications** - Seamlessly integrate ClamAV's powerful virus detection into your TypeScript/JavaScript projects with zero hassle.
|
||||||
|
|
||||||
## Features
|
## Why SmartAntivirus? 🚀
|
||||||
|
|
||||||
- **Docker Integration**: Automatically manages ClamAV containers for easy setup and testing
|
In today's digital landscape, security is paramount. Whether you're building a file-sharing platform, processing user uploads, or handling sensitive data streams, you need reliable virus protection that just works. SmartAntivirus gives you:
|
||||||
- **Real-time Logging**: Captures and processes ClamAV logs with type-safe event handling
|
|
||||||
- **Database Management**: Supports automatic database updates and version tracking
|
- **🐳 Docker-based or Direct Connection** - Choose your deployment style
|
||||||
- **Flexible Scanning**: Scan strings, buffers, and files for malware
|
- **⚡ In-memory Scanning** - Lightning-fast scanning without disk I/O
|
||||||
- **Health Monitoring**: Built-in service readiness checks and connection verification
|
- **🌊 Stream Processing** - Scan data on-the-fly as it flows through your app
|
||||||
|
- **🎯 TypeScript First** - Full type safety and IntelliSense support
|
||||||
|
- **📦 Zero Config** - Works out of the box with sensible defaults
|
||||||
|
- **🔄 Auto-updating** - Virus definitions stay current automatically
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
Installing `@push.rocks/smartantivirus` is straightforward. You'll need Node.js and npm installed on your machine:
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install @push.rocks/smartantivirus
|
npm install @push.rocks/smartantivirus
|
||||||
```
|
```
|
||||||
|
|
||||||
### Prerequisites
|
Or if you're using pnpm (recommended):
|
||||||
|
|
||||||
- Node.js and npm
|
```bash
|
||||||
- Docker (for container-based usage)
|
pnpm add @push.rocks/smartantivirus
|
||||||
- ClamAV daemon (for direct daemon usage)
|
```
|
||||||
|
|
||||||
## Usage
|
## Quick Start 🏃♂️
|
||||||
|
|
||||||
The package provides two main ways to use ClamAV:
|
### The 5-Minute Setup
|
||||||
|
|
||||||
1. **Docker-based Usage** (Recommended): Uses `ClamAVManager` to automatically handle container lifecycle
|
```typescript
|
||||||
2. **Direct Daemon Usage**: Uses `ClamAvService` to communicate with an existing ClamAV daemon
|
import { ClamAvService } from '@push.rocks/smartantivirus';
|
||||||
|
|
||||||
Below is a comprehensive guide on how to use both approaches.
|
// That's it! The service automatically manages a Docker container
|
||||||
|
const scanner = new ClamAvService();
|
||||||
|
|
||||||
### Docker-based Usage with ClamAVManager
|
// Scan a suspicious string
|
||||||
|
const result = await scanner.scanString('Is this text safe?');
|
||||||
|
console.log(result.isInfected ? '⚠️ Threat detected!' : '✅ All clear!');
|
||||||
|
|
||||||
The `ClamAVManager` class provides a high-level interface for managing ClamAV in Docker containers:
|
// Scan a buffer
|
||||||
|
const fileBuffer = await fs.readFile('./upload.pdf');
|
||||||
|
const scanResult = await scanner.scanBuffer(fileBuffer);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Core Concepts 💡
|
||||||
|
|
||||||
|
SmartAntivirus provides two main classes:
|
||||||
|
|
||||||
|
### 🎯 ClamAvService
|
||||||
|
The high-level interface for virus scanning. It handles all the complexity behind a simple, intuitive API.
|
||||||
|
|
||||||
|
### 🐳 ClamAVManager
|
||||||
|
Low-level Docker container management for advanced use cases. Most users won't need to interact with this directly.
|
||||||
|
|
||||||
|
## Real-World Examples 🌍
|
||||||
|
|
||||||
|
### Protecting File Uploads
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ClamAvService } from '@push.rocks/smartantivirus';
|
||||||
|
import express from 'express';
|
||||||
|
import multer from 'multer';
|
||||||
|
|
||||||
|
const app = express();
|
||||||
|
const scanner = new ClamAvService();
|
||||||
|
const upload = multer({ storage: multer.memoryStorage() });
|
||||||
|
|
||||||
|
app.post('/upload', upload.single('file'), async (req, res) => {
|
||||||
|
try {
|
||||||
|
// Scan the uploaded file buffer
|
||||||
|
const result = await scanner.scanBuffer(req.file.buffer);
|
||||||
|
|
||||||
|
if (result.isInfected) {
|
||||||
|
return res.status(400).json({
|
||||||
|
error: 'File rejected',
|
||||||
|
threat: result.reason
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// File is safe, proceed with storage
|
||||||
|
await saveFile(req.file);
|
||||||
|
res.json({ message: 'File uploaded successfully' });
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).json({ error: 'Scan failed' });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
### Streaming Large Files
|
||||||
|
|
||||||
|
Never load huge files into memory! Stream them instead:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ClamAvService } from '@push.rocks/smartantivirus';
|
||||||
|
import { createReadStream } from 'fs';
|
||||||
|
|
||||||
|
const scanner = new ClamAvService();
|
||||||
|
|
||||||
|
async function scanLargeFile(filePath: string) {
|
||||||
|
const stream = createReadStream(filePath);
|
||||||
|
const result = await scanner.scanStream(stream);
|
||||||
|
|
||||||
|
if (result.isInfected) {
|
||||||
|
console.log(`🚨 Threat found: ${result.reason}`);
|
||||||
|
// Quarantine or delete the file
|
||||||
|
} else {
|
||||||
|
console.log('✅ File is clean');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Scanning Remote Content
|
||||||
|
|
||||||
|
Perfect for proxies, CDNs, or content moderation:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const scanner = new ClamAvService();
|
||||||
|
|
||||||
|
// Scan a file from a URL
|
||||||
|
const result = await scanner.scanFileFromWebAsStream('https://example.com/document.pdf');
|
||||||
|
|
||||||
|
// For browser environments using Web Streams API
|
||||||
|
async function scanInBrowser(url: string) {
|
||||||
|
const response = await fetch(url);
|
||||||
|
const webStream = response.body as ReadableStream<Uint8Array>;
|
||||||
|
|
||||||
|
if (webStream) {
|
||||||
|
const result = await scanner.scanWebStream(webStream);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Advanced Container Management
|
||||||
|
|
||||||
|
For production environments requiring fine-grained control:
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { ClamAVManager } from '@push.rocks/smartantivirus';
|
import { ClamAVManager } from '@push.rocks/smartantivirus';
|
||||||
|
|
||||||
async function main() {
|
class AntivirusService {
|
||||||
// Create a new manager instance
|
private manager: ClamAVManager;
|
||||||
const manager = new ClamAVManager();
|
|
||||||
|
|
||||||
// Start the ClamAV container
|
|
||||||
await manager.startContainer();
|
|
||||||
|
|
||||||
// Listen for log events
|
|
||||||
manager.on('log', (event) => {
|
|
||||||
console.log(`[ClamAV ${event.type}] ${event.message}`);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get database information
|
|
||||||
const dbInfo = await manager.getDatabaseInfo();
|
|
||||||
console.log('Database Info:', dbInfo);
|
|
||||||
|
|
||||||
// Update virus definitions
|
|
||||||
await manager.updateDatabase();
|
|
||||||
|
|
||||||
// When done, stop the container
|
|
||||||
await manager.stopContainer();
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch(console.error);
|
|
||||||
```
|
|
||||||
|
|
||||||
### Direct Daemon Usage with ClamAvService
|
|
||||||
|
|
||||||
The primary interface provided by the package is the `ClamAvService` class. It allows you to scan data in memory or verify the connection to the ClamAV daemon.
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { ClamAvService } from '@push.rocks/smartantivirus';
|
|
||||||
|
|
||||||
async function main() {
|
|
||||||
const clamService = new ClamAvService('127.0.0.1', 3310); // Replace with your ClamAV host and port
|
|
||||||
|
|
||||||
// Verify connection to ClamAV
|
|
||||||
const isConnected = await clamService.verifyConnection();
|
|
||||||
console.log(`Connection to ClamAV: ${isConnected ? 'successful' : 'failed'}`);
|
|
||||||
|
|
||||||
if (!isConnected) {
|
|
||||||
console.error('Could not connect to ClamAV daemon. Please check your configuration.');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan a text string
|
|
||||||
const testString = 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*';
|
|
||||||
const scanResult = await clamService.scanString(testString);
|
|
||||||
console.log('Scan Result:', scanResult);
|
|
||||||
}
|
|
||||||
|
|
||||||
main().catch(console.error);
|
|
||||||
```
|
|
||||||
|
|
||||||
**Breaking Down the Example:**
|
|
||||||
|
|
||||||
1. **Initialization**: We start by creating an instance of the `ClamAvService` class. It takes two optional parameters: the host and port where your ClamAV daemon is running. By default, it assumes `127.0.0.1` and `3310`.
|
|
||||||
|
|
||||||
2. **Verify Connection**: The `verifyConnection` method is called to ensure that our application can communicate with the ClamAV daemon. It returns a promise that resolves to `true` if the connection is successful, and `false` otherwise.
|
|
||||||
|
|
||||||
3. **Scan Strings**: We utilize the `scanString` method to scan a text string (in this example, the EICAR test virus string is used). This method converts the string to a buffer and sends it to the ClamAV daemon for scanning.
|
|
||||||
|
|
||||||
### Handling Buffers
|
|
||||||
|
|
||||||
Below is an example demonstrating scanning raw binary data in the form of buffers:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
import { ClamAvService } from '@push.rocks/smartantivirus';
|
|
||||||
|
|
||||||
async function scanBufferExample() {
|
|
||||||
const clamService = new ClamAvService();
|
|
||||||
|
|
||||||
// This buffer should represent the binary data you want to scan.
|
|
||||||
const buffer = Buffer.from('Sample buffer contents', 'utf8');
|
|
||||||
|
|
||||||
try {
|
|
||||||
const scanResult = await clamService.scanBuffer(buffer);
|
|
||||||
console.log('Buffer Scan Result:', scanResult);
|
|
||||||
} catch (error) {
|
|
||||||
console.error('Error scanning buffer:', error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scanBufferExample();
|
|
||||||
```
|
|
||||||
|
|
||||||
**Explanation:**
|
|
||||||
|
|
||||||
- We create an instance of `ClamAvService`.
|
|
||||||
- A buffer is created and passed to the `scanBuffer` method, which scans the in-memory data for potential viruses.
|
|
||||||
|
|
||||||
### Error Handling and Debugging
|
|
||||||
|
|
||||||
Both `ClamAVManager` and `ClamAvService` provide comprehensive error handling:
|
|
||||||
|
|
||||||
```typescript
|
|
||||||
try {
|
|
||||||
// Using ClamAVManager
|
|
||||||
const manager = new ClamAVManager();
|
|
||||||
await manager.startContainer();
|
|
||||||
|
|
||||||
// Listen for errors in logs
|
async initialize() {
|
||||||
manager.on('log', (event) => {
|
this.manager = new ClamAVManager();
|
||||||
if (event.type === 'error') {
|
|
||||||
console.error(`ClamAV Error: ${event.message}`);
|
// Start the container
|
||||||
}
|
await this.manager.startContainer();
|
||||||
});
|
|
||||||
|
// Set up log monitoring
|
||||||
// Using ClamAvService
|
this.manager.on('log', (event) => {
|
||||||
const service = new ClamAvService();
|
if (event.type === 'error') {
|
||||||
const scanResult = await service.scanString('Some suspicious string...');
|
console.error(`ClamAV Error: ${event.message}`);
|
||||||
console.log(`Infection Status: ${scanResult.isInfected ? 'Infected' : 'Clean'}`);
|
// Send to your logging service
|
||||||
if (scanResult.isInfected) {
|
}
|
||||||
console.log(`Reason: ${scanResult.reason}`);
|
});
|
||||||
|
|
||||||
|
// Update virus definitions
|
||||||
|
await this.manager.updateDatabase();
|
||||||
|
|
||||||
|
// Get database info
|
||||||
|
const dbInfo = await this.manager.getDatabaseInfo();
|
||||||
|
console.log(`Virus DB Version: ${dbInfo}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async shutdown() {
|
||||||
|
await this.manager.stopContainer();
|
||||||
}
|
}
|
||||||
} catch (error) {
|
|
||||||
console.error('An error occurred during the scanning process:', error);
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Testing your setup
|
## Testing 🧪
|
||||||
|
|
||||||
A preconfigured test script is provided, which demonstrates how to use the package with the Tap bundle testing framework. You can find the test script in `test/test.ts`. This is configured to run with the default `@push.rocks/tapbundle` setup:
|
We use the industry-standard EICAR test string for verification:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { ClamAvService } from '@push.rocks/smartantivirus';
|
||||||
|
|
||||||
|
const scanner = new ClamAvService();
|
||||||
|
|
||||||
|
// This is the EICAR test string - it's harmless but triggers antivirus
|
||||||
|
const EICAR = 'X5O!P%@AP[4\\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*';
|
||||||
|
|
||||||
|
const result = await scanner.scanString(EICAR);
|
||||||
|
console.log(result.isInfected); // true
|
||||||
|
console.log(result.reason); // 'Eicar-Test-Signature'
|
||||||
|
```
|
||||||
|
|
||||||
|
Run the test suite:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run test
|
npm test
|
||||||
```
|
```
|
||||||
|
|
||||||
The tests include creating and utilizing a `ClamAvService` instance and attempts to scan the well-known EICAR test string. They ensure that the basic functionality of the package is working as intended.
|
## API Reference 📚
|
||||||
|
|
||||||
### Advanced Usage and Integration
|
### ClamAvService
|
||||||
|
|
||||||
#### Container Configuration
|
|
||||||
|
|
||||||
The `ClamAVManager` supports customizing the Docker container:
|
|
||||||
|
|
||||||
|
#### Constructor
|
||||||
```typescript
|
```typescript
|
||||||
const manager = new ClamAVManager();
|
new ClamAvService(host?: string, port?: number)
|
||||||
|
|
||||||
// Container properties are configurable
|
|
||||||
console.log(manager.containerName); // 'clamav-daemon'
|
|
||||||
console.log(manager.port); // 3310
|
|
||||||
```
|
```
|
||||||
|
- `host` - ClamAV daemon host (default: '127.0.0.1')
|
||||||
|
- `port` - ClamAV daemon port (default: 3310)
|
||||||
|
|
||||||
#### Log Management
|
#### Methods
|
||||||
|
|
||||||
Access and process ClamAV logs:
|
##### `scanString(text: string): Promise<ScanResult>`
|
||||||
|
Scan a text string for threats.
|
||||||
|
|
||||||
|
##### `scanBuffer(buffer: Buffer): Promise<ScanResult>`
|
||||||
|
Scan binary data in a Buffer.
|
||||||
|
|
||||||
|
##### `scanStream(stream: NodeJS.ReadableStream): Promise<ScanResult>`
|
||||||
|
Scan a Node.js readable stream.
|
||||||
|
|
||||||
|
##### `scanWebStream(stream: ReadableStream<Uint8Array>): Promise<ScanResult>`
|
||||||
|
Scan a Web Streams API stream (browser-compatible).
|
||||||
|
|
||||||
|
##### `scanFileFromWebAsStream(url: string): Promise<ScanResult>`
|
||||||
|
Download and scan a file from a URL.
|
||||||
|
|
||||||
|
##### `verifyConnection(): Promise<boolean>`
|
||||||
|
Test the connection to ClamAV daemon.
|
||||||
|
|
||||||
|
#### ScanResult Type
|
||||||
```typescript
|
```typescript
|
||||||
const manager = new ClamAVManager();
|
interface ScanResult {
|
||||||
|
isInfected: boolean;
|
||||||
// Get all logs
|
reason?: string; // Threat name if infected
|
||||||
const logs = manager.getLogs();
|
}
|
||||||
|
|
||||||
// Filter logs by type
|
|
||||||
const errorLogs = logs.filter(log => log.type === 'error');
|
|
||||||
const updateLogs = logs.filter(log => log.type === 'update');
|
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Health Checks
|
### ClamAVManager
|
||||||
|
|
||||||
Monitor ClamAV service health:
|
Advanced container management for production deployments:
|
||||||
|
|
||||||
```typescript
|
- `startContainer()` - Launch ClamAV in Docker
|
||||||
const manager = new ClamAVManager();
|
- `stopContainer()` - Gracefully shutdown
|
||||||
|
- `updateDatabase()` - Update virus definitions
|
||||||
|
- `getDatabaseInfo()` - Get current DB version
|
||||||
|
- `getLogs()` - Retrieve container logs
|
||||||
|
- Event: `'log'` - Real-time log streaming
|
||||||
|
|
||||||
// Service automatically checks readiness during initialization
|
## Production Considerations 🏭
|
||||||
await manager.startContainer(); // Includes readiness checks
|
|
||||||
|
|
||||||
// Get database status
|
### Performance Tips
|
||||||
const dbInfo = await manager.getDatabaseInfo();
|
|
||||||
console.log('Database Version:', dbInfo);
|
1. **Reuse connections** - Create one `ClamAvService` instance and reuse it
|
||||||
|
2. **Stream large files** - Don't load them into memory
|
||||||
|
3. **Implement timeouts** - Protect against hanging scans
|
||||||
|
4. **Monitor logs** - Watch for database update failures
|
||||||
|
|
||||||
|
### Security Best Practices
|
||||||
|
|
||||||
|
- Run ClamAV container with limited resources
|
||||||
|
- Implement rate limiting on scan endpoints
|
||||||
|
- Log all detected threats for audit trails
|
||||||
|
- Regularly update virus definitions
|
||||||
|
- Use separate containers for different environments
|
||||||
|
|
||||||
|
### Deployment Options
|
||||||
|
|
||||||
|
#### Docker Compose
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
clamav:
|
||||||
|
image: clamav/clamav:latest
|
||||||
|
ports:
|
||||||
|
- "3310:3310"
|
||||||
|
volumes:
|
||||||
|
- clamav-db:/var/lib/clamav
|
||||||
```
|
```
|
||||||
|
|
||||||
You can build upon these functionalities to implement advanced use cases such as:
|
#### Kubernetes
|
||||||
- Automated virus scanning in CI/CD pipelines
|
The service automatically manages containers, but you can also deploy ClamAV separately and connect directly to the daemon.
|
||||||
- Real-time file monitoring in web applications
|
|
||||||
- Cloud-based malware detection services
|
|
||||||
- Integration with security information and event management (SIEM) systems
|
|
||||||
|
|
||||||
With the help of Node.js worker threads or external task queues like RabbitMQ, you can distribute scanning tasks efficiently within high-traffic environments.
|
## Troubleshooting 🔧
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
|
||||||
|
**Container won't start**
|
||||||
|
- Ensure Docker is running
|
||||||
|
- Check port 3310 isn't already in use
|
||||||
|
- Verify sufficient disk space for virus definitions
|
||||||
|
|
||||||
|
**Scans timing out**
|
||||||
|
- Large files may take time - implement appropriate timeouts
|
||||||
|
- Check container resources (CPU/Memory)
|
||||||
|
- Ensure virus database is not updating
|
||||||
|
|
||||||
|
**False positives**
|
||||||
|
- Some packers/obfuscators trigger detection
|
||||||
|
- Whitelist known-safe patterns if needed
|
||||||
|
- Keep virus definitions updated
|
||||||
|
|
||||||
|
## Contributing & Support 🤝
|
||||||
|
|
||||||
|
- 🐛 [Report Issues](https://code.foss.global/push.rocks/smartantivirus/issues)
|
||||||
|
- 📖 [Documentation](https://code.foss.global/push.rocks/smartantivirus)
|
||||||
|
- 💬 [Discussions](https://code.foss.global/push.rocks/smartantivirus/issues)
|
||||||
|
|
||||||
## License and Legal Information
|
## License and Legal Information
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { expect, tap } from '../ts/plugins.js';
|
import { expect, tap } from '@push.rocks/tapbundle';
|
||||||
import type { ClamAVLogEvent } from '../ts/classes.clamav.manager.js';
|
import type { ClamAVLogEvent } from '../ts/classes.clamav.manager.js';
|
||||||
import { setupClamAV, cleanupClamAV, getManager } from './helpers/clamav.helper.js';
|
import { setupClamAV, cleanupClamAV, getManager } from './helpers/clamav.helper.js';
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { expect, tap } from '../ts/plugins.js';
|
import { tap, expect } from '@push.rocks/tapbundle';
|
||||||
import * as smartantivirus from '../ts/index.js';
|
import * as smartantivirus from '../ts/index.js';
|
||||||
import { setupClamAV, cleanupClamAV } from './helpers/clamav.helper.js';
|
import { setupClamAV, cleanupClamAV } from './helpers/clamav.helper.js';
|
||||||
|
|
||||||
|
@@ -3,6 +3,6 @@
|
|||||||
*/
|
*/
|
||||||
export const commitinfo = {
|
export const commitinfo = {
|
||||||
name: '@push.rocks/smartantivirus',
|
name: '@push.rocks/smartantivirus',
|
||||||
version: '1.1.2',
|
version: '1.3.2',
|
||||||
description: 'A Node.js package for integrating antivirus scanning capabilities using ClamAV, allowing in-memory file and data scanning.'
|
description: 'A Node.js package providing integration with ClamAV for anti-virus scanning, facilitating both Docker containerized management and direct connection to a ClamAV daemon.'
|
||||||
}
|
}
|
||||||
|
@@ -111,4 +111,77 @@ export class ClamAvService {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans data from a NodeJS stream using ClamAV daemon's INSTREAM command.
|
||||||
|
*/
|
||||||
|
public async scanStream(stream: NodeJS.ReadableStream): Promise<{ isInfected: boolean; reason?: string }> {
|
||||||
|
await this.ensureContainerStarted();
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const client = new net.Socket();
|
||||||
|
|
||||||
|
client.connect(this.port, this.host, () => {
|
||||||
|
console.log('Connected to ClamAV daemon for stream scanning');
|
||||||
|
client.write('zINSTREAM\0');
|
||||||
|
|
||||||
|
stream.on('data', (chunk: Buffer) => {
|
||||||
|
const buf = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
||||||
|
const sizeBuf = Buffer.alloc(4);
|
||||||
|
sizeBuf.writeUInt32BE(buf.length, 0);
|
||||||
|
client.write(sizeBuf);
|
||||||
|
client.write(buf);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('end', () => {
|
||||||
|
const endOfStream = Buffer.alloc(4);
|
||||||
|
endOfStream.writeUInt32BE(0, 0);
|
||||||
|
console.log('Stream ended, sending end-of-stream signal');
|
||||||
|
client.write(endOfStream);
|
||||||
|
});
|
||||||
|
|
||||||
|
stream.on('error', (err) => {
|
||||||
|
console.error('Error reading stream:', err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('data', (data) => {
|
||||||
|
const response = data.toString();
|
||||||
|
console.log('Raw Response from ClamAV (stream):', response);
|
||||||
|
const isInfected = response.includes('FOUND');
|
||||||
|
const reason = isInfected ? response.split('FOUND')[0].trim() : undefined;
|
||||||
|
resolve({ isInfected, reason });
|
||||||
|
client.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('error', (err) => {
|
||||||
|
console.error('Error with ClamAV stream scanning:', err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans a file from a web URL as a stream using ClamAV daemon's INSTREAM command.
|
||||||
|
*/
|
||||||
|
public async scanFileFromWebAsStream(url: string): Promise<{ isInfected: boolean; reason?: string }> {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
const protocol = url.startsWith('https') ? plugins.https : plugins.http;
|
||||||
|
protocol.get(url, (response) => {
|
||||||
|
this.scanStream(response).then(resolve).catch(reject);
|
||||||
|
}).on('error', (err) => {
|
||||||
|
console.error('Error fetching URL:', err);
|
||||||
|
reject(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scans a web resource by URL using ClamAV daemon's INSTREAM command.
|
||||||
|
*/
|
||||||
|
public async scanWebStream(webstreamArg: ReadableStream): Promise<{ isInfected: boolean; reason?: string }> {
|
||||||
|
// Convert the web ReadableStream to a NodeJS ReadableStream
|
||||||
|
const nodeStream = plugins.smartstream.nodewebhelpers.convertWebReadableToNodeReadable(webstreamArg);
|
||||||
|
return this.scanStream(nodeStream);
|
||||||
|
}
|
||||||
}
|
}
|
@@ -1,2 +1,2 @@
|
|||||||
export * from './classes.smartantivirus.js';
|
export * from './classes.clamavservice.js';
|
||||||
export * from './classes.clamav.manager.js';
|
export * from './classes.clamav.manager.js';
|
@@ -5,6 +5,8 @@ import { exec, spawn } from 'child_process';
|
|||||||
import { promisify } from 'util';
|
import { promisify } from 'util';
|
||||||
import { EventEmitter } from 'events';
|
import { EventEmitter } from 'events';
|
||||||
import net from 'net';
|
import net from 'net';
|
||||||
|
import * as http from 'http';
|
||||||
|
import * as https from 'https';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
fs,
|
fs,
|
||||||
@@ -13,19 +15,20 @@ export {
|
|||||||
spawn,
|
spawn,
|
||||||
promisify,
|
promisify,
|
||||||
EventEmitter,
|
EventEmitter,
|
||||||
net
|
net,
|
||||||
|
http,
|
||||||
|
https
|
||||||
};
|
};
|
||||||
|
|
||||||
// @push.rocks scope
|
// @push.rocks scope
|
||||||
import * as smartpath from '@push.rocks/smartpath';
|
import * as smartpath from '@push.rocks/smartpath';
|
||||||
import * as smartfile from '@push.rocks/smartfile';
|
import * as smartfile from '@push.rocks/smartfile';
|
||||||
import { expect, tap } from '@push.rocks/tapbundle';
|
import * as smartstream from '@push.rocks/smartstream';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
smartpath,
|
smartpath,
|
||||||
smartfile,
|
smartfile,
|
||||||
expect,
|
smartstream,
|
||||||
tap
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Third party scope
|
// Third party scope
|
||||||
|
Reference in New Issue
Block a user