/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmCPackDragNDropGenerator.h"

#include "cmCPackGenerator.h"
#include "cmCPackLog.h"
#include "cmDuration.h"
#include "cmGeneratedFileStream.h"
#include "cmSystemTools.h"

#include "cmsys/FStream.hxx"
#include "cmsys/RegularExpression.hxx"
#include <algorithm>
#include <iomanip>
#include <map>
#include <stdlib.h>

#include <CoreFoundation/CoreFoundation.h>

#ifdef HAVE_CoreServices
// For the old LocaleStringToLangAndRegionCodes() function, to convert
// to the old Script Manager RegionCode values needed for the 'LPic' data
// structure used for generating multi-lingual SLAs.
#  include <CoreServices/CoreServices.h>
#endif

static const char* SLAHeader =
  "data 'LPic' (5000) {\n"
  "    $\"0002 0011 0003 0001 0000 0000 0002 0000\"\n"
  "    $\"0008 0003 0000 0001 0004 0000 0004 0005\"\n"
  "    $\"0000 000E 0006 0001 0005 0007 0000 0007\"\n"
  "    $\"0008 0000 0047 0009 0000 0034 000A 0001\"\n"
  "    $\"0035 000B 0001 0020 000C 0000 0011 000D\"\n"
  "    $\"0000 005B 0004 0000 0033 000F 0001 000C\"\n"
  "    $\"0010 0000 000B 000E 0000\"\n"
  "};\n"
  "\n";

static const char* SLASTREnglish =
  "resource 'STR#' (5002, \"English\") {\n"
  "    {\n"
  "        \"English\",\n"
  "        \"Agree\",\n"
  "        \"Disagree\",\n"
  "        \"Print\",\n"
  "        \"Save...\",\n"
  "        \"You agree to the License Agreement terms when you click \"\n"
  "        \"the \\\"Agree\\\" button.\",\n"
  "        \"Software License Agreement\",\n"
  "        \"This text cannot be saved.  This disk may be full or locked, "
  "or the \"\n"
  "        \"file may be locked.\",\n"
  "        \"Unable to print.  Make sure you have selected a printer.\"\n"
  "    }\n"
  "};\n"
  "\n";

cmCPackDragNDropGenerator::cmCPackDragNDropGenerator()
  : singleLicense(false)
{
  // default to one package file for components
  this->componentPackageMethod = ONE_PACKAGE;
}

cmCPackDragNDropGenerator::~cmCPackDragNDropGenerator() = default;

int cmCPackDragNDropGenerator::InitializeInternal()
{
  // Starting with Xcode 4.3, look in "/Applications/Xcode.app" first:
  //
  std::vector<std::string> paths;
  paths.emplace_back("/Applications/Xcode.app/Contents/Developer/Tools");
  paths.emplace_back("/Developer/Tools");

  const std::string hdiutil_path =
    cmSystemTools::FindProgram("hdiutil", std::vector<std::string>(), false);
  if (hdiutil_path.empty()) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Cannot locate hdiutil command" << std::endl);
    return 0;
  }
  this->SetOptionIfNotSet("CPACK_COMMAND_HDIUTIL", hdiutil_path.c_str());

  const std::string setfile_path =
    cmSystemTools::FindProgram("SetFile", paths, false);
  if (setfile_path.empty()) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Cannot locate SetFile command" << std::endl);
    return 0;
  }
  this->SetOptionIfNotSet("CPACK_COMMAND_SETFILE", setfile_path.c_str());

  const std::string rez_path = cmSystemTools::FindProgram("Rez", paths, false);
  if (rez_path.empty()) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Cannot locate Rez command" << std::endl);
    return 0;
  }
  this->SetOptionIfNotSet("CPACK_COMMAND_REZ", rez_path.c_str());

  if (this->IsSet("CPACK_DMG_SLA_DIR")) {
    slaDirectory = this->GetOption("CPACK_DMG_SLA_DIR");
    if (!slaDirectory.empty() && this->IsSet("CPACK_RESOURCE_FILE_LICENSE")) {
      std::string license_file =
        this->GetOption("CPACK_RESOURCE_FILE_LICENSE");
      if (!license_file.empty() &&
          (license_file.find("CPack.GenericLicense.txt") ==
           std::string::npos)) {
        cmCPackLogger(
          cmCPackLog::LOG_OUTPUT,
          "Both CPACK_DMG_SLA_DIR and CPACK_RESOURCE_FILE_LICENSE specified, "
          "using CPACK_RESOURCE_FILE_LICENSE as a license for all languages."
            << std::endl);
        singleLicense = true;
      }
    }
    if (!this->IsSet("CPACK_DMG_SLA_LANGUAGES")) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "CPACK_DMG_SLA_DIR set but no languages defined "
                    "(set CPACK_DMG_SLA_LANGUAGES)"
                      << std::endl);
      return 0;
    }
    if (!cmSystemTools::FileExists(slaDirectory, false)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "CPACK_DMG_SLA_DIR does not exist" << std::endl);
      return 0;
    }

    std::vector<std::string> languages;
    cmSystemTools::ExpandListArgument(
      this->GetOption("CPACK_DMG_SLA_LANGUAGES"), languages);
    if (languages.empty()) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "CPACK_DMG_SLA_LANGUAGES set but empty" << std::endl);
      return 0;
    }
    for (auto const& language : languages) {
      std::string license = slaDirectory + "/" + language + ".license.txt";
      if (!singleLicense && !cmSystemTools::FileExists(license)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Missing license file " << language << ".license.txt"
                                              << std::endl);
        return 0;
      }
      std::string menu = slaDirectory + "/" + language + ".menu.txt";
      if (!cmSystemTools::FileExists(menu)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Missing menu file " << language << ".menu.txt"
                                           << std::endl);
        return 0;
      }
    }
  }

  return this->Superclass::InitializeInternal();
}

