prey/prey-node-client

View on GitHub
lib/agent/providers/screenshot/mac/index.js

Summary

Maintainability
C
1 day
Test Coverage
const { exec } = require('child_process');
// eslint-disable-next-line camelcase
const { is_greater_than } = require('../../../helpers');
const common = require('../../../common');

const socket = require('../../../socket');
const { nameArray } = require('../../../socket/messages');
const { system } = common;
// eslint-disable-next-line camelcase
const { run_as_logged_user } = system;
// eslint-disable-next-line camelcase
const { tempfile_path } = common.system;

const screenshotTimeout = 10000;

let timer;
let child;
let running = true;

const screenshotUtilData = {
  userPath: '',
  appPath: '',
  screenshotDir: '',
  tmpScreenshot: '',
};
/**
 * Executes the callback function after the completion of a task.
 *
 * @param {Error} err - The error object, if any.
 * @param {string} filePath - The path of the file.
 * @param {function} cb - The callback function to be executed.
 * @return {undefined} Executes the callback function with the specified parameters.
 */
// eslint-disable-next-line consistent-return
const done = (err, filePath, cb) => {
  running = false;
  if (timer) clearTimeout(timer);
  if (err) return cb(err);
  cb(null, filePath, 'image/jpeg');
};
/**
 * Configures the screenshot user data.
 */
const configureScreenshotUserData = () => {
  screenshotUtilData.appPath = `${__dirname}/../../../utils/Prey.app`;
  screenshotUtilData.screenshotDir = '/tmp';
  screenshotUtilData.tmpScreenshot = `${screenshotUtilData.screenshotDir}/screenshot.jpg`;
};
/**
 * Retrieves the user ID for the given user.
 *
 * @param {string} user - The username of the user.
 * @param {function} cb - The callback function to be executed after retrieving the user ID.
 * @return {undefined} This function does not return a value.
 */
const getIdUser = (user, cb) => {
  configureScreenshotUserData(user);
  cb();
};

/**
 * Takes a screenshot.
 *
 * @param {function} cb - The callback function to be called after the screenshot is taken.
 * @return {undefined} No return value.
 */
const takeScreenshot = (cb) => {
  // eslint-disable-next-line consistent-return
  child = run_as_logged_user(`open -n ${screenshotUtilData.appPath}`, ['--args', '-screenshot'], (err) => {
    if (err) return cb(err);
    cb();
  });
};

exports.get_screenshot = (callback) => {
  socket.writeMessage(nameArray[4], (err, data) => {
    if (err) return exports.get_screenshot_old(callback);
    try {
      if (typeof data.result.success === 'boolean' && data.result.success === false)
        return done(new Error("Couldn't get screenshot"), null, callback);
      done(null, data.result.messages[1].message, callback);
    } catch (_ex) {
      done(new Error("Couldn't get screenshot"), null, callback);
    }
    // if (err) return get_screenshot_old(callback);
    // return done(null, data, callback);
  });
};

/**
 * Generates the function comment for the given function body.
 *
 * @param {function} callback - The callback function to be called.
 * @return {undefined}
 */
exports.get_screenshot_old = (callback) => {
  // if after 10 seconds the screenshot hasn't been taken, cancel it.
  timer = setTimeout(() => {
    if (running && child) child.kill();
  }, screenshotTimeout);

  if (is_greater_than('10.15.0', common.os_release)) {
    const filePath1015 = tempfile_path(`screenshot.${process.pid}.jpg`);
    child = exec('/usr/sbin/screencapture -t jpg -mx', (err) => {
      done(err, filePath1015, callback);
    });
    return;
  }
  // Patch for MacOS Mojave and future versions
  // eslint-disable-next-line consistent-return
  common.system.get_logged_user((err, user) => {
    if (err || !user) return done(new Error(`Unable to get logged user: ${err.toString()}`), null, callback);
    // eslint-disable-next-line consistent-return
    configureScreenshotUserData();
    // eslint-disable-next-line consistent-return
    takeScreenshot((errorTakescreenshot) => {
      if (errorTakescreenshot) return done(errorTakescreenshot, null, callback);
      setTimeout(() => {
        done(null, screenshotUtilData.tmpScreenshot, callback);
      }, 3000);
    });
  });
};

exports.done = done;
exports.running = running;
exports.timer = timer;
exports.getIdUser = getIdUser;
exports.screenshotUtilData = screenshotUtilData;
exports.configureScreenshotUserData = configureScreenshotUserData;
exports.takeScreenshot = takeScreenshot;