]> de.git.xonotic.org Git - xonotic/netradiant.git/blob - contrib/pk3man/pak.cpp
* added pk3man and fixed it to compile for latest radiant
[xonotic/netradiant.git] / contrib / pk3man / pak.cpp
1 // Pak.cpp: implementation of the CPak class.
2 //
3 //////////////////////////////////////////////////////////////////////
4
5 #include "stdafx.h"
6 #include "pak.h"
7
8 //////////////////////////////////////////////////////////////////////
9 // Construction/Destruction
10 //////////////////////////////////////////////////////////////////////
11
12 CPak::CPak()
13 {
14         m_bModified=FALSE;
15         
16 }
17
18 CPak::~CPak()
19 {
20         Close();
21 }
22
23
24 bool CPak::Open(const char *filename)
25 {
26         Close();
27         
28         unzFile uf=NULL;
29
30         uf = unzOpen(filename);
31         if (uf==NULL)
32                 return FALSE;
33
34         unz_global_info gi;
35         int err = unzGetGlobalInfo (uf,&gi);
36         if (err!=UNZ_OK)
37         {
38                 Close();
39                 return FALSE;
40         }
41
42         m_filename=filename;
43
44         // ok, now build the internal list of entries
45
46         unzGoToFirstFile(uf);
47
48         do
49         {
50                 pak_entry pe;
51
52                 pe.frompak=TRUE;
53                 pe.pakname=m_filename;
54                 pe.rename=FALSE;
55
56                 char filename_inzip[256];
57                 unz_file_info file_info;
58                 //              uLong ratio=0;
59                 //              const char *string_method;
60                 err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
61                 if (err!=UNZ_OK)
62                 {
63                         continue;
64                 }
65                 
66                 pe.filename=filename_inzip;
67                 pe.compressed=file_info.compressed_size;
68                 pe.uncompressed=file_info.uncompressed_size;
69
70                 entries.push_back(pe);
71
72         } while (unzGoToNextFile(uf)==UNZ_OK);
73         
74
75         unzClose(uf);
76         m_bModified=FALSE;
77
78         return TRUE;
79 }
80
81 bool CPak::Save(const char *path)
82 {
83         if (!m_bModified)
84                 return FALSE;
85
86         if (path==NULL)
87                 return FALSE;
88
89         //      unzFile uf=NULL;
90         zipFile zf=NULL;
91         
92         zf=zipOpen(path,0);
93
94         for ( std::list<pak_entry>::const_iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++)
95         {
96                 pak_entry pe=*iEntry;
97
98                 if (pe.frompak)
99                 {
100                         if (pe.pakname.compare(m_filename)==0)
101                         {
102                                 // its in this pak
103                                 long size;
104                                 unsigned char *buf=Extract(pe.filename.c_str(),size);
105
106                                 if (!buf)
107                                         continue;
108
109                                 zip_fileinfo zipfi;
110
111                                 std::string name=pe.filename;
112                                 if (pe.rename)
113                                         name=pe.newname;
114
115                                 zipOpenNewFileInZip(zf,name.c_str(),&zipfi,NULL,0,NULL,0,NULL,Z_DEFLATED,Z_DEFAULT_COMPRESSION);
116                                 zipWriteInFileInZip(zf,buf,size);
117                                 zipCloseFileInZip(zf);
118
119                                 delete buf;
120                         }
121                         else
122                         {
123                                 // its in another pack
124
125                                 CPak p;
126                                 if (!p.Open(pe.pakname.c_str()))
127                                         continue;
128
129                                 long size;
130                                 unsigned char *buf=p.Extract(pe.filename.c_str(),size);
131
132                                 if (!buf)
133                                         continue;
134
135                                 zip_fileinfo zipfi;
136
137                                 std::string name=pe.filename;
138                                 if (pe.rename)
139                                         name=pe.newname;
140
141                                 zipOpenNewFileInZip(zf,name.c_str(),&zipfi,NULL,0,NULL,0,NULL,Z_DEFLATED,Z_DEFAULT_COMPRESSION);
142                                 zipWriteInFileInZip(zf,buf,size);
143                                 zipCloseFileInZip(zf);
144
145                                 delete buf;
146                         }
147
148                 }
149                 else
150                 {
151                         // its an external file
152
153                         FILE *fp;
154                         fp=fopen(pe.pathname.c_str(),"rb");
155
156                         if (!fp)
157                                 continue;
158
159                         fseek(fp,0,SEEK_END);
160                         long size=ftell(fp);
161                         fseek(fp,0,0);
162                         unsigned char *buf=new unsigned char[size];
163                         fread(buf,sizeof(unsigned char),size,fp);
164                         fclose(fp);
165
166                         if (!buf)
167                                 continue;
168
169                         zip_fileinfo zipfi;
170
171                         std::string name=pe.filename;
172                         if (pe.rename)
173                                 name=pe.newname;
174
175                         zipOpenNewFileInZip(zf,name.c_str(),&zipfi,NULL,0,NULL,0,NULL,Z_DEFLATED,Z_DEFAULT_COMPRESSION);
176                         zipWriteInFileInZip(zf,buf,size);
177                         zipCloseFileInZip(zf);
178
179                         delete buf;
180
181                 }
182         
183         }
184
185         zipClose(zf,"Created by Pk3man - http://pk3man.sourceforge.net");
186
187         m_bModified=FALSE;
188         return TRUE;
189 }
190
191 void CPak::Close()
192 {
193
194         m_filename="";
195         entries.clear();
196         m_bModified=FALSE;
197
198 }
199
200 bool CPak::IsModified()
201 {
202         return m_bModified;
203 }
204
205 pak_entry CPak::FindPE(const char *path)
206 {
207         pak_entry pe;   
208
209         for ( std::list<pak_entry>::const_iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++)
210         {
211                 pe=*iEntry;
212
213                 if (!pe.rename && pe.filename.compare(path)==0)
214                         return pe;
215
216                 if (pe.rename && pe.newname.compare(path)==0)
217                         return pe;
218         }
219
220         pe.compressed=0;
221         pe.uncompressed=0;
222
223         return pe;
224 }
225
226 bool CPak::IsEmpty()
227 {
228         return entries.empty();
229 }
230
231 unsigned char *CPak::Extract(const char *path, long &size)
232 {
233         unzFile uf=NULL;
234
235         uf = unzOpen(m_filename.GetBuffer());
236         if (uf==NULL)
237                 return FALSE;
238
239         unz_global_info gi;
240         int err = unzGetGlobalInfo (uf,&gi);
241         if (err!=UNZ_OK)
242         {
243                 Close();
244                 return FALSE;
245         }
246         
247         unzGoToFirstFile(uf);
248
249         do
250         {
251                 char filename_inzip[256];
252                 unz_file_info file_info;
253                                 
254                 err = unzGetCurrentFileInfo(uf,&file_info,filename_inzip,sizeof(filename_inzip),NULL,0,NULL,0);
255                 
256                 if (err!=UNZ_OK)
257                 {
258                         unzClose(uf);
259                         return FALSE;
260                 }
261                 
262                 size=file_info.uncompressed_size;
263
264                 if (strcmp(path,filename_inzip)==0)
265                 {
266                         // found it
267                         // extract it
268                         
269                         if (unzOpenCurrentFile(uf)!=UNZ_OK)
270                         {
271                                 unzClose(uf);
272                                 return NULL;
273                         }
274                                                 
275                         unsigned char *buf=new unsigned char[size];
276                         unzReadCurrentFile(uf,buf,size);
277                         unzCloseCurrentFile(uf);
278                         unzClose(uf);
279                         return buf;
280                 }
281
282         } while (unzGoToNextFile(uf)==UNZ_OK);
283
284
285         unzClose(uf);
286         return NULL;
287 }
288
289 bool CPak::ExtractTo(const char *path, char *pathto)
290 {
291         long size;
292         unsigned char *buf=Extract(path,size);
293         
294         if (!buf)
295                 return FALSE;
296         
297         FILE *f=fopen(pathto,"wb");
298         if (f)
299         {                               
300                 fwrite(buf,sizeof(unsigned char),size,f);
301                 fclose(f);
302                 delete buf;
303                 return TRUE;
304         }       
305
306         delete buf;
307         return FALSE;
308 }
309
310 bool CPak::IsInPak(const char *path)
311 {
312         pak_entry pe;   
313
314         for ( std::list<pak_entry>::const_iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++)
315         {
316                 pe=*iEntry;
317
318                 if (!pe.rename && pe.filename.compare(path)==0)
319                         return TRUE;
320
321                 if (pe.rename && pe.newname.compare(path)==0)
322                         return TRUE;
323         }
324
325         return FALSE;
326 }
327
328 bool CPak::AddExternalFile(const char *name,const char *path)
329 {
330
331         FILE *fp;
332         fp=fopen(path,"rb");
333
334         if (!fp)
335                 return FALSE;
336
337         fseek(fp,0,SEEK_END);
338         long size=ftell(fp);
339         fclose(fp);
340         
341         pak_entry pe;
342
343         pe.rename=FALSE;
344         pe.frompak=FALSE;
345         pe.pathname=path;
346         pe.filename=name;
347         pe.compressed=size;
348         pe.uncompressed=size;
349         
350         entries.push_back(pe);
351
352         m_bModified=TRUE;
353
354         return TRUE;
355
356 }
357
358 bool CPak::AddPakFile(const char *name,const char *pakname,long comp, long uncomp)
359 {
360         pak_entry pe;
361
362         pe.rename=FALSE;
363         pe.frompak=TRUE;
364
365         pe.filename=name;
366         pe.pakname=pakname;
367         pe.pathname="";
368         
369         pe.compressed=comp;
370         pe.uncompressed=uncomp;
371         
372         entries.push_back(pe);
373
374         m_bModified=TRUE;
375
376         return TRUE;
377 }
378
379 bool CPak::Delete(const char *path)
380 {
381         pak_entry pe;   
382
383         for ( std::list<pak_entry>::iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++)
384         {
385                 pe=*iEntry;
386
387                 if ((!pe.rename && pe.filename.compare(path)==0) || (pe.rename && pe.newname.compare(path)==0))
388                 {
389                         entries.erase(iEntry);
390                         m_bModified=TRUE;
391                         return TRUE;
392                 }
393         }
394
395         return FALSE;
396 }
397
398 bool CPak::Rename(const char *path,const char *newname)
399 {
400         pak_entry pe;   
401
402         for ( std::list<pak_entry>::iterator iEntry = entries.begin() ; iEntry != entries.end() ; iEntry++)
403         {
404                 pe=*iEntry;
405
406                 if ((!pe.rename && pe.filename.compare(path)==0) || (pe.rename && pe.newname.compare(path)==0))
407                 {
408                         entries.erase(iEntry);
409                         
410                         pe.rename=TRUE;
411                         pe.newname=newname;
412
413                         entries.push_back(pe);
414                         m_bModified=TRUE;
415
416                         return TRUE;
417                 }
418         }
419
420         return FALSE;
421 }