bool Archive::GetComment(Array<wchar> *CmtData)
{
  if (!MainComment)
    return false;
  SaveFilePos SavePos(*this);

#ifndef SFX_MODULE
  uint CmtLength;
  if (Format==RARFMT14)
  {
    Seek(SFXSize+SIZEOF_MAINHEAD14,SEEK_SET);
    CmtLength=GetByte();
    CmtLength+=(GetByte()<<8);
  }
  else
#endif
  {
    if (MainHead.CommentInHeader)
    {
      // Old style (RAR 2.9) archive comment embedded into the main 
      // archive header.
      Seek(SFXSize+SIZEOF_MARKHEAD3+SIZEOF_MAINHEAD3,SEEK_SET);
      if (!ReadHeader())
        return false;
    }
    else
    {
      // Current (RAR 3.0+) version of archive comment.
      Seek(GetStartPos(),SEEK_SET);
      return SearchSubBlock(SUBHEAD_TYPE_CMT)!=0 && ReadCommentData(CmtData);
    }
#ifndef SFX_MODULE
    // Old style (RAR 2.9) comment header embedded into the main 
    // archive header.
    if (BrokenHeader)
    {
      uiMsg(UIERROR_CMTBROKEN,FileName);
      return false;
    }
    CmtLength=CommHead.HeadSize-SIZEOF_COMMHEAD;
#endif
  }
#ifndef SFX_MODULE
  if ((Format==RARFMT14 && MainHead.PackComment) || (Format!=RARFMT14 && CommHead.Method!=0x30))
  {
    if (Format!=RARFMT14 && (CommHead.UnpVer < 15 || CommHead.UnpVer > VER_UNPACK || CommHead.Method > 0x35))
      return false;
    ComprDataIO DataIO;
    DataIO.SetTestMode(true);
    uint UnpCmtLength;
    if (Format==RARFMT14)
    {
#ifdef RAR_NOCRYPT
      return false;
#else
      UnpCmtLength=GetByte();
      UnpCmtLength+=(GetByte()<<8);
      CmtLength-=2;
      DataIO.SetCmt13Encryption();
      CommHead.UnpVer=15;
#endif
    }
    else
      UnpCmtLength=CommHead.UnpSize;
    DataIO.SetFiles(this,NULL);
    DataIO.EnableShowProgress(false);
    DataIO.SetPackedSizeToRead(CmtLength);
    DataIO.UnpHash.Init(HASH_CRC32,1);
    DataIO.SetNoFileHeader(true); // this->FileHead is not filled yet.

    Unpack CmtUnpack(&DataIO);
    CmtUnpack.Init(0x10000,false);
    CmtUnpack.SetDestSize(UnpCmtLength);
    CmtUnpack.DoUnpack(CommHead.UnpVer,false);

    if (Format!=RARFMT14 && (DataIO.UnpHash.GetCRC32()&0xffff)!=CommHead.CommCRC)
    {
      uiMsg(UIERROR_CMTBROKEN,FileName);
      return false;
    }
    else
    {
      byte *UnpData;
      size_t UnpDataSize;
      DataIO.GetUnpackedData(&UnpData,&UnpDataSize);
#ifdef _WIN_ALL
      // If we ever decide to extend it to Android, we'll need to alloc
      // 4x memory for OEM to UTF-8 output here.
      OemToCharBuffA((char *)UnpData,(char *)UnpData,(DWORD)UnpDataSize);
#endif
      CmtData->Alloc(UnpDataSize+1);
      memset(CmtData->Addr(0),0,CmtData->Size()*sizeof(wchar));
      CharToWide((char *)UnpData,CmtData->Addr(0),CmtData->Size());
      CmtData->Alloc(wcslen(CmtData->Addr(0)));
    }
  }
  else
  {
    if (CmtLength==0)
      return false;
    Array<byte> CmtRaw(CmtLength);
    int ReadSize=Read(&CmtRaw[0],CmtLength);
    if (ReadSize>=0 && (uint)ReadSize<CmtLength) // Comment is shorter than declared.
    {
      CmtLength=ReadSize;
      CmtRaw.Alloc(CmtLength);
    }

    if (Format!=RARFMT14 && CommHead.CommCRC!=(~CRC32(0xffffffff,&CmtRaw[0],CmtLength)&0xffff))
    {
      uiMsg(UIERROR_CMTBROKEN,FileName);
      return false;
    }
    CmtData->Alloc(CmtLength+1);
    CmtRaw.Push(0);
#ifdef _WIN_ALL
    // If we ever decide to extend it to Android, we'll need to alloc
    // 4x memory for OEM to UTF-8 output here.
    OemToCharA((char *)&CmtRaw[0],(char *)&CmtRaw[0]);
#endif
    CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
    CmtData->Alloc(wcslen(CmtData->Addr(0)));
  }
#endif
  return CmtData->Size() > 0;
}


bool Archive::ReadCommentData(Array<wchar> *CmtData)
{
  Array<byte> CmtRaw;
  if (!ReadSubData(&CmtRaw,NULL))
    return false;
  size_t CmtSize=CmtRaw.Size();
  CmtRaw.Push(0);
  CmtData->Alloc(CmtSize+1);
  if (Format==RARFMT50)
    UtfToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
  else
    if ((SubHead.SubFlags & SUBHEAD_FLAGS_CMT_UNICODE)!=0)
    {
      RawToWide(&CmtRaw[0],CmtData->Addr(0),CmtSize/2);
      (*CmtData)[CmtSize/2]=0;

    }
    else
    {
      CharToWide((char *)&CmtRaw[0],CmtData->Addr(0),CmtData->Size());
    }
  CmtData->Alloc(wcslen(CmtData->Addr(0))); // Set buffer size to actual comment length.
  return true;
}


void Archive::ViewComment()
{
  if (Cmd->DisableComment)
    return;
  Array<wchar> CmtBuf;
  if (GetComment(&CmtBuf)) // In GUI too, so "Test" command detects broken comments.
  {
    size_t CmtSize=CmtBuf.Size();
    wchar *ChPtr=wcschr(&CmtBuf[0],0x1A);
    if (ChPtr!=NULL)
      CmtSize=ChPtr-&CmtBuf[0];
    mprintf(L"\n");
    OutComment(&CmtBuf[0],CmtSize);
  }
}