const char* cmCPackDragNDropGenerator::GetOutputExtension()
{
  return ".dmg";
}

int cmCPackDragNDropGenerator::PackageFiles()
{
  // gather which directories to make dmg files for
  // multiple directories occur if packaging components or groups separately

  // monolith
  if (this->Components.empty()) {
    return this->CreateDMG(toplevel, packageFileNames[0]);
  }

  // component install
  std::vector<std::string> package_files;

  std::map<std::string, cmCPackComponent>::iterator compIt;
  for (compIt = this->Components.begin(); compIt != this->Components.end();
       ++compIt) {
    std::string name = GetComponentInstallDirNameSuffix(compIt->first);
    package_files.push_back(name);
  }
  std::sort(package_files.begin(), package_files.end());
  package_files.erase(std::unique(package_files.begin(), package_files.end()),
                      package_files.end());

  // loop to create dmg files
  packageFileNames.clear();
  for (auto const& package_file : package_files) {
    std::string full_package_name = std::string(toplevel) + std::string("/");
    if (package_file == "ALL_IN_ONE") {
      full_package_name += this->GetOption("CPACK_PACKAGE_FILE_NAME");
    } else {
      full_package_name += package_file;
    }
    full_package_name += std::string(GetOutputExtension());
    packageFileNames.push_back(full_package_name);

    std::string src_dir = toplevel;
    src_dir += "/";
    src_dir += package_file;

    if (0 == this->CreateDMG(src_dir, full_package_name)) {
      return 0;
    }
  }
  return 1;
}

bool cmCPackDragNDropGenerator::CopyFile(std::ostringstream& source,
                                         std::ostringstream& target)
{
  if (!cmSystemTools::CopyFileIfDifferent(source.str(), target.str())) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Error copying " << source.str() << " to " << target.str()
                                   << std::endl);

    return false;
  }

  return true;
}

bool cmCPackDragNDropGenerator::CreateEmptyFile(std::ostringstream& target,
                                                size_t size)
{
  cmsys::ofstream fout(target.str().c_str(), std::ios::out | std::ios::binary);
  if (!fout) {
    return false;
  }

  // Seek to desired size - 1 byte
  fout.seekp(size - 1, std::ios::beg);
  char byte = 0;
  // Write one byte to ensure file grows
  fout.write(&byte, 1);

  return true;
}

bool cmCPackDragNDropGenerator::RunCommand(std::ostringstream& command,
                                           std::string* output)
{
  int exit_code = 1;

  bool result = cmSystemTools::RunSingleCommand(
    command.str().c_str(), output, output, &exit_code, nullptr,
    this->GeneratorVerbose, cmDuration::zero());

  if (!result || exit_code) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Error executing: " << command.str() << std::endl);

    return false;
  }

  return true;
}

