Installation Add the package via Composer:
composer require xenolope/quahog
Register the service provider in config/app.php (if not auto-discovered):
'providers' => [
// ...
Xenolope\Quahog\QuahogServiceProvider::class,
],
Configuration Publish the config file:
php artisan vendor:publish --provider="Xenolope\Quahog\QuahogServiceProvider" --tag="config"
Update config/quahog.php with your clamd daemon details (default: unix:///var/run/clamav/clamd.ctl).
First Scan
Inject the Quahog facade or service into a controller/service:
use Xenolope\Quahog\Facades\Quahog;
public function scanFile(Request $request) {
$filePath = $request->file('file')->getRealPath();
$result = Quahog::scan($filePath);
return response()->json($result);
}
File Scanning
Quahog::scan($filePath) to check a file.Quahog::scanStream($stream).Quahog::scanDirectory($path) to scan all files in a directory.Command Execution
clamd commands (e.g., reload, stats):
Quahog::command('reload');
$stats = Quahog::command('stats');
Integration with Laravel
public function handle($request, Closure $next) {
if ($request->hasFile('file')) {
$scan = Quahog::scan($request->file('file')->getRealPath());
if ($scan['infected']) {
abort(403, 'Malware detected!');
}
}
return $next($request);
}
event(new FileScanned($filePath, $result));
Batch Processing
ScanFileJob::dispatch($filePath)->onQueue('scans');
Custom Responses Extend the default response format:
$result = Quahog::scan($filePath, [
'format' => 'json',
'verbose' => true,
]);
Logging Log scan results to a custom table or external service:
\Log::info('Scan result', ['file' => $filePath, 'result' => $result]);
Fallback Mechanisms
Handle clamd unavailability gracefully:
try {
$result = Quahog::scan($filePath);
} catch (\Exception $e) {
// Fallback to another AV or log the error
}
Connection Issues
clamd is running and the socket path/port in config/quahog.php is correct.clamdscan --socket=/var/run/clamav/clamd.ctl /tmp/testfile
Permission Errors
www-data) must have read access to scanned files and write access to clamd socket.chmod 666 /var/run/clamav/clamd.ctl
chmod -R 755 /path/to/files
Large File Handling
$stream = fopen($filePath, 'r');
$result = Quahog::scanStream($stream);
fclose($stream);
Signature Updates
Quahog::command('reload') must be called after manual clamav-freshclam updates.Enable Verbose Output
Configure config/quahog.php:
'verbose' => env('QUAHOG_VERBOSE', false),
Check Laravel logs for raw clamd output.
Check clamd Logs
Monitor /var/log/clamav/freshclam.log or /var/log/clamav/clamd.log for errors.
Test with Known Files Use EICAR test file:
echo "X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*" > /tmp/eicar.com
Scan via:
Quahog::scan('/tmp/eicar.com'); // Should return 'infected'.
Custom Commands
Extend the Quahog class to add domain-specific commands:
Quahog::extend(function ($quahog) {
$quahog->customCommand = function ($arg) {
return $quahog->run('custom ' . $arg);
};
});
Response Parsing
Override response handling in app/Providers/QuahogServiceProvider.php:
public function boot() {
Quahog::macro('parseResponse', function ($raw) {
// Custom parsing logic
return ['custom' => 'data'];
});
}
Mocking for Tests
Use Laravel’s service container to mock Quahog:
$this->app->instance(\Xenolope\Quahog\Quahog::class, Mockery::mock());
How can I help you explore Laravel packages today?