home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / wxos2240.zip / wxWindows-2.4.0 / src / common / fs_zip.cpp < prev    next >
C/C++ Source or Header  |  2002-12-16  |  6KB  |  230 lines

  1. /////////////////////////////////////////////////////////////////////////////
  2. // Name:        fs_zip.cpp
  3. // Purpose:     ZIP file system
  4. // Author:      Vaclav Slavik
  5. // Copyright:   (c) 1999 Vaclav Slavik
  6. // CVS-ID:      $Id: fs_zip.cpp,v 1.18.2.5 2002/12/16 00:16:05 VS Exp $
  7. // Licence:     wxWindows Licence
  8. /////////////////////////////////////////////////////////////////////////////
  9.  
  10.  
  11.  
  12. #ifdef __GNUG__
  13. #pragma implementation "fs_zip.h"
  14. #endif
  15.  
  16. #include "wx/wxprec.h"
  17.  
  18. #ifdef __BORLANDC__
  19. #pragma hdrstop
  20. #endif
  21.  
  22. #if wxUSE_FILESYSTEM && wxUSE_FS_ZIP && wxUSE_ZIPSTREAM
  23.  
  24. #ifndef WXPRECOMP
  25.     #include "wx/intl.h"
  26.     #include "wx/log.h"
  27. #endif
  28.  
  29. #include "wx/hash.h"
  30. #include "wx/filesys.h"
  31. #include "wx/zipstrm.h"
  32. #include "wx/fs_zip.h"
  33.  
  34. /* Not the right solution (paths in makefiles) but... */
  35. #ifdef __BORLANDC__
  36. #include "../common/unzip.h"
  37. #else
  38. #include "unzip.h"
  39. #endif
  40.  
  41.  
  42. //--------------------------------------------------------------------------------
  43. // wxZipFSHandler
  44. //--------------------------------------------------------------------------------
  45.  
  46.  
  47.  
  48. wxZipFSHandler::wxZipFSHandler() : wxFileSystemHandler()
  49. {
  50.     m_Archive = NULL;
  51.     m_ZipFile = m_Pattern = m_BaseDir = wxEmptyString;
  52.     m_AllowDirs = m_AllowFiles = TRUE;
  53.     m_DirsFound = NULL;
  54. }
  55.  
  56.  
  57.  
  58. wxZipFSHandler::~wxZipFSHandler()
  59. {
  60.     if (m_Archive)
  61.         unzClose((unzFile)m_Archive);
  62.     if (m_DirsFound)
  63.         delete m_DirsFound;
  64. }
  65.  
  66.  
  67.  
  68. bool wxZipFSHandler::CanOpen(const wxString& location)
  69. {
  70.     wxString p = GetProtocol(location);
  71.     return (p == wxT("zip")) &&
  72.            (GetProtocol(GetLeftLocation(location)) == wxT("file"));
  73. }
  74.  
  75.  
  76.  
  77.  
  78. wxFSFile* wxZipFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs), const wxString& location)
  79. {
  80.     wxString right = GetRightLocation(location);
  81.     wxString left = GetLeftLocation(location);
  82.     wxInputStream *s;
  83.  
  84.     if (GetProtocol(left) != wxT("file"))
  85.     {
  86.         wxLogError(_("ZIP handler currently supports only local files!"));
  87.         return NULL;
  88.     }
  89.  
  90.     if (right.GetChar(0) == wxT('/')) right = right.Mid(1);
  91.  
  92.     wxFileName leftFilename = wxFileSystem::URLToFileName(left);
  93.  
  94.     s = new wxZipInputStream(leftFilename.GetFullPath(), right);
  95.     if (s && s->IsOk() )
  96.     {
  97.         return new wxFSFile(s,
  98.                             left + wxT("#zip:") + right,
  99.                             GetMimeTypeFromExt(location),
  100.                             GetAnchor(location),
  101.                             wxDateTime(wxFileModificationTime(left)));
  102.     }
  103.  
  104.     delete s;
  105.     return NULL;
  106. }
  107.  
  108.  
  109.  
  110. wxString wxZipFSHandler::FindFirst(const wxString& spec, int flags)
  111. {
  112.     wxString right = GetRightLocation(spec);
  113.     wxString left = GetLeftLocation(spec);
  114.  
  115.     if (right.Last() == wxT('/')) right.RemoveLast();
  116.  
  117.     if (m_Archive)
  118.     {
  119.         unzClose((unzFile)m_Archive);
  120.         m_Archive = NULL;
  121.     }
  122.  
  123.     if (GetProtocol(left) != wxT("file"))
  124.     {
  125.         wxLogError(_("ZIP handler currently supports only local files!"));
  126.         return wxEmptyString;
  127.     }
  128.  
  129.     switch (flags)
  130.     {
  131.         case wxFILE:
  132.             m_AllowDirs = FALSE, m_AllowFiles = TRUE; break;
  133.         case wxDIR:
  134.             m_AllowDirs = TRUE, m_AllowFiles = FALSE; break;
  135.         default:
  136.             m_AllowDirs = m_AllowFiles = TRUE; break;
  137.     }
  138.  
  139.     m_ZipFile = left;
  140.     wxString nativename = wxFileSystem::URLToFileName(m_ZipFile).GetFullPath();
  141.     m_Archive = (void*) unzOpen(nativename.mb_str());
  142.     m_Pattern = right.AfterLast(wxT('/'));
  143.     m_BaseDir = right.BeforeLast(wxT('/'));
  144.  
  145.     if (m_Archive)
  146.     {
  147.         if (unzGoToFirstFile((unzFile)m_Archive) != UNZ_OK)
  148.         {
  149.             unzClose((unzFile)m_Archive);
  150.             m_Archive = NULL;
  151.         }
  152.         else
  153.         {
  154.             if (m_AllowDirs)
  155.             {
  156.                 delete m_DirsFound;
  157.                 m_DirsFound = new wxHashTableLong();
  158.             }
  159.             return DoFind();
  160.         }
  161.     }
  162.     return wxEmptyString;
  163. }
  164.  
  165.  
  166.  
  167. wxString wxZipFSHandler::FindNext()
  168. {
  169.     if (!m_Archive) return wxEmptyString;
  170.     return DoFind();
  171. }
  172.  
  173.  
  174.  
  175. wxString wxZipFSHandler::DoFind()
  176. {
  177.     static char namebuf[1024]; // char, not wxChar!
  178.     char *c;
  179.     wxString namestr, dir, filename;
  180.     wxString match = wxEmptyString;
  181.  
  182.     while (match == wxEmptyString)
  183.     {
  184.         unzGetCurrentFileInfo((unzFile)m_Archive, NULL, namebuf, 1024, NULL, 0, NULL, 0);
  185.         for (c = namebuf; *c; c++) if (*c == '\\') *c = '/';
  186.         namestr = wxString::FromAscii( namebuf );    // TODO what encoding does ZIP use?
  187.  
  188.         if (m_AllowDirs)
  189.         {
  190.             dir = namestr.BeforeLast(wxT('/'));
  191.             while (!dir.IsEmpty())
  192.             {
  193.                 long key = 0;
  194.                 for (size_t i = 0; i < dir.Length(); i++) key += (wxUChar)dir[i];
  195.                 if (m_DirsFound->Get(key) == wxNOT_FOUND)
  196.                 {
  197.                     m_DirsFound->Put(key, 1);
  198.                     filename = dir.AfterLast(wxT('/'));
  199.                     dir = dir.BeforeLast(wxT('/'));
  200.                     if (!filename.IsEmpty() && m_BaseDir == dir &&
  201.                                 wxMatchWild(m_Pattern, filename, FALSE))
  202.                         match = m_ZipFile + wxT("#zip:") + dir + wxT("/") + filename;
  203.                 }
  204.                 else
  205.                     break; // already tranversed
  206.             }
  207.         }
  208.  
  209.         filename = namestr.AfterLast(wxT('/'));
  210.         dir = namestr.BeforeLast(wxT('/'));
  211.         if (m_AllowFiles && !filename.IsEmpty() && m_BaseDir == dir &&
  212.                             wxMatchWild(m_Pattern, filename, FALSE))
  213.             match = m_ZipFile + wxT("#zip:") + namestr;
  214.  
  215.         if (unzGoToNextFile((unzFile)m_Archive) != UNZ_OK)
  216.         {
  217.             unzClose((unzFile)m_Archive);
  218.             m_Archive = NULL;
  219.             break;
  220.         }
  221.     }
  222.  
  223.     return match;
  224. }
  225.  
  226.  
  227.  
  228. #endif
  229.       //wxUSE_FILESYSTEM && wxUSE_FS_ZIP && wxUSE_ZIPSTREAM
  230.