int cmCPackDragNDropGenerator::CreateDMG(const std::string& src_dir,
                                         const std::string& output_file)
{
  // Get optional arguments ...
  const std::string cpack_package_icon = this->GetOption("CPACK_PACKAGE_ICON")
    ? this->GetOption("CPACK_PACKAGE_ICON")
    : "";

  const std::string cpack_dmg_volume_name =
    this->GetOption("CPACK_DMG_VOLUME_NAME")
    ? this->GetOption("CPACK_DMG_VOLUME_NAME")
    : this->GetOption("CPACK_PACKAGE_FILE_NAME");

  const std::string cpack_dmg_format = this->GetOption("CPACK_DMG_FORMAT")
    ? this->GetOption("CPACK_DMG_FORMAT")
    : "UDZO";

  // Get optional arguments ...
  std::string cpack_license_file =
    this->GetOption("CPACK_RESOURCE_FILE_LICENSE")
    ? this->GetOption("CPACK_RESOURCE_FILE_LICENSE")
    : "";

  const std::string cpack_dmg_background_image =
    this->GetOption("CPACK_DMG_BACKGROUND_IMAGE")
    ? this->GetOption("CPACK_DMG_BACKGROUND_IMAGE")
    : "";

  const std::string cpack_dmg_ds_store = this->GetOption("CPACK_DMG_DS_STORE")
    ? this->GetOption("CPACK_DMG_DS_STORE")
    : "";

  const std::string cpack_dmg_languages =
    this->GetOption("CPACK_DMG_SLA_LANGUAGES")
    ? this->GetOption("CPACK_DMG_SLA_LANGUAGES")
    : "";

  const std::string cpack_dmg_ds_store_setup_script =
    this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT")
    ? this->GetOption("CPACK_DMG_DS_STORE_SETUP_SCRIPT")
    : "";

  const bool cpack_dmg_disable_applications_symlink =
    this->IsOn("CPACK_DMG_DISABLE_APPLICATIONS_SYMLINK");

  // only put license on dmg if is user provided
  if (!cpack_license_file.empty() &&
      cpack_license_file.find("CPack.GenericLicense.txt") !=
        std::string::npos) {
    cpack_license_file = "";
  }

  // use sla_dir if both sla_dir and license_file are set
  if (!cpack_license_file.empty() && !slaDirectory.empty() && !singleLicense) {
    cpack_license_file = "";
  }

  // The staging directory contains everything that will end-up inside the
  // final disk image ...
  std::ostringstream staging;
  staging << src_dir;

  // Add a symlink to /Applications so users can drag-and-drop the bundle
  // into it unless this behaviour was disabled
  if (!cpack_dmg_disable_applications_symlink) {
    std::ostringstream application_link;
    application_link << staging.str() << "/Applications";
    cmSystemTools::CreateSymlink("/Applications", application_link.str());
  }

  // Optionally add a custom volume icon ...
  if (!cpack_package_icon.empty()) {
    std::ostringstream package_icon_source;
    package_icon_source << cpack_package_icon;

    std::ostringstream package_icon_destination;
    package_icon_destination << staging.str() << "/.VolumeIcon.icns";

    if (!this->CopyFile(package_icon_source, package_icon_destination)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error copying disk volume icon.  "
                    "Check the value of CPACK_PACKAGE_ICON."
                      << std::endl);

      return 0;
    }
  }

  // Optionally add a custom .DS_Store file
  // (e.g. for setting background/layout) ...
  if (!cpack_dmg_ds_store.empty()) {
    std::ostringstream package_settings_source;
    package_settings_source << cpack_dmg_ds_store;

    std::ostringstream package_settings_destination;
    package_settings_destination << staging.str() << "/.DS_Store";

    if (!this->CopyFile(package_settings_source,
                        package_settings_destination)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error copying disk volume settings file.  "
                    "Check the value of CPACK_DMG_DS_STORE."
                      << std::endl);

      return 0;
    }
  }

  // Optionally add a custom background image ...
  // Make sure the background file type is the same as the custom image
  // and that the file is hidden so it doesn't show up.
  if (!cpack_dmg_background_image.empty()) {
    const std::string extension =
      cmSystemTools::GetFilenameLastExtension(cpack_dmg_background_image);
    std::ostringstream package_background_source;
    package_background_source << cpack_dmg_background_image;

    std::ostringstream package_background_destination;
    package_background_destination << staging.str()
                                   << "/.background/background" << extension;

    if (!this->CopyFile(package_background_source,
                        package_background_destination)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error copying disk volume background image.  "
                    "Check the value of CPACK_DMG_BACKGROUND_IMAGE."
                      << std::endl);

      return 0;
    }
  }

  bool remount_image =
    !cpack_package_icon.empty() || !cpack_dmg_ds_store_setup_script.empty();

  std::string temp_image_format = "UDZO";

  // Create 1 MB dummy padding file in staging area when we need to remount
  // image, so we have enough space for storing changes ...
  if (remount_image) {
    std::ostringstream dummy_padding;
    dummy_padding << staging.str() << "/.dummy-padding-file";
    if (!this->CreateEmptyFile(dummy_padding, 1048576)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error creating dummy padding file." << std::endl);

      return 0;
    }
    temp_image_format = "UDRW";
  }

  // Create a temporary read-write disk image ...
  std::string temp_image = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
  temp_image += "/temp.dmg";

  std::string create_error;
  std::ostringstream temp_image_command;
  temp_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
  temp_image_command << " create";
  temp_image_command << " -ov";
  temp_image_command << " -srcfolder \"" << staging.str() << "\"";
  temp_image_command << " -volname \"" << cpack_dmg_volume_name << "\"";
  temp_image_command << " -fs HFS+";
  temp_image_command << " -format " << temp_image_format;
  temp_image_command << " \"" << temp_image << "\"";

  if (!this->RunCommand(temp_image_command, &create_error)) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Error generating temporary disk image." << std::endl
                                                           << create_error
                                                           << std::endl);

    return 0;
  }

  if (remount_image) {
    // Store that we have a failure so that we always unmount the image
    // before we exit.
    bool had_error = false;

    std::ostringstream attach_command;
    attach_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
    attach_command << " attach";
    attach_command << " \"" << temp_image << "\"";

    std::string attach_output;
    if (!this->RunCommand(attach_command, &attach_output)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error attaching temporary disk image." << std::endl);

      return 0;
    }

    cmsys::RegularExpression mountpoint_regex(".*(/Volumes/[^\n]+)\n.*");
    mountpoint_regex.find(attach_output.c_str());
    std::string const temp_mount = mountpoint_regex.match(1);
    std::string const temp_mount_name =
      temp_mount.substr(sizeof("/Volumes/") - 1);

    // Remove dummy padding file so we have enough space on RW image ...
    std::ostringstream dummy_padding;
    dummy_padding << temp_mount << "/.dummy-padding-file";
    if (!cmSystemTools::RemoveFile(dummy_padding.str())) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error removing dummy padding file." << std::endl);

      had_error = true;
    }

    // Optionally set the custom icon flag for the image ...
    if (!had_error && !cpack_package_icon.empty()) {
      std::string error;
      std::ostringstream setfile_command;
      setfile_command << this->GetOption("CPACK_COMMAND_SETFILE");
      setfile_command << " -a C";
      setfile_command << " \"" << temp_mount << "\"";

      if (!this->RunCommand(setfile_command, &error)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Error assigning custom icon to temporary disk image."
                        << std::endl
                        << error << std::endl);

        had_error = true;
      }
    }

    // Optionally we can execute a custom apple script to generate
    // the .DS_Store for the volume folder ...
    if (!had_error && !cpack_dmg_ds_store_setup_script.empty()) {
      std::ostringstream setup_script_command;
      setup_script_command << "osascript"
                           << " \"" << cpack_dmg_ds_store_setup_script << "\""
                           << " \"" << temp_mount_name << "\"";
      std::string error;
      if (!this->RunCommand(setup_script_command, &error)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Error executing custom script on disk image."
                        << std::endl
                        << error << std::endl);

        had_error = true;
      }
    }

    std::ostringstream detach_command;
    detach_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
    detach_command << " detach";
    detach_command << " \"" << temp_mount << "\"";

    if (!this->RunCommand(detach_command)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error detaching temporary disk image." << std::endl);

      return 0;
    }

    if (had_error) {
      return 0;
    }
  }

  if (!cpack_license_file.empty() || !slaDirectory.empty()) {
    // Use old hardcoded style if sla_dir is not set
    bool oldStyle = slaDirectory.empty();
    std::string sla_r = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
    sla_r += "/sla.r";

    std::vector<std::string> languages;
    if (!oldStyle) {
      cmSystemTools::ExpandListArgument(cpack_dmg_languages, languages);
    }

    cmGeneratedFileStream ofs(sla_r);
    ofs << "#include <CoreServices/CoreServices.r>\n\n";
    if (oldStyle) {
      ofs << SLAHeader;
      ofs << "\n";
    } else {
      /*
       * LPic Layout
       * (https://github.com/pypt/dmg-add-license/blob/master/main.c)
       * as far as I can tell (no official documentation seems to exist):
       * struct LPic {
       *  uint16_t default_language; // points to a resid, defaulting to 0,
       *                             // which is the first set language
       *  uint16_t length;
       *  struct {
       *    uint16_t language_code;
       *    uint16_t resid;
       *    uint16_t encoding; // Encoding from TextCommon.h,
       *                       // forcing MacRoman (0) for now. Might need to
       *                       // allow overwrite per license by user later
       *  } item[1];
       * }
       */

      // Create vector first for readability, then iterate to write to ofs
      std::vector<uint16_t> header_data;
      header_data.push_back(0);
      header_data.push_back(languages.size());
      for (size_t i = 0; i < languages.size(); ++i) {
        CFStringRef language_cfstring = CFStringCreateWithCString(
          nullptr, languages[i].c_str(), kCFStringEncodingUTF8);
        CFStringRef iso_language =
          CFLocaleCreateCanonicalLanguageIdentifierFromString(
            nullptr, language_cfstring);
        if (!iso_language) {
          cmCPackLogger(cmCPackLog::LOG_ERROR,
                        languages[i] << " is not a recognized language"
                                     << std::endl);
        }
        char iso_language_cstr[65];
        CFStringGetCString(iso_language, iso_language_cstr,
                           sizeof(iso_language_cstr) - 1,
                           kCFStringEncodingMacRoman);
        LangCode lang = 0;
        RegionCode region = 0;
#ifdef HAVE_CoreServices
        OSStatus err =
          LocaleStringToLangAndRegionCodes(iso_language_cstr, &lang, &region);
        if (err != noErr)
#endif
        {
          cmCPackLogger(cmCPackLog::LOG_ERROR,
                        "No language/region code available for "
                          << iso_language_cstr << std::endl);
          return 0;
        }
#ifdef HAVE_CoreServices
        header_data.push_back(region);
        header_data.push_back(i);
        header_data.push_back(0);
#endif
      }
      ofs << "data 'LPic' (5000) {\n";
      ofs << std::hex << std::uppercase << std::setfill('0');

      for (size_t i = 0; i < header_data.size(); ++i) {
        if (i % 8 == 0) {
          ofs << "    $\"";
        }

        ofs << std::setw(4) << header_data[i];

        if (i % 8 == 7 || i == header_data.size() - 1) {
          ofs << "\"\n";
        } else {
          ofs << " ";
        }
      }
      ofs << "};\n\n";
      // Reset ofs options
      ofs << std::dec << std::nouppercase << std::setfill(' ');
    }

    bool have_write_license_error = false;
    std::string error;

    if (oldStyle) {
      if (!this->WriteLicense(ofs, 0, "", cpack_license_file, &error)) {
        have_write_license_error = true;
      }
    } else {
      for (size_t i = 0; i < languages.size() && !have_write_license_error;
           ++i) {
        if (singleLicense) {
          if (!this->WriteLicense(ofs, i + 5000, languages[i],
                                  cpack_license_file, &error)) {
            have_write_license_error = true;
          }
        } else {
          if (!this->WriteLicense(ofs, i + 5000, languages[i], "", &error)) {
            have_write_license_error = true;
          }
        }
      }
    }

    ofs.Close();

    if (have_write_license_error) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error writing license file to SLA." << std::endl
                                                         << error
                                                         << std::endl);
      return 0;
    }

    if (temp_image_format != "UDZO") {
      temp_image_format = "UDZO";
      // convert to UDZO to enable unflatten/flatten
      std::string temp_udzo = this->GetOption("CPACK_TOPLEVEL_DIRECTORY");
      temp_udzo += "/temp-udzo.dmg";

      std::ostringstream udco_image_command;
      udco_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
      udco_image_command << " convert \"" << temp_image << "\"";
      udco_image_command << " -format UDZO";
      udco_image_command << " -ov -o \"" << temp_udzo << "\"";

      if (!this->RunCommand(udco_image_command, &error)) {
        cmCPackLogger(cmCPackLog::LOG_ERROR,
                      "Error converting to UDCO dmg for adding SLA."
                        << std::endl
                        << error << std::endl);
        return 0;
      }
      temp_image = temp_udzo;
    }

    // unflatten dmg
    std::ostringstream unflatten_command;
    unflatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
    unflatten_command << " unflatten ";
    unflatten_command << "\"" << temp_image << "\"";

    if (!this->RunCommand(unflatten_command, &error)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error unflattening dmg for adding SLA." << std::endl
                                                             << error
                                                             << std::endl);
      return 0;
    }

    // Rez the SLA
    std::ostringstream embed_sla_command;
    embed_sla_command << this->GetOption("CPACK_COMMAND_REZ");
    const char* sysroot = this->GetOption("CPACK_OSX_SYSROOT");
    if (sysroot && sysroot[0] != '\0') {
      embed_sla_command << " -isysroot \"" << sysroot << "\"";
    }
    embed_sla_command << " \"" << sla_r << "\"";
    embed_sla_command << " -a -o ";
    embed_sla_command << "\"" << temp_image << "\"";

    if (!this->RunCommand(embed_sla_command, &error)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error adding SLA." << std::endl
                                        << error << std::endl);
      return 0;
    }

    // flatten dmg
    std::ostringstream flatten_command;
    flatten_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
    flatten_command << " flatten ";
    flatten_command << "\"" << temp_image << "\"";

    if (!this->RunCommand(flatten_command, &error)) {
      cmCPackLogger(cmCPackLog::LOG_ERROR,
                    "Error flattening dmg for adding SLA." << std::endl
                                                           << error
                                                           << std::endl);
      return 0;
    }
  }

  // Create the final compressed read-only disk image ...
  std::ostringstream final_image_command;
  final_image_command << this->GetOption("CPACK_COMMAND_HDIUTIL");
  final_image_command << " convert \"" << temp_image << "\"";
  final_image_command << " -format ";
  final_image_command << cpack_dmg_format;
  final_image_command << " -imagekey";
  final_image_command << " zlib-level=9";
  final_image_command << " -o \"" << output_file << "\"";

  std::string convert_error;

  if (!this->RunCommand(final_image_command, &convert_error)) {
    cmCPackLogger(cmCPackLog::LOG_ERROR,
                  "Error compressing disk image." << std::endl
                                                  << convert_error
                                                  << std::endl);

    return 0;
  }

  return 1;
}

