00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifndef __CS_ARCHIVE_H__
00021 #define __CS_ARCHIVE_H__
00022
00027 #include "csextern.h"
00028
00029 #include "iutil/databuff.h"
00030 #include "iutil/vfs.h"
00031 #include "csutil/csstring.h"
00032 #include "csutil/databuf.h"
00033 #include "csutil/parray.h"
00034 #include "csutil/ref.h"
00035 #include "csutil/stringarray.h"
00036 #include "csutil/zip.h"
00037
00038 struct csFileTime;
00039
00059 class CS_CRYSTALSPACE_EXPORT csArchive
00060 {
00061 public:
00062 static const char hdr_central[4];
00063 static const char hdr_local[4];
00064 static const char hdr_endcentral[4];
00065 static const char hdr_extlocal[4];
00066
00067 private:
00069 class ArchiveEntry
00070 {
00071 public:
00072 char *filename;
00073 ZIP_central_directory_file_header info;
00074 char *buffer;
00075 size_t buffer_pos;
00076 size_t buffer_size;
00077 char *extrafield, *comment;
00078 bool faked;
00079
00080 ArchiveEntry (const char *name, ZIP_central_directory_file_header &cdfh);
00081 ~ArchiveEntry ();
00082 bool Append (const void *data, size_t size);
00083 bool WriteLFH (iFile* file);
00084 bool WriteCDFH (iFile* file);
00085 bool ReadExtraField (iFile* file, size_t extra_field_length);
00086 bool ReadFileComment (iFile* file, size_t file_comment_length);
00087 bool WriteFile (iFile* file);
00088 void FreeBuffer ();
00089 };
00090 friend class ArchiveEntry;
00091
00093 class CS_CRYSTALSPACE_EXPORT ArchiveEntryVector
00094 : public csPDelArray<ArchiveEntry, CS::Container::ArrayAllocDefault,
00095 csArrayCapacityFixedGrow<256> >
00096 {
00097 public:
00098 ArchiveEntryVector () : csPDelArray<ArchiveEntry,
00099 CS::Container::ArrayAllocDefault, csArrayCapacityFixedGrow<256> > (256) {}
00100 static int Compare (ArchiveEntry* const& Item1, ArchiveEntry* const& Item2)
00101 { return strcmp (Item1->filename, Item2->filename); }
00102 static int CompareKey (ArchiveEntry* const& Item, char const* const& Key)
00103 { return strcmp (Item->filename, Key); }
00104 };
00105
00106 ArchiveEntryVector dir;
00107 csStringArray del;
00108 csArray<ArchiveEntry*> lazy;
00109
00110 char *filename;
00111
00112 csRef<iFile> file;
00113
00114 size_t comment_length;
00115 char *comment;
00116
00117 void ReadDirectory ();
00118 bool IsDeleted (const char *name) const;
00119 void UnpackTime (ush zdate, ush ztime, csFileTime &rtime) const;
00120 void PackTime (const csFileTime &ztime, ush &rdate, ush &rtime) const;
00121 bool ReadArchiveComment (iFile* file, size_t zipfile_comment_length);
00122 void LoadECDR (ZIP_end_central_dir_record &ecdr, char *buff);
00123 bool ReadCDFH (ZIP_central_directory_file_header &cdfh, iFile* file);
00124 bool ReadLFH (ZIP_local_file_header &lfh, iFile* file);
00125 bool WriteECDR (ZIP_end_central_dir_record &ecdr, iFile* file);
00126 bool WriteZipArchive ();
00127 bool WriteCentralDirectory (iFile* temp);
00128 void UpdateDirectory ();
00129 void ReadZipDirectory (iFile *infile);
00130 ArchiveEntry *InsertEntry (const char *name,
00131 ZIP_central_directory_file_header &cdfh);
00132 void ReadZipEntries (iFile* infile);
00133 bool ReadEntry (iFile* infile, ArchiveEntry *f, char* buf);
00134 ArchiveEntry *CreateArchiveEntry (const char *name,
00135 size_t size = 0, bool pack = true);
00136 void ResetArchiveEntry (ArchiveEntry *f, size_t size, bool pack);
00137
00138 public:
00140 csArchive (const char *filename);
00142 ~csArchive ();
00143
00145 void Dir () const;
00146
00161 void *NewFile (const char *name, size_t size = 0, bool pack = true);
00162
00167 bool DeleteFile (const char *name);
00168
00173 bool FileExists (const char *name, size_t *size = 0) const;
00174
00181 char *Read (const char *name, size_t *size = 0);
00182
00187 template<typename Allocator>
00188 csPtr<iDataBuffer> Read (const char *name, Allocator& alloc)
00189 {
00190 ArchiveEntry *f = (ArchiveEntry *) FindName (name);
00191
00192 if (!f)
00193 return 0;
00194
00195 csRef<iDataBuffer> buf;
00196 buf.AttachNew (new CS::DataBuffer<Allocator> (f->info.ucsize, alloc));
00197 if (!ReadEntry (file, f, buf->GetData()))
00198 return 0;
00199 return csPtr<iDataBuffer> (buf);
00200 }
00201
00206 csPtr<iDataBuffer> Read (const char *name)
00207 {
00208 CS::Memory::AllocatorMalloc alloc;
00209 return Read (name, alloc);
00210 }
00211
00218 bool Write (void *entry, const char *data, size_t size);
00219
00229 bool Flush ();
00230
00232 void *GetFile (size_t no)
00233 { return (no < dir.GetSize ()) ? dir.Get (no) : 0; }
00234
00236 void *FindName (const char *name) const;
00238 char *GetFileName (void *entry) const
00239 { return ((ArchiveEntry*)entry)->filename; }
00241 size_t GetFileSize (void *entry) const
00242 { return ((ArchiveEntry*)entry)->info.ucsize; }
00244 void GetFileTime (void *entry, csFileTime &ztime) const;
00246 void SetFileTime (void *entry, const csFileTime &ztime);
00247
00249 char *GetName () const
00250 { return filename; }
00252 char *GetComment () const
00253 { return comment; }
00254 };
00255
00256 inline void csArchive::GetFileTime (void *entry, csFileTime &ztime) const
00257 {
00258 if (entry)
00259 {
00260 UnpackTime (((ArchiveEntry*)entry)->info.last_mod_file_date,
00261 ((ArchiveEntry*)entry)->info.last_mod_file_time,
00262 ztime);
00263 }
00264 }
00265
00266 inline void csArchive::SetFileTime (void *entry, const csFileTime &ztime)
00267 {
00268 if (entry)
00269 {
00270 PackTime (ztime,
00271 ((ArchiveEntry*)entry)->info.last_mod_file_date,
00272 ((ArchiveEntry*)entry)->info.last_mod_file_time);
00273 }
00274 }
00275
00276 #endif // __CS_ARCHIVE_H__