/Framework/qzlib.cpp

https://github.com/DavidXanatos/NeoLoader · C++ · 222 lines · 186 code · 28 blank · 8 comment · 75 complexity · fee2c9b525e317482ca7a5323f69ecf9 MD5 · raw file

  1. #include "GlobalHeader.h"
  2. #include "qzlib.h"
  3. QByteArray Pack(const QByteArray& Data)
  4. {
  5. uLongf newsize = Data.size() + 300;
  6. QByteArray Buffer;
  7. Buffer.resize(newsize);
  8. int result = compress2((byte*)Buffer.data(),&newsize,(byte*)Data.data(),Data.size(),Z_BEST_COMPRESSION);
  9. Buffer.truncate(newsize);
  10. ASSERT(result == Z_OK);
  11. return Buffer;
  12. }
  13. QByteArray Unpack(const QByteArray& Data)
  14. {
  15. QByteArray Buffer;
  16. uLongf newsize = Data.size()*10+300;
  17. uLongf unpackedsize = 0;
  18. int result = 0;
  19. do
  20. {
  21. Buffer.resize(newsize);
  22. unpackedsize = newsize;
  23. result = uncompress((byte*)Buffer.data(),&unpackedsize,(byte*)Data.data(),Data.size());
  24. newsize *= 2; // size for the next try if needed
  25. }
  26. while (result == Z_BUF_ERROR && newsize < Max(MB2B(16), (uLongf)(Data.size()*100))); // do not allow the unzip buffer to grow infinetly,
  27. // assume that no packetcould be originaly larger than the UnpackLimit nd those it must be damaged
  28. if (result == Z_OK)
  29. Buffer.truncate(unpackedsize);
  30. else
  31. Buffer.clear();
  32. return Buffer;
  33. }
  34. // gzip ////////////////////////////////////////////////
  35. bool gzip_arr(QByteArray& in)
  36. {
  37. QByteArray out;
  38. out.resize(in.size() + 16);
  39. z_stream zlibStreamStruct;
  40. zlibStreamStruct.zalloc = Z_NULL; // Set zalloc, zfree, and opaque to Z_NULL so
  41. zlibStreamStruct.zfree = Z_NULL; // that when we call deflateInit2 they will be
  42. zlibStreamStruct.opaque = Z_NULL; // updated to use default allocation functions.
  43. zlibStreamStruct.total_out = 0; // Total number of output bytes produced so far
  44. zlibStreamStruct.next_in = (Bytef*)in.data(); // Pointer to input bytes
  45. zlibStreamStruct.avail_in = in.size(); // Number
  46. int res = deflateInit2(&zlibStreamStruct, Z_BEST_COMPRESSION, Z_DEFLATED, (15+16), 8, Z_DEFAULT_STRATEGY);
  47. if (res!= Z_OK) return false;
  48. do {
  49. zlibStreamStruct.next_out = (Bytef*)out.data() + zlibStreamStruct.total_out;
  50. zlibStreamStruct.avail_out = out.size() - zlibStreamStruct.total_out;
  51. res = deflate(&zlibStreamStruct, Z_FINISH);
  52. } while ( res == Z_OK );
  53. deflateEnd(&zlibStreamStruct);
  54. out.truncate(zlibStreamStruct.total_out);
  55. if(out.size() < in.size())
  56. {
  57. in = out;
  58. return true;
  59. }
  60. return false;
  61. }
  62. static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
  63. /* gzip flag byte */
  64. #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
  65. #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
  66. #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
  67. #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
  68. #define COMMENT 0x10 /* bit 4 set: file comment present */
  69. #define RESERVED 0xE0 /* bits 5..7: reserved */
  70. int get_byte(QByteArray& zipped)
  71. {
  72. if(zipped.isEmpty())
  73. return EOF;
  74. unsigned char c = zipped.at(0);
  75. zipped.remove(0,1);
  76. return c;
  77. }
  78. int check_header(z_stream *stream, QByteArray& zipped)
  79. {
  80. int method; /* method byte */
  81. int flags; /* flags byte */
  82. uInt len;
  83. int c;
  84. /* Check the gzip magic header */
  85. for(len = 0; len < 2; len++) {
  86. c = get_byte(zipped);
  87. if(c != gz_magic[len]) {
  88. if(len != 0) stream->avail_in++, stream->next_in--;
  89. if(c != EOF) {
  90. stream->avail_in++, stream->next_in--;
  91. //do not support transparent streams
  92. return stream->avail_in != 0 ? Z_DATA_ERROR : Z_STREAM_END;
  93. }
  94. return stream->avail_in != 0 ? Z_OK : Z_STREAM_END;
  95. }
  96. }
  97. method = get_byte(zipped);
  98. flags = get_byte(zipped);
  99. if(method != Z_DEFLATED || (flags & RESERVED) != 0)
  100. return Z_DATA_ERROR;
  101. /* Discard time, xflags and OS code: */
  102. for(len = 0; len < 6; len++) (void)get_byte(zipped);
  103. if((flags & EXTRA_FIELD) != 0) { /* skip the extra field */
  104. len = (uInt)get_byte(zipped);
  105. len += ((uInt)get_byte(zipped))<<8;
  106. /* len is garbage if EOF but the loop below will quit anyway */
  107. while(len-- != 0 && get_byte(zipped) != EOF) ;
  108. }
  109. if((flags & ORIG_NAME) != 0) { /* skip the original file name */
  110. while((c = get_byte(zipped)) != 0 && c != EOF) ;
  111. }
  112. if((flags & COMMENT) != 0) { /* skip the .gz file comment */
  113. while((c = get_byte(zipped)) != 0 && c != EOF) ;
  114. }
  115. if((flags & HEAD_CRC) != 0) { /* skip the header crc */
  116. for(len = 0; len < 2; len++) (void)get_byte(zipped);
  117. }
  118. //return Z_DATA_ERROR if we hit EOF?
  119. return Z_OK;
  120. }
  121. bool IsgZiped(const QByteArray& zipped)
  122. {
  123. if(zipped.size() < 2 || (Byte)zipped.at(0) != gz_magic[0] || (Byte)zipped.at(1) != gz_magic[1])
  124. return false;
  125. return true;
  126. }
  127. QByteArray ungzip_arr(z_stream* &zS, QByteArray& zipped, bool bGZip, int iRecursion /*= 0*/)
  128. {
  129. QByteArray unzipped;
  130. unzipped.resize(zipped.size() * 2 * (iRecursion + 1));
  131. int err = Z_DATA_ERROR;
  132. try
  133. {
  134. if (zS == NULL)
  135. {
  136. zS = new z_stream;
  137. zS->zalloc = (alloc_func)0;
  138. zS->zfree = (free_func)0;
  139. zS->opaque = (voidpf)0;
  140. if(bGZip)
  141. {
  142. err = inflateInit2(zS, -MAX_WBITS);
  143. if (err != Z_OK)
  144. return QByteArray();
  145. err = check_header(zS, zipped);
  146. if (err != Z_OK)
  147. return QByteArray();
  148. }
  149. else
  150. {
  151. err = inflateInit(zS);
  152. if (err != Z_OK)
  153. return QByteArray();
  154. }
  155. }
  156. if(iRecursion == 0)
  157. {
  158. zS->next_in = const_cast<Bytef*>((Byte*)zipped.data());
  159. zS->avail_in = zipped.size();
  160. }
  161. zS->next_out = (Byte*)unzipped.data();
  162. zS->avail_out = unzipped.size();
  163. uLong totalUnzipped = zS->total_out;
  164. err = inflate(zS, Z_SYNC_FLUSH);
  165. if (err == Z_STREAM_END)
  166. {
  167. err = inflateEnd(zS);
  168. if (err != Z_OK)
  169. return QByteArray();
  170. unzipped.truncate(zS->total_out - totalUnzipped);
  171. delete zS;
  172. zS = NULL;
  173. }
  174. else if (err == Z_OK)
  175. {
  176. unzipped.truncate(zS->total_out - totalUnzipped);
  177. if((zS->avail_out == 0) && (zS->avail_in != 0))
  178. unzipped.append(ungzip_arr(zS, zipped, bGZip, iRecursion + 1));
  179. }
  180. }
  181. catch (...){
  182. err = Z_DATA_ERROR;
  183. ASSERT(0);
  184. }
  185. if(err != Z_OK)
  186. return QByteArray();
  187. return unzipped;
  188. }
  189. void clear_z(z_stream* &zS)
  190. {
  191. inflateEnd(zS);
  192. delete zS;
  193. zS = NULL;
  194. }