bool cmCPackDragNDropGenerator::SupportsComponentInstallation() const
{
  return true;
}

std::string cmCPackDragNDropGenerator::GetComponentInstallDirNameSuffix(
  const std::string& componentName)
{
  // we want to group components together that go in the same dmg package
  std::string package_file_name = this->GetOption("CPACK_PACKAGE_FILE_NAME");

  // we have 3 mutually exclusive modes to work in
  // 1. all components in one package
  // 2. each group goes in its own package with left over
  //    components in their own package
  // 3. ignore groups - if grouping is defined, it is ignored
  //    and each component goes in its own package

  if (this->componentPackageMethod == ONE_PACKAGE) {
    return "ALL_IN_ONE";
  }

  if (this->componentPackageMethod == ONE_PACKAGE_PER_GROUP) {
    // We have to find the name of the COMPONENT GROUP
    // the current COMPONENT belongs to.
    std::string groupVar =
      "CPACK_COMPONENT_" + cmSystemTools::UpperCase(componentName) + "_GROUP";
    const char* _groupName = GetOption(groupVar);
    if (_groupName) {
      std::string groupName = _groupName;

      groupName =
        GetComponentPackageFileName(package_file_name, groupName, true);
      return groupName;
    }
  }

  return GetComponentPackageFileName(package_file_name, componentName, false);
}

