/modules/libjar/zipwriter/src/nsZipDataStream.cpp

http://github.com/zpao/v8monkey · C++ · 219 lines · 137 code · 31 blank · 51 comment · 12 complexity · c5fd25c4ec65709aaca11819bf70920e MD5 · raw file

  1. /* ***** BEGIN LICENSE BLOCK *****
  2. * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  3. *
  4. * The contents of this file are subject to the Mozilla Public License Version
  5. * 1.1 (the "License"); you may not use this file except in compliance with
  6. * the License. You may obtain a copy of the License at
  7. * http://www.mozilla.org/MPL/
  8. *
  9. * Software distributed under the License is distributed on an "AS IS" basis,
  10. * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  11. * for the specific language governing rights and limitations under the
  12. * License.
  13. *
  14. * The Original Code is Zip Writer Component.
  15. *
  16. * The Initial Developer of the Original Code is
  17. * Dave Townsend <dtownsend@oxymoronical.com>.
  18. *
  19. * Portions created by the Initial Developer are Copyright (C) 2007
  20. * the Initial Developer. All Rights Reserved.
  21. *
  22. * Contributor(s):
  23. * Mook <mook.moz+random.code@gmail.com>
  24. *
  25. * Alternatively, the contents of this file may be used under the terms of
  26. * either the GNU General Public License Version 2 or later (the "GPL"), or
  27. * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  28. * in which case the provisions of the GPL or the LGPL are applicable instead
  29. * of those above. If you wish to allow use of your version of this file only
  30. * under the terms of either the GPL or the LGPL, and not to allow others to
  31. * use your version of this file under the terms of the MPL, indicate your
  32. * decision by deleting the provisions above and replace them with the notice
  33. * and other provisions required by the GPL or the LGPL. If you do not delete
  34. * the provisions above, a recipient may use your version of this file under
  35. * the terms of any one of the MPL, the GPL or the LGPL.
  36. *
  37. * ***** END LICENSE BLOCK *****
  38. */
  39. #include "StreamFunctions.h"
  40. #include "nsZipDataStream.h"
  41. #include "nsIStringStream.h"
  42. #include "nsISeekableStream.h"
  43. #include "nsDeflateConverter.h"
  44. #include "nsNetUtil.h"
  45. #include "nsComponentManagerUtils.h"
  46. #include "nsMemory.h"
  47. #define ZIP_METHOD_STORE 0
  48. #define ZIP_METHOD_DEFLATE 8
  49. /**
  50. * nsZipDataStream handles the writing an entry's into the zip file.
  51. * It is set up to wither write the data as is, or in the event that compression
  52. * has been requested to pass it through a stream converter.
  53. * Currently only the deflate compression method is supported.
  54. * The CRC checksum for the entry's data is also generated here.
  55. */
  56. NS_IMPL_THREADSAFE_ISUPPORTS2(nsZipDataStream, nsIStreamListener,
  57. nsIRequestObserver)
  58. nsresult nsZipDataStream::Init(nsZipWriter *aWriter,
  59. nsIOutputStream *aStream,
  60. nsZipHeader *aHeader,
  61. PRInt32 aCompression)
  62. {
  63. mWriter = aWriter;
  64. mHeader = aHeader;
  65. mStream = aStream;
  66. mHeader->mCRC = crc32(0L, Z_NULL, 0);
  67. nsresult rv = NS_NewSimpleStreamListener(getter_AddRefs(mOutput), aStream,
  68. nsnull);
  69. NS_ENSURE_SUCCESS(rv, rv);
  70. if (aCompression > 0) {
  71. mHeader->mMethod = ZIP_METHOD_DEFLATE;
  72. nsCOMPtr<nsIStreamConverter> converter =
  73. new nsDeflateConverter(aCompression);
  74. NS_ENSURE_TRUE(converter, NS_ERROR_OUT_OF_MEMORY);
  75. rv = converter->AsyncConvertData("uncompressed", "rawdeflate", mOutput,
  76. nsnull);
  77. NS_ENSURE_SUCCESS(rv, rv);
  78. mOutput = do_QueryInterface(converter, &rv);
  79. NS_ENSURE_SUCCESS(rv, rv);
  80. }
  81. else {
  82. mHeader->mMethod = ZIP_METHOD_STORE;
  83. }
  84. return NS_OK;
  85. }
  86. /* void onDataAvailable (in nsIRequest aRequest, in nsISupports aContext,
  87. * in nsIInputStream aInputStream,
  88. * in unsigned long aOffset, in unsigned long aCount); */
  89. NS_IMETHODIMP nsZipDataStream::OnDataAvailable(nsIRequest *aRequest,
  90. nsISupports *aContext,
  91. nsIInputStream *aInputStream,
  92. PRUint32 aOffset,
  93. PRUint32 aCount)
  94. {
  95. if (!mOutput)
  96. return NS_ERROR_NOT_INITIALIZED;
  97. nsAutoArrayPtr<char> buffer(new char[aCount]);
  98. NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
  99. nsresult rv = ZW_ReadData(aInputStream, buffer.get(), aCount);
  100. NS_ENSURE_SUCCESS(rv, rv);
  101. return ProcessData(aRequest, aContext, buffer.get(), aOffset, aCount);
  102. }
  103. /* void onStartRequest (in nsIRequest aRequest, in nsISupports aContext); */
  104. NS_IMETHODIMP nsZipDataStream::OnStartRequest(nsIRequest *aRequest,
  105. nsISupports *aContext)
  106. {
  107. if (!mOutput)
  108. return NS_ERROR_NOT_INITIALIZED;
  109. return mOutput->OnStartRequest(aRequest, aContext);
  110. }
  111. /* void onStopRequest (in nsIRequest aRequest, in nsISupports aContext,
  112. * in nsresult aStatusCode); */
  113. NS_IMETHODIMP nsZipDataStream::OnStopRequest(nsIRequest *aRequest,
  114. nsISupports *aContext,
  115. nsresult aStatusCode)
  116. {
  117. if (!mOutput)
  118. return NS_ERROR_NOT_INITIALIZED;
  119. nsresult rv = mOutput->OnStopRequest(aRequest, aContext, aStatusCode);
  120. mOutput = nsnull;
  121. if (NS_FAILED(rv)) {
  122. mWriter->EntryCompleteCallback(mHeader, rv);
  123. }
  124. else {
  125. rv = CompleteEntry();
  126. rv = mWriter->EntryCompleteCallback(mHeader, rv);
  127. }
  128. mStream = nsnull;
  129. mWriter = nsnull;
  130. mHeader = nsnull;
  131. return rv;
  132. }
  133. inline nsresult nsZipDataStream::CompleteEntry()
  134. {
  135. nsresult rv;
  136. nsCOMPtr<nsISeekableStream> seekable = do_QueryInterface(mStream, &rv);
  137. NS_ENSURE_SUCCESS(rv, rv);
  138. PRInt64 pos;
  139. rv = seekable->Tell(&pos);
  140. NS_ENSURE_SUCCESS(rv, rv);
  141. mHeader->mCSize = pos - mHeader->mOffset - mHeader->GetFileHeaderLength();
  142. mHeader->mWriteOnClose = true;
  143. return NS_OK;
  144. }
  145. nsresult nsZipDataStream::ProcessData(nsIRequest *aRequest,
  146. nsISupports *aContext, char *aBuffer,
  147. PRUint32 aOffset, PRUint32 aCount)
  148. {
  149. mHeader->mCRC = crc32(mHeader->mCRC,
  150. reinterpret_cast<const unsigned char*>(aBuffer),
  151. aCount);
  152. nsresult rv;
  153. nsCOMPtr<nsIStringInputStream> stream =
  154. do_CreateInstance("@mozilla.org/io/string-input-stream;1", &rv);
  155. NS_ENSURE_SUCCESS(rv, rv);
  156. stream->ShareData(aBuffer, aCount);
  157. rv = mOutput->OnDataAvailable(aRequest, aContext, stream, aOffset, aCount);
  158. mHeader->mUSize += aCount;
  159. return rv;
  160. }
  161. nsresult nsZipDataStream::ReadStream(nsIInputStream *aStream)
  162. {
  163. if (!mOutput)
  164. return NS_ERROR_NOT_INITIALIZED;
  165. nsresult rv = OnStartRequest(nsnull, nsnull);
  166. NS_ENSURE_SUCCESS(rv, rv);
  167. nsAutoArrayPtr<char> buffer(new char[4096]);
  168. NS_ENSURE_TRUE(buffer, NS_ERROR_OUT_OF_MEMORY);
  169. PRUint32 read = 0;
  170. PRUint32 offset = 0;
  171. do
  172. {
  173. rv = aStream->Read(buffer.get(), 4096, &read);
  174. if (NS_FAILED(rv)) {
  175. OnStopRequest(nsnull, nsnull, rv);
  176. return rv;
  177. }
  178. if (read > 0) {
  179. rv = ProcessData(nsnull, nsnull, buffer.get(), offset, read);
  180. if (NS_FAILED(rv)) {
  181. OnStopRequest(nsnull, nsnull, rv);
  182. return rv;
  183. }
  184. offset += read;
  185. }
  186. } while (read > 0);
  187. return OnStopRequest(nsnull, nsnull, NS_OK);
  188. }