You are here

function _clamav_scan_via_exec in ClamAV 7

Same name and namespace in other branches
  1. 6 clamav.inc \_clamav_scan_via_exec()

Scan a single file using a clamav executable.

Parameters

String $filepath: Full filepath to the file which is to be scanned. This must be a file which is readable by the web server.

String $filename: Filename of the uploaded file (used for logging).

Return value

int one of:

1 call to _clamav_scan_via_exec()
clamav_scan_file in ./clamav.inc
Scan a single file

File

./clamav.inc, line 216
clamav.inc API and helper functions for the ClamAV module.

Code

function _clamav_scan_via_exec($filepath, $filename) {

  // get the path to the executable
  $executable = variable_get('clamav_executable_path', CLAMAV_DEFAULT_PATH);

  // check that the executable is available
  if (!file_exists($executable)) {
    watchdog('clamav', "The clamscan executable could not be found at %path", array(
      '%path' => $executable,
    ), WATCHDOG_ERROR);
    return CLAMAV_SCANRESULT_UNCHECKED;
  }

  // optional additional options for the executable
  $exec_params = trim(variable_get('clamav_executable_parameters', CLAMAV_DEFAULT_PARAMS));
  if (!empty($exec_params)) {

    // individually shell-escape multiple options in the string
    $exec_params = explode(' ', $exec_params);
    $exec_params = array_filter($exec_params);
    $exec_params = array_map('escapeshellarg', $exec_params);
    $exec_params = implode(' ', $exec_params);
  }
  $filepath = drupal_realpath($filepath);

  // using 2>&1 to grab the full command-line output.
  $cmd = escapeshellcmd($executable);
  $cmd .= !empty($exec_params) ? ' ' . $exec_params : '';

  // already escaped
  $cmd .= ' ' . escapeshellarg($filepath) . ' 2>&1';

  // exec:
  // The lines of text output by clamscan are assigned as an array to $output
  // The actual result of clamscan is assigned to $result:
  // 0 = clean
  // 1 = infected
  // x = unchecked
  exec($cmd, $output, $result);

  /**
   * clamscan return values (documented from man clamscan)
   *  0 : No virus found.
   *  1 : Virus(es) found.
   *  2 : Some error(s) occured
   *
   * Specific return codes below retained for backwards-compatibilty
   *   (with very old versions of clamscan < 0.96)
   *
   * 40: Unknown option passed.
   * 50: Database initialization error.
   * 52: Not supported file type.
   * 53: Can't open directory.
   * 54: Can't open file. (ofm)
   * 55: Error reading file. (ofm)
   * 56: Can't stat input file / directory.
   * 57: Can't get absolute path name of current working directory.
   * 58: I/O error, please check your file system.
   * 62: Can't initialize logger.
   * 63: Can't create temporary files/directories (check permissions).
   * 64: Can't write to temporary directory (please specify another one).
   * 70: Can't allocate memory (calloc).
   * 71: Can't allocate memory (malloc).
   */
  switch ($result) {
    case 0:

      // Log the message to watchdog, if verbose mode is used.
      if (variable_get('clamav_verbose', CLAMAV_VERBOSE_DEFAULT)) {
        watchdog('clamav', 'File %filename scanned by ClamAV and found clean.', array(
          '%filename' => $filename,
        ), WATCHDOG_INFO);
      }
      return CLAMAV_SCANRESULT_CLEAN;
    case 1:
      watchdog('clamav', 'Virus detected in uploaded file %filename. Clamscan reported:<br />!clamscan_output', array(
        '%filename' => $filename,
        '!clamscan_output' => _clamav_sanitise_output($output),
      ), WATCHDOG_CRITICAL);
      return CLAMAV_SCANRESULT_INFECTED;
    default:
      $descriptions = array(
        2 => "Some error(s) occured.",
        40 => "Unknown option passed.",
        50 => "Database initialization error.",
        52 => "Not supported file type.",
        53 => "Can't open directory.",
        54 => "Can't open file. (ofm)",
        55 => "Error reading file. (ofm)",
        56 => "Can't stat input file / directory.",
        57 => "Can't get absolute path name of current working directory.",
        58 => "I/O error, please check your file system.",
        62 => "Can't initialize logger.",
        63 => "Can't create temporary files/directories (check permissions).",
        64 => "Can't write to temporary directory (please specify another one).",
        70 => "Can't allocate memory (calloc).",
        71 => "Can't allocate memory (malloc).",
      );
      $description = array_key_exists($result, $descriptions) ? $descriptions[$result] : 'unknown error';
      watchdog('clamav', 'Uploaded file %filename could not be scanned. Clamscan reported: [@error_code] - @error_description Output:<br />!clamscan_output', array(
        '%filename' => $filename,
        '@error_code' => $result,
        '@error_description' => $description,
        '!clamscan_output' => _clamav_sanitise_output($output),
      ), WATCHDOG_WARNING);
      return CLAMAV_SCANRESULT_UNCHECKED;
  }
}