bool cmCPackDragNDropGenerator::WriteLicense(
  cmGeneratedFileStream& outputStream, int licenseNumber,
  std::string licenseLanguage, const std::string& licenseFile,
  std::string* error)
{
  if (!licenseFile.empty() && !singleLicense) {
    licenseNumber = 5002;
    licenseLanguage = "English";
  }

  // License header
  outputStream << "data 'TEXT' (" << licenseNumber << ", \"" << licenseLanguage
               << "\") {\n";
  // License body
  std::string actual_license = !licenseFile.empty()
    ? licenseFile
    : (slaDirectory + "/" + licenseLanguage + ".license.txt");
  cmsys::ifstream license_ifs;
  license_ifs.open(actual_license.c_str());
  if (license_ifs.is_open()) {
    while (license_ifs.good()) {
      std::string line;
      std::getline(license_ifs, line);
      if (!line.empty()) {
        EscapeQuotesAndBackslashes(line);
        std::vector<std::string> lines;
        if (!this->BreakLongLine(line, lines, error)) {
          return false;
        }
        for (auto const& l : lines) {
          outputStream << "        \"" << l << "\"\n";
        }
      }
      outputStream << "        \"\\n\"\n";
    }
    license_ifs.close();
  }

  // End of License
  outputStream << "};\n\n";
  if (!licenseFile.empty() && !singleLicense) {
    outputStream << SLASTREnglish;
  } else {
    // Menu header
    outputStream << "resource 'STR#' (" << licenseNumber << ", \""
                 << licenseLanguage << "\") {\n";
    outputStream << "    {\n";

    // Menu body
    cmsys::ifstream menu_ifs;
    menu_ifs.open(
      (slaDirectory + "/" + licenseLanguage + ".menu.txt").c_str());
    if (menu_ifs.is_open()) {
      size_t lines_written = 0;
      while (menu_ifs.good()) {
        // Lines written from original file, not from broken up lines
        std::string line;
        std::getline(menu_ifs, line);
        if (!line.empty()) {
          EscapeQuotesAndBackslashes(line);
          std::vector<std::string> lines;
          if (!this->BreakLongLine(line, lines, error)) {
            return false;
          }
          for (size_t i = 0; i < lines.size(); ++i) {
            std::string comma;
            // We need a comma after every complete string,
            // but not on the very last line
            if (lines_written != 8 && i == lines.size() - 1) {
              comma = ",";
            } else {
              comma = "";
            }
            outputStream << "        \"" << lines[i] << "\"" << comma << "\n";
          }
          ++lines_written;
        }
      }
      menu_ifs.close();
    }

    // End of menu
    outputStream << "    }\n";
    outputStream << "};\n";
    outputStream << "\n";
  }

  return true;
}

