code: function validate(archiveDirectory, strict, cb) {
    // Root validation checks
    fs.readdir(archiveDirectory, function(err, files) {
      if (err) {
        return cb(err);
      }
  
      if (files.length < 2 || (files.length !== 2 && strict)) {
        return cb('Root directory must contain exactly one metadata file and one forms directory');
      }
  
      if (files.indexOf('forms') === -1) {
        return cb('A forms directory should be present in the root of the zip file');
      }
  
      if (files.indexOf('metadata.json') === -1) {
        return cb('A metadata.json file must be present in the root of the zip file');
      }
  
      var metadataPath = path.join(archiveDirectory, 'metadata.json');
  
      async.waterfall([
        function(callback) {
          validateMetadata(metadataPath, function(err, formFiles) {
            callback(err, formFiles);
          });
        },
        function(formFiles, callback) {
          var forms = [];
  
          _.each(formFiles, function(formFile) {
            forms.push(path.join(archiveDirectory, formFile.path));
          });
  
          async.each(forms, validateForm, callback);
        }
      ], function(err) {
        cb(err);
      });
    });
  }
docs: Validates the content of the extracted ZIP to check that it is a valid archive to be imported.
  
  @param {string} archiveDirectory The directory where the ZIP archive has been unzipped
  @param {boolean} strict if true, strict checks must be performed: no extraneous files will be
  admitted.
  @param {function} cb callback