Compress-Deflate7

 view release on metacpan or  search on metacpan

7zip/CPP/7zip/UI/Explorer/ContextMenu.cpp  view on Meta::CPAN

  " def dep dlg dsp dsw"
  " eps"
  " f f77 f90 f95 fla flac frm"
  " gif"
  " h hpp hta htm html hxx"
  " ico idl inc ini inl"
  " java jpeg jpg js"
  " la"
  " mak manifest wmv mov mp3 mp4 mpe mpeg mpg m4a"
  " ofr ogg"
  " pac pas pdf php php3 php4 php5 phptml pl pm png ps py pyo"
  " ra rb rc reg rka rm rtf"
  " sed sh shn shtml sln sql srt swa"
  " tcl tex tiff tta txt"
  " vb vcproj vbs"
  " wav wma wv"
  " xml xsd xsl xslt"
  " ";

static const char *kNoOpenAsExtensions =
  " 7z arj bz2 cab chm cpio dmg flv gz lha lzh lzma rar swm tar tbz2 tgz wim xar xz z zip ";

static bool FindExt(const char *p, const UString &name)
{
  int extPos = name.ReverseFind('.');
  if (extPos < 0)
    return false;
  UString ext = name.Mid(extPos + 1);
  ext.MakeLower();
  AString ext2 = UnicodeStringToMultiByte(ext);
  for (int i = 0; p[i] != 0;)
  {
    int j;
    for (j = i; p[j] != ' '; j++);
    if (ext2.Length() == j - i && memcmp(p + i, (const char *)ext2, ext2.Length()) == 0)
      return true;
    i = j + 1;
  }
  return false;
}

static bool DoNeedExtract(const UString &name)
{
  return !FindExt(kExtractExludeExtensions, name);
}

