title: How to convert minizip wrapper to unicode?
body: <p>I am trying to use minzip wrapper from [http://www.zlib.net/] for zipping a folder. It works fine  as long as the file names are in english. Has anyone tried to modify minizip to support unicode?</p>
  
  <p>The modified code is posted below. The problem is with this function, the second argument takes const char* as the input. When I do the conversion  it looses data and files names are not the same. </p>
  
  <p>eg: Chinese-統一碼.txt becomes Chinese-t+ƒS+Çtáü.txt inside zip. </p>
  
  <pre><code>err = zipOpenNewFileInZip3_64(  zf,outstr.c_str(),&amp;zi,
                                          NULL,0,NULL,0,NULL /* comment*/,
                                          (opt_compress_level != 0) ? Z_DEFLATED : 0,
                                          opt_compress_level,0,
                                          /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
                                          -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                          password,crcFile, zip64);
  
  
  
  
  
  
  
  
  minizip.c
  Version 1.1, February 14h, 2010
  sample part of the MiniZip project - ( http://www.winimage.com/zLibDll/minizip.html )
  
  Copyright (C) 1998-2010 Gilles Vollant (minizip) ( http://www.winimage.com/zLibDll/minizip.html )
  
  Modifications of Unzip for Zip64
  Copyright (C) 2007-2008 Even Rouault
  
  Modifications for Zip64 support on both zip and unzip
  Copyright (C) 2009-2010 Mathias Svensson ( http://result42.com )
  */
  
  
  #if (!defined(_WIN32)) &amp;&amp; (!defined(WIN32)) &amp;&amp; (!defined(__APPLE__))
  #ifndef __USE_FILE_OFFSET64
  #define __USE_FILE_OFFSET64
  #endif
  #ifndef __USE_LARGEFILE64
  #define __USE_LARGEFILE64
  #endif
  #ifndef _LARGEFILE64_SOURCE
  #define _LARGEFILE64_SOURCE
  #endif
  #ifndef _FILE_OFFSET_BIT
  #define _FILE_OFFSET_BIT 64
  #endif
  #endif
  
  #ifdef __APPLE__
  // In darwin and perhaps other BSD variants off_t is a 64 bit value, hence no need for specific 64 bit functions
  #define FOPEN_FUNC(filename, mode) fopen(filename, mode)
  #define FTELLO_FUNC(stream) ftello(stream)
  #define FSEEKO_FUNC(stream, offset, origin) fseeko(stream, offset, origin)
  #else
  #define FOPEN_FUNC(filename, mode) fopen64(filename, mode)
  #define FTELLO_FUNC(stream) ftello64(stream)
  #define FSEEKO_FUNC(stream, offset, origin) fseeko64(stream, offset, origin)
  #endif
  
  #include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;string.h&gt;
  #include &lt;time.h&gt;
  #include &lt;errno.h&gt;
  #include &lt;fcntl.h&gt;
  #ifdef _WIN32
  # include &lt;direct.h&gt;
  # include &lt;io.h&gt;
  #define GetCurrentDir _getcwd
  #else
  # include &lt;unistd.h&gt;
  # include &lt;utime.h&gt;
  # include &lt;sys/types.h&gt;
  # include &lt;sys/stat.h&gt;
  #endif
  
  #include "zip.h"
  #include "Shlwapi.h"
  
  #ifdef _WIN32
  #define USEWIN32IOAPI
  #include "iowin32.h"
  #endif
  
  #include &lt;windows.h&gt;
  #include &lt;string&gt;
  #include &lt;iostream&gt;
  #include &lt;list&gt;
  #include &lt;fstream&gt;
  #include &lt;sstream&gt;
  #include &lt;set&gt;
  using namespace std;
  
  #define WRITEBUFFERSIZE (16384)
  #define MAXFILENAME (256)
  
  #ifdef _WIN32
  uLong filetime(
      wchar_t *f,                /* name of file to get info on */
      tm_zip *tmzip,             /* return value: access, modific. and creation times */
      uLong *dt)           /* dostime */
  {
      int ret = 0;
      {
          FILETIME ftLocal;
          HANDLE hFind;
          _WIN32_FIND_DATAW ff32;
  
          hFind = FindFirstFileW(f,&amp;ff32);
          if (hFind != INVALID_HANDLE_VALUE)
          {
              FileTimeToLocalFileTime(&amp;(ff32.ftLastWriteTime),&amp;ftLocal);
              FileTimeToDosDateTime(&amp;ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
              FindClose(hFind);
              ret = 1;
          }
      }
      return ret;
  }
  #else
  #ifdef unix || __APPLE__
  uLong filetime(f, tmzip, dt)
      char *f;               /* name of file to get info on */
  tm_zip *tmzip;         /* return value: access, modific. and creation times */
  uLong *dt;             /* dostime */
  {
      int ret=0;
      struct stat s;        /* results of stat() */
      struct tm* filedate;
      time_t tm_t=0;
  
      if (strcmp(f,"-")!=0)
      {
          char name[MAXFILENAME+1];
          int len = strlen(f);
          if (len &gt; MAXFILENAME)
              len = MAXFILENAME;
  
          strncpy(name, f,MAXFILENAME-1);
          /* strncpy doesnt append the trailing NULL, of the string is too long. */
          name[ MAXFILENAME ] = '\0';
  
          if (name[len - 1] == '/')
              name[len - 1] = '\0';
          /* not all systems allow stat'ing a file with / appended */
          if (stat(name,&amp;s)==0)
          {
              tm_t = s.st_mtime;
              ret = 1;
          }
      }
      filedate = localtime(&amp;tm_t);
  
      tmzip-&gt;tm_sec  = filedate-&gt;tm_sec;
      tmzip-&gt;tm_min  = filedate-&gt;tm_min;
      tmzip-&gt;tm_hour = filedate-&gt;tm_hour;
      tmzip-&gt;tm_mday = filedate-&gt;tm_mday;
      tmzip-&gt;tm_mon  = filedate-&gt;tm_mon ;
      tmzip-&gt;tm_year = filedate-&gt;tm_year;
  
      return ret;
  }
  #else
  uLong filetime(f, tmzip, dt)
      char *f;                /* name of file to get info on */
  tm_zip *tmzip;             /* return value: access, modific. and creation times */
  uLong *dt;             /* dostime */
  {
      return 0;
  }
  #endif
  #endif
  
  void addFileToList(list&lt;wstring&gt;&amp; fileList, const wstring&amp; directory, const set&lt;wstring&gt;&amp; excludeFilterSet, const wstring&amp; fileName )
  {
      wstring fileExtension = fileName.substr(fileName.find_last_of(L".") + 1);
      if (!fileExtension.empty()) 
      {
          if (excludeFilterSet.find(fileExtension) != excludeFilterSet.end()) return;
      } 
  
      fileList.push_back(directory + fileName);
  }
  
  void GetFileListing(list&lt;wstring&gt;&amp; fileList, wstring directory,const set&lt;wstring&gt;&amp; excludeFilterSet,bool recursively=true)
  {
      directory = directory + L"\\";
      wstring filter = directory + L"*";
  
      _WIN32_FIND_DATAW FindFileData;
      HANDLE hFind = FindFirstFileW(filter.c_str(), &amp;FindFileData);
  
      if (hFind == INVALID_HANDLE_VALUE)
      {
          DWORD dwError = GetLastError();
          if (dwError != ERROR_FILE_NOT_FOUND)
          {
              //cout &lt;&lt; "Invalid file handle for filter " &lt;&lt; filter &lt;&lt; ". Error is " &lt;&lt; GetLastError() &lt;&lt; endl;
          }
          return;
      }
  
      do
      {
          if (FindFileData.dwFileAttributes &amp; FILE_ATTRIBUTE_DIRECTORY) 
          {
              if ((recursively) &amp;&amp; (wcscmp(FindFileData.cFileName, L".") != 0) &amp;&amp; (wcscmp(FindFileData.cFileName, L"..") != 0))
              {
                  GetFileListing(fileList, directory + FindFileData.cFileName, excludeFilterSet);
              }
          } 
          else
          {
              addFileToList(fileList, directory, excludeFilterSet,FindFileData.cFileName);
          }
      } while (FindNextFileW(hFind, &amp;FindFileData) != 0);
  
      DWORD dwError = GetLastError();
      FindClose(hFind);
  
      if (dwError != ERROR_NO_MORE_FILES)
      {
          //cout &lt;&lt; "FindNextFile error. Error is "&lt;&lt; dwError &lt;&lt; endl;
      }
  }
  
  
  int check_exist_file(wchar_t* filename)
  {
      FILE* ftestexist;
      int ret = 1;
      //ftestexist = FOPEN_FUNC(filename,"rb");
      ftestexist = _wfopen(filename,L"rb");
      if (ftestexist==NULL)
          ret = 0;
      else
          fclose(ftestexist);
      return ret;
  }
  
  /* calculate the CRC32 of a file,
  because to encrypt a file, we need known the CRC32 of the file before */
  int getFileCrc(const wchar_t * filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)
  {
      unsigned long calculate_crc=0;
      int err=ZIP_OK;
      //FILE * fin = FOPEN_FUNC(filenameinzip,"rb");
      FILE * fin = _wfopen(filenameinzip,L"rb");
  
      unsigned long size_read = 0;
      unsigned long total_read = 0;
      if (fin==NULL)
      {
          err = ZIP_ERRNO;
      }
  
      if (err == ZIP_OK)
          do
          {
              err = ZIP_OK;
              size_read = (int)fread(buf,1,size_buf,fin);
              if (size_read &lt; size_buf)
                  if (feof(fin)==0)
                  {
                      printf("error in reading %s\n",filenameinzip);
                      err = ZIP_ERRNO;
                  }
  
                  if (size_read&gt;0)
                      calculate_crc = crc32(calculate_crc,(const Bytef *)buf,size_read);
                  total_read += size_read;
  
          } while ((err == ZIP_OK) &amp;&amp; (size_read&gt;0));
  
          if (fin)
              fclose(fin);
  
          *result_crc=calculate_crc;
          printf("file %s crc %lx\n", filenameinzip, calculate_crc);
          return err;
  }
  
  int isLargeFile(const wchar_t * filename)
  {
      int largeFile = 0;
      ZPOS64_T pos = 0;
      //FILE* pFile = FOPEN_FUNC(filename, "rb");
      FILE* pFile = _wfopen(filename, L"rb");
  
      if(pFile != NULL)
      {
          int n = FSEEKO_FUNC(pFile, 0, SEEK_END);
          pos = FTELLO_FUNC(pFile);
  
          printf("File : %s is %lld bytes\n", filename, pos);
  
          if(pos &gt;= 0xffffffff)
              largeFile = 1;
  
          fclose(pFile);
      }
  
      return largeFile;
  }
  
  void split( const wstring&amp; text, wchar_t delimiter,set&lt;wstring&gt;&amp; result )
  {
      wstring::size_type start = 0;
      wstring::size_type end   = text.find( delimiter, start );
      wstring token;
  
      while( end != wstring::npos )
      {
          token = text.substr( start, end - start );
          token.erase(0,2);
          result.insert( token );
          start = end + 1;
          end   = text.find( delimiter, start );
      }
  
      // Add the last string
      token = text.substr(start);
      token = token.erase(0,2);
      result.insert(token);
  }
  
  //Do not call me.
  long getUTF8size(const wchar_t *string){
      if (!string)
          return 0;
      long res=0;
      for (;*string;string++){
          if (*string&lt;0x80)
              res++;
          else if (*string&lt;0x800)
              res+=2;
          else
              res+=3;
      }
      return res;
  }
  
  char *WChar_to_UTF8(const wchar_t *string){
      long fSize=getUTF8size(string);
      char *res=new char[fSize+1];
      res[fSize]=0;
      if (!string)
          return res;
      long b=0;
      for (;*string;string++,b++){
          if (*string&lt;0x80)
              res[b]=(char)*string;
          else if (*string&lt;0x800){
              res[b++]=(*string&gt;&gt;6)|192;
              res[b]=*string&amp;63|128;
          }else{
              res[b++]=(*string&gt;&gt;12)|224;
              res[b++]=((*string&amp;4095)&gt;&gt;6)|128;
              res[b]=*string&amp;63|128;
          }
      }
      return res;
  }
  
  
  std::string utf8_encode(const std::wstring &amp;wstr)
  {
      int size_needed = WideCharToMultiByte(CP_UTF8, 0, &amp;wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
      std::string strTo( size_needed, 0 );
      WideCharToMultiByte                  (CP_UTF8, 0, &amp;wstr[0], (int)wstr.size(), &amp;strTo[0], size_needed, NULL, NULL);
      return strTo;
  }
  
  
  wstring zipper( const wstring&amp; directoryPath, const wstring&amp; strExcludeFilter, wstring &amp; zipFileName )
  {
      int opt_overwrite=0,opt_compress_level=Z_BEST_COMPRESSION,opt_exclude_path=0,err=0,size_buf=0;
      void* buf=NULL;
      const char* password=NULL;
      list&lt;wstring&gt; fileList;
      DWORD dwRet;
  
      wchar_t cCurrentPath[MAX_PATH];
      dwRet = GetCurrentDirectoryW(MAX_PATH, cCurrentPath);
      if( dwRet == 0 )
      {
          return wstring();
      }
  
      // Change the directory to the current folder
      _wchdir(directoryPath.c_str());
      set&lt;wstring&gt; excludeFilterSet;
      split(strExcludeFilter,'|',excludeFilterSet);
  
      GetFileListing(fileList, directoryPath,excludeFilterSet);
      opt_overwrite = 1;
  
      size_buf = WRITEBUFFERSIZE;
      buf = (void*)malloc(size_buf);
      if (buf==NULL) return wstring();
  
      wchar_t tempDirPath[MAX_PATH];
      dwRet = GetTempPathW (MAX_PATH, tempDirPath);
      if( dwRet == 0 ) return wstring();
  
      wstring directoryName,zipFilePath;
      _WIN32_FIND_DATAW FindFileData;
      HANDLE hFind = FindFirstFileW(directoryPath.c_str(), &amp;FindFileData);
      if (FindFileData.dwFileAttributes &amp; FILE_ATTRIBUTE_DIRECTORY) 
      {
          directoryName = FindFileData.cFileName;
      }
  
      zipFilePath = wstring(tempDirPath)+L"\\"+directoryName+L".zip";
      zipFile zf;
      int errclose;
  
      #ifdef USEWIN32IOAPI
          zlib_filefunc64_def ffunc;
          fill_win32_filefunc64W (&amp;ffunc);
          zf = zipOpen2_64(zipFilePath.c_str(),(opt_overwrite==2) ? 2 : 0,NULL,&amp;ffunc);
      #   else
          zf = zipOpen64(zipFilePath.c_str(),(opt_overwrite==2) ? 2 : 0);
      #   endif
  
      if (zf == NULL)
      {
          //printf("error opening %s\n",filename_try);
          err= ZIP_ERRNO;
      }
      else
      {
          //printf("creating %s\n",filename_try);
      }
  
      for(list&lt;wstring&gt;::iterator it = fileList.begin() ; it!=fileList.end();++it) 
      {
          FILE * fin;
          int size_read;
          //const char* filenameinzip = (*it).c_str();
          wstring filenameinzip = (*it).c_str();
          wchar_t szOut[MAX_PATH];
  
          PathRelativePathToW(szOut,
                              directoryPath.c_str(),
                              FILE_ATTRIBUTE_DIRECTORY,
                              filenameinzip.c_str(),
                              FILE_ATTRIBUTE_NORMAL);
  
          wchar_t *savefilenameinzip;
          zip_fileinfo zi;
          unsigned long crcFile=0;
          int zip64 = 0;
  
          zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
              zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
          zi.dosDate = 0;
          zi.internal_fa = 0;
      zi.external_fa = 0;
          filetime(szOut,&amp;zi.tmz_date,&amp;zi.dosDate);
  
          if ((password != NULL) &amp;&amp; (err==ZIP_OK))
              err = getFileCrc(szOut,buf,size_buf,&amp;crcFile);
  
          zip64 = isLargeFile(szOut);
  
          /* The path name saved, should not include a leading slash. */
          /*if it did, windows/xp and dynazip couldn't read the zip file. */
          savefilenameinzip = szOut;
          while( savefilenameinzip[0] == '\\' || savefilenameinzip[0] == '/' )
          {
              savefilenameinzip++;
          }
  
          string outstr = utf8_encode(savefilenameinzip);
          //char * op = (char*)outstr.c_str();
  
  
          err = zipOpenNewFileInZip3_64(  zf,outstr.c_str(),&amp;zi,
                                          NULL,0,NULL,0,NULL /* comment*/,
                                          (opt_compress_level != 0) ? Z_DEFLATED : 0,
                                          opt_compress_level,0,
                                          /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
                                          -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
                                          password,crcFile, zip64);
  
          if (err != ZIP_OK)
          {
              //printf("error in opening %s in zipfile\n",szOut);
          }
          else
          {
              //fin = FOPEN_FUNC(szOut,"rb");
              fin = _wfopen(szOut,L"rb");
  
              if (fin==NULL)
              {
                  err=ZIP_ERRNO;
                  //printf("error in opening %s for reading\n",szOut);
              }
          }
  
          if (err == ZIP_OK)
              do
              {
                  err = ZIP_OK;
                  size_read = (int)fread(buf,1,size_buf,fin);
                  if (size_read &lt; size_buf)
                      if (feof(fin)==0)
                      {
                          //printf("error in reading %s\n",szOut);
                          err = ZIP_ERRNO;
                      }
  
                      if (size_read&gt;0)
                      {
                          err = zipWriteInFileInZip (zf,buf,size_read);
                          if (err&lt;0)
                          {
                              //printf("error in writing %s in the zipfile\n",szOut);
                          }
  
                      }
              } while ((err == ZIP_OK) &amp;&amp; (size_read&gt;0));
  
              if (fin)
                  fclose(fin);
  
              if (err&lt;0)
                  err=ZIP_ERRNO;
              else
              {
                  err = zipCloseFileInZip(zf);
                  if (err!=ZIP_OK)
                  {
                      //printf("error in closing %s in the zipfile\n",szOut);
                  }
              }
      }
  
      errclose = zipClose(zf,NULL);
      if (errclose != ZIP_OK)
      {
          //printf("error in closing %s\n",filename_try);
      }
  
      free(buf);
      // Change back the executabe context
      _wchdir(cCurrentPath);
      return zipFilePath;
  }
  </code></pre>