zipObject.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2013 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. #include "io/zip/zipObject.h"
  23. #include "memory/safeDelete.h"
  24. //////////////////////////////////////////////////////////////////////////
  25. // Constructor/Destructor
  26. //////////////////////////////////////////////////////////////////////////
  27. ZipObject::ZipObject()
  28. {
  29. mZipArchive = NULL;
  30. }
  31. ZipObject::~ZipObject()
  32. {
  33. closeArchive();
  34. }
  35. IMPLEMENT_CONOBJECT(ZipObject);
  36. //////////////////////////////////////////////////////////////////////////
  37. // Protected Methods
  38. //////////////////////////////////////////////////////////////////////////
  39. StreamObject *ZipObject::createStreamObject(Stream *stream)
  40. {
  41. for(S32 i = 0;i < mStreamPool.size();++i)
  42. {
  43. StreamObject *so = mStreamPool[i];
  44. if(so == NULL)
  45. {
  46. // Reuse any free locations in the pool
  47. so = new StreamObject(stream);
  48. so->registerObject();
  49. mStreamPool[i] = so;
  50. return so;
  51. }
  52. if(so->getStream() == NULL)
  53. {
  54. // Existing unused stream, update it and return it
  55. so->setStream(stream);
  56. return so;
  57. }
  58. }
  59. // No free object found, create a new one
  60. StreamObject *so = new StreamObject(stream);
  61. so->registerObject();
  62. mStreamPool.push_back(so);
  63. return so;
  64. }
  65. //////////////////////////////////////////////////////////////////////////
  66. // Public Methods
  67. //////////////////////////////////////////////////////////////////////////
  68. bool ZipObject::openArchive(const char *filename, Zip::ZipArchive::AccessMode mode /* = Read */)
  69. {
  70. closeArchive();
  71. mZipArchive = new Zip::ZipArchive;
  72. if(mZipArchive->openArchive(filename, mode))
  73. return true;
  74. SAFE_DELETE(mZipArchive);
  75. return false;
  76. }
  77. void ZipObject::closeArchive()
  78. {
  79. if(mZipArchive == NULL)
  80. return;
  81. for(S32 i = 0;i < mStreamPool.size();++i)
  82. {
  83. StreamObject *so = mStreamPool[i];
  84. if(so && so->getStream() != NULL)
  85. closeFile(so);
  86. SAFE_DELETE_OBJECT(mStreamPool[i]);
  87. }
  88. mStreamPool.clear();
  89. mZipArchive->closeArchive();
  90. SAFE_DELETE(mZipArchive);
  91. }
  92. //////////////////////////////////////////////////////////////////////////
  93. StreamObject * ZipObject::openFileForRead(const char *filename)
  94. {
  95. if(mZipArchive == NULL)
  96. return NULL;
  97. Stream *stream;
  98. if((stream = mZipArchive->openFile(filename, Zip::ZipArchive::Read)))
  99. return createStreamObject(stream);
  100. return NULL;
  101. }
  102. StreamObject * ZipObject::openFileForWrite(const char *filename)
  103. {
  104. if(mZipArchive == NULL)
  105. return NULL;
  106. Stream *stream;
  107. if((stream = mZipArchive->openFile(filename, Zip::ZipArchive::Write)))
  108. return createStreamObject(stream);
  109. return NULL;
  110. }
  111. void ZipObject::closeFile(StreamObject *stream)
  112. {
  113. if(mZipArchive == NULL)
  114. return;
  115. #ifdef TORQUE_DEBUG
  116. bool found = false;
  117. for(S32 i = 0;i < mStreamPool.size();++i)
  118. {
  119. StreamObject *so = mStreamPool[i];
  120. if(so && so == stream)
  121. {
  122. found = true;
  123. break;
  124. }
  125. }
  126. AssertFatal(found, "ZipObject::closeFile() - Attempting to close stream not opened by this ZipObject");
  127. #endif
  128. mZipArchive->closeFile(stream->getStream());
  129. stream->setStream(NULL);
  130. }
  131. //////////////////////////////////////////////////////////////////////////
  132. bool ZipObject::addFile(const char *filename, const char *pathInZip, bool replace /* = true */)
  133. {
  134. return mZipArchive->addFile(filename, pathInZip, replace);
  135. }
  136. bool ZipObject::extractFile(const char *pathInZip, const char *filename)
  137. {
  138. return mZipArchive->extractFile(pathInZip, filename);
  139. }
  140. bool ZipObject::deleteFile(const char *filename)
  141. {
  142. return mZipArchive->deleteFile(filename);
  143. }
  144. //////////////////////////////////////////////////////////////////////////
  145. S32 ZipObject::getFileEntryCount()
  146. {
  147. return mZipArchive ? mZipArchive->numEntries() : 0;
  148. }
  149. const char *ZipObject::getFileEntry(S32 idx)
  150. {
  151. if(mZipArchive == NULL)
  152. return "";
  153. const Zip::CentralDir &dir = (*mZipArchive)[idx];
  154. char buffer[1024];
  155. dSprintf(buffer, sizeof(buffer), "%s\t%d\t%d\t%d\t%08x",
  156. dir.mFilename, dir.mUncompressedSize, dir.mCompressedSize,
  157. dir.mCompressMethod, dir.mCRC32);
  158. return StringTable->insert(buffer, true);
  159. }
  160. //////////////////////////////////////////////////////////////////////////
  161. // Console Methods
  162. //////////////////////////////////////////////////////////////////////////
  163. static const struct
  164. {
  165. const char *strMode;
  166. Zip::ZipArchive::AccessMode mode;
  167. } gModeMap[]=
  168. {
  169. { "read", Zip::ZipArchive::Read },
  170. { "write", Zip::ZipArchive::Write },
  171. { "readwrite", Zip::ZipArchive::ReadWrite },
  172. { NULL, (Zip::ZipArchive::AccessMode)0 }
  173. };
  174. //////////////////////////////////////////////////////////////////////////
  175. ConsoleMethod(ZipObject, openArchive, bool, 3, 4, "(filename, [accessMode = Read]) Open a zip file"
  176. "@param filename The file's name\n"
  177. "@param accessMode The mode in which to open the file (default Read)\n"
  178. "@return Returns true on success, false otherwise"
  179. "@sa closeArchive, openFileForRead, openFileForWrite, closeFile" )
  180. {
  181. Zip::ZipArchive::AccessMode mode = Zip::ZipArchive::Read;
  182. if(argc > 3)
  183. {
  184. for(S32 i = 0;gModeMap[i].strMode;++i)
  185. {
  186. if(dStricmp(gModeMap[i].strMode, argv[3]) == 0)
  187. {
  188. mode = gModeMap[i].mode;
  189. break;
  190. }
  191. }
  192. }
  193. char buf[512];
  194. Con::expandPath(buf, sizeof(buf), argv[2]);
  195. return object->openArchive(buf, mode);
  196. }
  197. ConsoleMethod(ZipObject, closeArchive, void, 2, 2, "() Close the zip file\n"
  198. "@return No return value.")
  199. {
  200. object->closeArchive();
  201. }
  202. //////////////////////////////////////////////////////////////////////////
  203. ConsoleMethod(ZipObject, openFileForRead, S32, 3, 3, "(filename) Open a file within the zip for reading\n"
  204. "@param filename The file's name to open in current zip file\n"
  205. "@return The file stream ID as an integer or zero on failure.")
  206. {
  207. StreamObject *stream = object->openFileForRead(argv[2]);
  208. return stream ? stream->getId() : 0;
  209. }
  210. ConsoleMethod(ZipObject, openFileForWrite, S32, 3, 3, "(filename) Open a file within the zip for writing\n"
  211. "@param filename The file's name to open in current zip file\n"
  212. "@return The file stream ID as an integer or 0 on failure.")
  213. {
  214. StreamObject *stream = object->openFileForWrite(argv[2]);
  215. return stream ? stream->getId() : 0;
  216. }
  217. ConsoleMethod(ZipObject, closeFile, void, 3, 3, "(stream) Close a file within the zip"
  218. "@param stream The file stream ID\n"
  219. "@return No return value.")
  220. {
  221. StreamObject *stream = dynamic_cast<StreamObject *>(Sim::findObject(argv[2]));
  222. if(stream == NULL)
  223. {
  224. Con::errorf("ZipObject::closeFile - Invalid stream specified");
  225. return;
  226. }
  227. object->closeFile(stream);
  228. }
  229. //////////////////////////////////////////////////////////////////////////
  230. ConsoleMethod(ZipObject, addFile, bool, 4, 5, "(filename, pathInZip[, replace = true]) Add a file to the zip\n"
  231. "@param filename The name of the file\n"
  232. "@param pathInZip The internal (to the zip) path to the file\n"
  233. "@param replace Set whether to replace the file if one already exists with the name in the path (default true)"
  234. "@return Returns true on success and false otherwise")
  235. {
  236. // Left this line commented out as it was useful when i had a problem
  237. // with the zip's i was creating. [2/21/2007 justind]
  238. // [tom, 2/21/2007] To is now a warnf() for better visual separation in the console
  239. // Con::errorf("zipAdd: %s", argv[2]);
  240. //Con::warnf(" To: %s", argv[3]);
  241. return object->addFile(argv[2], argv[3], argc > 4 ? dAtob(argv[4]) : true);
  242. }
  243. ConsoleMethod(ZipObject, extractFile, bool, 4, 4, "(pathInZip, filename) Extract a file from the zip"
  244. "@param pathInZip The internal path of the desired file\n"
  245. "@param filename The file's name\n"
  246. "@return Returns true on success and false otherwise")
  247. {
  248. return object->extractFile(argv[2], argv[3]);
  249. }
  250. ConsoleMethod(ZipObject, deleteFile, bool, 3, 3, "(pathInZip) Delete a file from the zip"
  251. "@param pathInZip The full internal path of the file\n"
  252. "@return Returns true on success and false otherwise.")
  253. {
  254. return object->deleteFile(argv[2]);
  255. }
  256. //////////////////////////////////////////////////////////////////////////
  257. ConsoleMethod(ZipObject, getFileEntryCount, S32, 2, 2, "() Get number of files in the zip\n"
  258. "@return Returns the number of files found in zip")
  259. {
  260. return object->getFileEntryCount();
  261. }
  262. ConsoleMethod(ZipObject, getFileEntry, const char *, 3, 3, "(index) Get file entry.\n"
  263. "@param index Index to file entry\n"
  264. "@return Returns tab separated string containing filename, uncompressed size, compressed size, compression method and CRC32")
  265. {
  266. return object->getFileEntry(dAtoi(argv[2]));
  267. }