Stream.cpp 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. #include "Stream.h"
  2. #include "MuException.h"
  3. #include "ObjWrapper.h"
  4. #include "Vcclr.h"
  5. using namespace IO;
  6. using namespace Runtime::InteropServices;
  7. #pragma unmanaged
  8. static fz_stream* OpenStream(fz_context* ctx, const wchar_t* filePath) {
  9. fz_stream* s;
  10. MuTryReturn(ctx, fz_open_file_w(ctx, filePath), s)
  11. }
  12. static fz_stream* OpenStream(fz_context* ctx, const unsigned char* buffer, int length) {
  13. fz_stream* s;
  14. MuTryReturn(ctx, fz_open_memory(ctx, buffer, length), s)
  15. }
  16. static fz_stream* DecodeTiffFax(fz_context* ctx, fz_stream* s, int width, int height, int k, int endOfLine, int encodedByteAlign, int endOfBlock, int blackIs1) {
  17. fz_stream* r;
  18. MuTryReturn(ctx, fz_open_faxd(ctx, s, k, endOfLine, encodedByteAlign, width, height, endOfBlock, blackIs1), r);
  19. }
  20. #pragma managed
  21. MuPDF::Stream::Stream(String^ filePath) {
  22. pin_ptr<const wchar_t> p = PtrToStringChars(filePath);
  23. fz_stream* s = OpenStream(Context::Ptr, (const wchar_t*)p);
  24. if (s) {
  25. _stream = s;
  26. _initDataLength = -1;
  27. return;
  28. }
  29. throw MuException::FromContext();
  30. }
  31. array<Byte>^ MuPDF::Stream::ReadAll(int maxSize) {
  32. if (_data.IsAllocated) {
  33. GcnewArray(Byte, b, maxSize > _initDataLength ? _initDataLength : maxSize);
  34. pin_ptr<Byte> p = &b[0];
  35. fz_read(Context::Ptr, _stream, p, b->Length);
  36. return b;
  37. }
  38. MemoryStream^ ms = gcnew MemoryStream(4096);
  39. BinaryWriter^ bw = gcnew BinaryWriter(ms);
  40. int l;
  41. try {
  42. GcnewArray(Byte, b, 4096);
  43. pin_ptr<Byte> p = &b[0];
  44. while ((l = fz_read(Context::Ptr, _stream, p, 4096)) > 0) {
  45. bw->Write(b, 0, l);
  46. if (ms->Length >= 0x06400000 && ms->Length > maxSize) {
  47. throw gcnew IOException("Compression bomb detected.");
  48. }
  49. }
  50. ms->Flush();
  51. return ms->ToArray();
  52. }
  53. catch (const Exception^) {
  54. throw;
  55. }
  56. finally {
  57. if (ms) { delete ms; }
  58. if (bw) { delete bw; }
  59. }
  60. }
  61. MuPDF::Stream^ MuPDF::Stream::DecodeTiffFax(int width, int height, int k, bool endOfLine, bool encodeByteAlign, bool endOfBlock, bool blackIs1) {
  62. auto s = ::DecodeTiffFax(Context::Ptr, _stream, width, height, k, endOfLine, encodeByteAlign, endOfBlock, blackIs1);
  63. if (s != NULL) {
  64. return gcnew MuPDF::Stream(s);
  65. }
  66. throw MuException::FromContext();
  67. }
  68. MuPDF::Stream::Stream(array<Byte>^ data) {
  69. _data = GCHandle::Alloc(data, GCHandleType::Pinned);
  70. fz_stream* s = OpenStream(Context::Ptr, (const unsigned char*)(void*)(_data.AddrOfPinnedObject()), data->Length);
  71. if (s) {
  72. _stream = s;
  73. _initDataLength = data->Length;
  74. return;
  75. }
  76. throw MuException::FromContext();
  77. }
  78. void MuPDF::Stream::ReleaseHandle() {
  79. fz_drop_stream(Context::Ptr, _stream);
  80. if (_data.IsAllocated) {
  81. _data.Free();
  82. }
  83. _stream = NULL;
  84. }