STDMETHODIMP CZipContextMenu::QueryContextMenu(HMENU hMenu, UINT indexMenu,
      UINT commandIDFirst, UINT commandIDLast, UINT flags)
{
  LoadLangOneTime();
  if (_fileNames.Size() == 0)
    return E_FAIL;
  UINT currentCommandID = commandIDFirst;
  if ((flags & 0x000F) != CMF_NORMAL  &&
      (flags & CMF_VERBSONLY) == 0 &&
      (flags & CMF_EXPLORE) == 0)
    return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID);

  _commandMap.Clear();

  CMenu popupMenu;
  CMenuDestroyer menuDestroyer;

  CContextMenuInfo ci;
  ci.Load();
  MENUITEMINFO menuItem;
  UINT subIndex = indexMenu;
  if (ci.Cascaded)
  {
    CCommandMapItem commandMapItem;
    if (!popupMenu.CreatePopup())
      return E_FAIL;
    menuDestroyer.Attach(popupMenu);
    commandMapItem.CommandInternalID = kCommandNULL;
    commandMapItem.Verb = kMainVerb;
    commandMapItem.HelpString = LangString(IDS_CONTEXT_CAPTION_HELP, 0x02000102);
    _commandMap.Add(commandMapItem);
    
    menuItem.wID = currentCommandID++;
    subIndex = 0;
  }
  else
  {
    popupMenu.Attach(hMenu);
  }

  UInt32 contextMenuFlags = ci.Flags;

  UString mainString;
  if (_fileNames.Size() == 1 && currentCommandID + 6 <= commandIDLast)
  {
    const UString &fileName = _fileNames.Front();
    UString folderPrefix;
    NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix);
   
    NFile::NFind::CFileInfoW fileInfo;
    if (!fileInfo.Find(fileName))
      return E_FAIL;
    if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name))
    {
      // Open
      bool thereIsMainOpenItem = ((contextMenuFlags & NContextMenuFlags::kOpen) != 0);
      if (thereIsMainOpenItem)
      {
        CCommandMapItem commandMapItem;
        FillCommand(kOpen, mainString, commandMapItem);
        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
        _commandMap.Add(commandMapItem);
      }
      if ((contextMenuFlags & NContextMenuFlags::kOpenAs) != 0 &&
          (!thereIsMainOpenItem || !FindExt(kNoOpenAsExtensions, fileInfo.Name)))
      {
        CMenu subMenu;
        if (subMenu.CreatePopup())
        {
          CCommandMapItem commandMapItem;
          
          CMenuItem menuItem;
          menuItem.fType = MFT_STRING;
          menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
          menuItem.wID = currentCommandID++;
          menuItem.hSubMenu = subMenu;
          menuItem.StringValue = LangString(IDS_CONTEXT_OPEN, 0x02000103);
          popupMenu.InsertItem(subIndex++, true, menuItem);
          
          commandMapItem.CommandInternalID = kCommandNULL;
          commandMapItem.Verb = kMainVerb;
          commandMapItem.HelpString = LangString(IDS_CONTEXT_OPEN_HELP, 0x02000104);
          _commandMap.Add(commandMapItem);
          
          UINT subIndex2 = 0;
          const wchar_t *exts[] = { L"", L"*", L"7z", L"zip", L"cab", L"rar" };
          for (int i = (thereIsMainOpenItem ? 1 : 0); i < sizeof(exts) / sizeof(exts[0]); i++)
          {
            CCommandMapItem commandMapItem;
            if (i == 0)
              FillCommand(kOpen, mainString, commandMapItem);
            else
            {
              mainString = exts[i];
              commandMapItem.CommandInternalID = kOpen;
              commandMapItem.Verb = (UString)kMainVerb + L".Open." + mainString;
              commandMapItem.HelpString = mainString;
              commandMapItem.ArcType = mainString;
            }
            MyInsertMenu(subMenu, subIndex2++, currentCommandID++, mainString);
            _commandMap.Add(commandMapItem);
          }
          subMenu.Detach();
        }
      }
    }
  }

  if (_fileNames.Size() > 0 && currentCommandID + 10 <= commandIDLast)
  {
    bool needExtract = false;
    for(int i = 0; i < _fileNames.Size(); i++)
    {
      NFile::NFind::CFileInfoW fileInfo;
      if (!fileInfo.Find(_fileNames[i]))
        return E_FAIL;
      if (!fileInfo.IsDir() && DoNeedExtract(fileInfo.Name))
        needExtract = true;
    }
    const UString &fileName = _fileNames.Front();
    if (needExtract)
    {
      UString folderPrefix;
      NFile::NDirectory::GetOnlyDirPrefix(fileName, folderPrefix);
      NFile::NFind::CFileInfoW fileInfo;
      if (!fileInfo.Find(fileName))
        return E_FAIL;
      // Extract
      if ((contextMenuFlags & NContextMenuFlags::kExtract) != 0)
      {
        CCommandMapItem commandMapItem;
        FillCommand(kExtract, mainString, commandMapItem);
        if (_dropMode)
          commandMapItem.Folder = _dropPath;
        else
          commandMapItem.Folder = folderPrefix;
        commandMapItem.Folder += GetSubFolderNameForExtract(fileInfo.Name) + UString(WCHAR_PATH_SEPARATOR);
        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
        _commandMap.Add(commandMapItem);
      }

      // Extract Here
      if ((contextMenuFlags & NContextMenuFlags::kExtractHere) != 0)
      {
        CCommandMapItem commandMapItem;
        FillCommand(kExtractHere, mainString, commandMapItem);
        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
        if (_dropMode)
          commandMapItem.Folder = _dropPath;
        else
          commandMapItem.Folder = folderPrefix;
        _commandMap.Add(commandMapItem);
      }

      // Extract To
      if ((contextMenuFlags & NContextMenuFlags::kExtractTo) != 0)
      {
        CCommandMapItem commandMapItem;
        UString s;
        FillCommand(kExtractTo, s, commandMapItem);
        UString folder;
        if (_fileNames.Size() == 1)
          folder = GetSubFolderNameForExtract(fileInfo.Name);
        else
          folder = L'*';
        if (_dropMode)
          commandMapItem.Folder = _dropPath;
        else
          commandMapItem.Folder = folderPrefix;
        commandMapItem.Folder += folder;
        s = MyFormatNew(s, GetQuotedReducedString(folder + UString(WCHAR_PATH_SEPARATOR)));
        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
        _commandMap.Add(commandMapItem);
      }
      // Test
      if ((contextMenuFlags & NContextMenuFlags::kTest) != 0)
      {
        CCommandMapItem commandMapItem;
        FillCommand(kTest, mainString, commandMapItem);
        MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
        _commandMap.Add(commandMapItem);
      }
    }
    UString archiveName = CreateArchiveName(fileName, _fileNames.Size() > 1, false);
    UString archiveName7z = archiveName + L".7z";
    UString archiveNameZip = archiveName + L".zip";
    UString archivePathPrefix;
    NFile::NDirectory::GetOnlyDirPrefix(fileName, archivePathPrefix);

    // Compress
    if ((contextMenuFlags & NContextMenuFlags::kCompress) != 0)
    {
      CCommandMapItem commandMapItem;
      if (_dropMode)
        commandMapItem.Folder = _dropPath;
      else
        commandMapItem.Folder = archivePathPrefix;
      commandMapItem.ArcName = archiveName;
      FillCommand(kCompress, mainString, commandMapItem);
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
      _commandMap.Add(commandMapItem);
    }

    #ifdef EMAIL_SUPPORT
    // CompressEmail
    if ((contextMenuFlags & NContextMenuFlags::kCompressEmail) != 0 && !_dropMode)
    {
      CCommandMapItem commandMapItem;
      commandMapItem.ArcName = archiveName;
      FillCommand(kCompressEmail, mainString, commandMapItem);
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, mainString);
      _commandMap.Add(commandMapItem);
    }
    #endif

    // CompressTo7z
    if (contextMenuFlags & NContextMenuFlags::kCompressTo7z)
    {
      CCommandMapItem commandMapItem;
      UString s;
      FillCommand(kCompressTo7z, s, commandMapItem);
      if (_dropMode)
        commandMapItem.Folder = _dropPath;
      else
        commandMapItem.Folder = archivePathPrefix;
      commandMapItem.ArcName = archiveName7z;
      commandMapItem.ArcType = L"7z";
      s = MyFormatNew(s, GetQuotedReducedString(archiveName7z));
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
      _commandMap.Add(commandMapItem);
    }

    #ifdef EMAIL_SUPPORT
    // CompressTo7zEmail
    if ((contextMenuFlags & NContextMenuFlags::kCompressTo7zEmail) != 0  && !_dropMode)
    {
      CCommandMapItem commandMapItem;
      UString s;
      FillCommand(kCompressTo7zEmail, s, commandMapItem);
      commandMapItem.ArcName = archiveName7z;
      commandMapItem.ArcType = L"7z";
      s = MyFormatNew(s, GetQuotedReducedString(archiveName7z));
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
      _commandMap.Add(commandMapItem);
    }
    #endif

    // CompressToZip
    if (contextMenuFlags & NContextMenuFlags::kCompressToZip)
    {
      CCommandMapItem commandMapItem;
      UString s;
      FillCommand(kCompressToZip, s, commandMapItem);
      if (_dropMode)
        commandMapItem.Folder = _dropPath;
      else
        commandMapItem.Folder = archivePathPrefix;
      commandMapItem.ArcName = archiveNameZip;
      commandMapItem.ArcType = L"zip";
      s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip));
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
      _commandMap.Add(commandMapItem);
    }

    #ifdef EMAIL_SUPPORT
    // CompressToZipEmail
    if ((contextMenuFlags & NContextMenuFlags::kCompressToZipEmail) != 0  && !_dropMode)
    {
      CCommandMapItem commandMapItem;
      UString s;
      FillCommand(kCompressToZipEmail, s, commandMapItem);
      commandMapItem.ArcName = archiveNameZip;
      commandMapItem.ArcType = L"zip";
      s = MyFormatNew(s, GetQuotedReducedString(archiveNameZip));
      MyInsertMenu(popupMenu, subIndex++, currentCommandID++, s);
      _commandMap.Add(commandMapItem);
    }
    #endif
  }


  // don't use InsertMenu:  See MSDN:
  // PRB: Duplicate Menu Items In the File Menu For a Shell Context Menu Extension
  // ID: Q214477

  if (ci.Cascaded)
  {
    CMenuItem menuItem;
    menuItem.fType = MFT_STRING;
    menuItem.fMask = MIIM_SUBMENU | MIIM_TYPE | MIIM_ID;
    menuItem.wID = currentCommandID++;
    menuItem.hSubMenu = popupMenu.Detach();
    menuDestroyer.Disable();
    menuItem.StringValue = LangString(IDS_CONTEXT_POPUP_CAPTION, 0x02000101);
    CMenu menu;
    menu.Attach(hMenu);
    menu.InsertItem(indexMenu++, true, menuItem);
  }

  return MAKE_HRESULT(SEVERITY_SUCCESS, 0, currentCommandID - commandIDFirst);
}