bool cmCPackDragNDropGenerator::BreakLongLine(const std::string& line,
                                              std::vector<std::string>& lines,
                                              std::string* error)
{
  const size_t max_line_length = 512;
  for (size_t i = 0; i < line.size(); i += max_line_length) {
    size_t line_length = max_line_length;
    if (i + line_length > line.size()) {
      line_length = line.size() - i;
    } else {
      while (line_length > 0 && line[i + line_length - 1] != ' ') {
        line_length = line_length - 1;
      }
    }

    if (line_length == 0) {
      *error = "Please make sure there are no words "
               "(or character sequences not broken up by spaces or newlines) "
               "in your license file which are more than 512 characters long.";
      return false;
    }
    lines.push_back(line.substr(i, line_length));
  }
  return true;
}

void cmCPackDragNDropGenerator::EscapeQuotesAndBackslashes(std::string& line)
{
  std::string::size_type backslash_pos = line.find('\\');
  while (backslash_pos != std::string::npos) {
    line.replace(backslash_pos, 1, "\\\\");
    backslash_pos = line.find('\\', backslash_pos + 2);
  }

  std::string::size_type quote_pos = line.find('\"');
  while (quote_pos != std::string::npos) {
    line.replace(quote_pos, 1, "\\\"");
    quote_pos = line.find('\"', quote_pos + 2);
  }
}