int CZipContextMenu::FindVerb(const UString &verb)
{
  for(int i = 0; i < _commandMap.Size(); i++)
    if (_commandMap[i].Verb.Compare(verb) == 0)
      return i;
  return -1;
}

static UString Get7zFmPath()
{
  UString path;
  GetProgramFolderPath(path);
  return path + L"7zFM.exe";
}

STDMETHODIMP CZipContextMenu::InvokeCommand(LPCMINVOKECOMMANDINFO commandInfo)
{
  // ::OutputDebugStringA("1");
  int commandOffset;

  // It's fix for bug: crashing in XP. See example in MSDN: "Creating Context Menu Handlers".

  #ifndef UNDER_CE
  if (commandInfo->cbSize == sizeof(CMINVOKECOMMANDINFOEX) &&
      (commandInfo->fMask & CMIC_MASK_UNICODE) != 0)
  {
    LPCMINVOKECOMMANDINFOEX commandInfoEx = (LPCMINVOKECOMMANDINFOEX)commandInfo;
    if (HIWORD(commandInfoEx->lpVerbW) == 0)
      commandOffset = LOWORD(commandInfo->lpVerb);
    else
      commandOffset = FindVerb(commandInfoEx->lpVerbW);
  }
  else
  #endif
    if (HIWORD(commandInfo->lpVerb) == 0)
      commandOffset = LOWORD(commandInfo->lpVerb);
    else
      commandOffset = FindVerb(GetUnicodeString(commandInfo->lpVerb));

  if (commandOffset < 0 || commandOffset >= _commandMap.Size())
    return E_FAIL;

  const CCommandMapItem commandMapItem = _commandMap[commandOffset];
  ECommandInternalID cmdID = commandMapItem.CommandInternalID;

  try
  {
    switch(cmdID)
    {



( run in 1.671 second using v1.01-cache-2.11-cpan-364913b4093 )