Compare commits

...

19 Commits

Author SHA1 Message Date
97889060df resource pack manager 2023-02-23 14:50:30 +02:00
c7aa107392 video_core: Rewrite custom textures 2023-02-22 21:22:42 +02:00
77961d2f07 rasterizer_cache: Add support for texture dumping 2023-02-17 20:17:40 +02:00
6cf9c0c7d5 rasterizer_cache: Fix surface validation
* Sometimes the copy interval might be larger than the validation interval
2023-02-16 15:49:23 +02:00
87b23fdb10 common: Move image decoders to common
* Replace the various image interfaces with spng which is very lightweight and fast. Also add a dds header which will be useful when support for that format is implemented
2023-02-15 23:46:52 +02:00
65d9ba7db5 rasterizer_cache: Remove expanded surface immediately
* Since allocations are recycled under the hood there's not risk of a texture being in use
2023-02-15 21:54:33 +02:00
234cfd25ed rasterizer_cache: Explicit type in traits 2023-02-15 21:24:34 +02:00
e67a4a739a video_core: Cleanup surface interface
* Remove unused FramebufferView and make the opengl handles private
2023-02-15 20:55:21 +02:00
c7d315058e video_core: Cleanup microprofiles
* Remove upload/download targets these are covered by the rasterizer cache
2023-02-15 00:27:37 +02:00
df6b36eb67 rasterizer_cache: Support multi-level surfaces
* With this commit the cache can now directly upload and use mipmaps
  without needing to sync them with watchers. By using native mimaps
  directly this also adds support for mipmap for cube

* Since watchers have been removed texture cubes still work but are uncached
  so slower as well. Will be fixed soon.
2023-02-15 00:11:10 +02:00
087bcd8f97 rasterizer_cache: Cleanup texture clears 2023-02-14 22:35:30 +02:00
44c187d705 rasterizer_cache: Wrap common draw operation in FramebufferBase
* Makes the rasterizer draw method much cleaner
2023-02-14 22:35:25 +02:00
a14be97238 rasterizer_cache: Simplify SurfaceBase
* The casts are bit ugly but will be refactored soon
2023-02-13 22:47:07 +02:00
e4502a1a6c video_core: Manage samplers in the rasterizer cache 2023-02-13 22:21:48 +02:00
c57a912e30 rasterizer_cache: Remove BlitSurfaces
* Choose copy or blit based on the caller instead
2023-02-13 21:57:29 +02:00
5615c7be60 rasterizer_cache: Commonize texture acceleration functions
* They don't contain any backend specific code so don't duplicate them
2023-02-13 21:50:47 +02:00
8afe3bc2b6 rasterizer_cache: Move microprofile to the top 2023-02-13 21:42:56 +02:00
b2bc71ccf4 rasterizer_cache: Remove Invalid match flags
* It was specified in every FindMatch. Only copy did not specify it, but copy surfaces ignore the flag regardless making it superflous
2023-02-13 21:38:54 +02:00
6e90a9812f rasterizer_cache: Switch to page table
* Should be more efficient for surface storage than the interval map
2023-02-13 21:33:45 +02:00
136 changed files with 32274 additions and 2434 deletions

6
.gitmodules vendored
View File

@ -43,9 +43,6 @@
[submodule "teakra"]
path = externals/teakra
url = https://github.com/wwylele/teakra.git
[submodule "lodepng"]
path = externals/lodepng/lodepng
url = https://github.com/lvandeve/lodepng.git
[submodule "zstd"]
path = externals/zstd
url = https://github.com/facebook/zstd.git
@ -73,3 +70,6 @@
[submodule "sirit"]
path = externals/sirit
url = https://github.com/GPUCode/sirit
[submodule "zlib-ng"]
path = externals/zlib-ng/zlib-ng
url = https://github.com/zlib-ng/zlib-ng

View File

@ -114,6 +114,12 @@ if (ENABLE_SDL2 AND NOT USE_SYSTEM_SDL2)
add_subdirectory(sdl2)
endif()
# Zlib
add_subdirectory(zlib-ng)
# Minizip
add_subdirectory(minizip)
# Zstandard
set(ZSTD_LEGACY_SUPPORT OFF)
set(ZSTD_BUILD_PROGRAMS OFF)
@ -172,8 +178,8 @@ if (ENABLE_WEB_SERVICE)
target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
endif()
# lodepng
add_subdirectory(lodepng)
# libspng
add_subdirectory(libspng)
# (xperia64): Only use libyuv on Android b/c of build issues on Windows and mandatory JPEG
if(ANDROID)

View File

@ -1,25 +1,27 @@
/*
OpenGL, OpenGL ES loader generated by glad 0.1.36 on Fri Sep 9 09:22:43 2022.
OpenGL, OpenGL ES loader generated by glad 0.1.36 on Tue Feb 21 16:13:52 2023.
Language/Generator: C/C++
Specification: gl
APIs: gl=4.4, gles2=3.2
APIs: gl=4.6, gles2=3.2
Profile: core
Extensions:
GL_ARB_buffer_storage,
GL_ARB_direct_state_access,
GL_ARB_texture_compression_bptc,
GL_EXT_buffer_storage,
GL_EXT_clip_cull_distance
GL_EXT_clip_cull_distance,
GL_EXT_texture_compression_s3tc
Loader: True
Local files: False
Omit khrplatform: False
Reproducible: False
Commandline:
--profile="core" --api="gl=4.4,gles2=3.2" --generator="c" --spec="gl" --extensions="GL_ARB_buffer_storage,GL_ARB_direct_state_access,GL_EXT_buffer_storage,GL_EXT_clip_cull_distance"
--profile="core" --api="gl=4.6,gles2=3.2" --generator="c" --spec="gl" --extensions="GL_ARB_buffer_storage,GL_ARB_direct_state_access,GL_ARB_texture_compression_bptc,GL_EXT_buffer_storage,GL_EXT_clip_cull_distance,GL_EXT_texture_compression_s3tc"
Online:
https://glad.dav1d.de/#profile=core&language=c&specification=gl&loader=on&api=gl%3D4.4&api=gles2%3D3.2&extensions=GL_ARB_buffer_storage&extensions=GL_ARB_direct_state_access&extensions=GL_EXT_buffer_storage&extensions=GL_EXT_clip_cull_distance
https://glad.dav1d.de/#profile=core&language=c&specification=gl&loader=on&api=gl%3D4.6&api=gles2%3D3.2&extensions=GL_ARB_buffer_storage&extensions=GL_ARB_direct_state_access&extensions=GL_ARB_texture_compression_bptc&extensions=GL_EXT_buffer_storage&extensions=GL_EXT_clip_cull_distance&extensions=GL_EXT_texture_compression_s3tc
*/
@ -1472,6 +1474,62 @@ typedef void (APIENTRY *GLVULKANPROCNV)(void);
#define GL_QUERY_BUFFER_BINDING 0x9193
#define GL_QUERY_RESULT_NO_WAIT 0x9194
#define GL_MIRROR_CLAMP_TO_EDGE 0x8743
#define GL_CONTEXT_LOST 0x0507
#define GL_NEGATIVE_ONE_TO_ONE 0x935E
#define GL_ZERO_TO_ONE 0x935F
#define GL_CLIP_ORIGIN 0x935C
#define GL_CLIP_DEPTH_MODE 0x935D
#define GL_QUERY_WAIT_INVERTED 0x8E17
#define GL_QUERY_NO_WAIT_INVERTED 0x8E18
#define GL_QUERY_BY_REGION_WAIT_INVERTED 0x8E19
#define GL_QUERY_BY_REGION_NO_WAIT_INVERTED 0x8E1A
#define GL_MAX_CULL_DISTANCES 0x82F9
#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES 0x82FA
#define GL_TEXTURE_TARGET 0x1006
#define GL_QUERY_TARGET 0x82EA
#define GL_GUILTY_CONTEXT_RESET 0x8253
#define GL_INNOCENT_CONTEXT_RESET 0x8254
#define GL_UNKNOWN_CONTEXT_RESET 0x8255
#define GL_RESET_NOTIFICATION_STRATEGY 0x8256
#define GL_LOSE_CONTEXT_ON_RESET 0x8252
#define GL_NO_RESET_NOTIFICATION 0x8261
#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
#define GL_COLOR_TABLE 0x80D0
#define GL_POST_CONVOLUTION_COLOR_TABLE 0x80D1
#define GL_POST_COLOR_MATRIX_COLOR_TABLE 0x80D2
#define GL_PROXY_COLOR_TABLE 0x80D3
#define GL_PROXY_POST_CONVOLUTION_COLOR_TABLE 0x80D4
#define GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE 0x80D5
#define GL_CONVOLUTION_1D 0x8010
#define GL_CONVOLUTION_2D 0x8011
#define GL_SEPARABLE_2D 0x8012
#define GL_HISTOGRAM 0x8024
#define GL_PROXY_HISTOGRAM 0x8025
#define GL_MINMAX 0x802E
#define GL_CONTEXT_RELEASE_BEHAVIOR 0x82FB
#define GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH 0x82FC
#define GL_SHADER_BINARY_FORMAT_SPIR_V 0x9551
#define GL_SPIR_V_BINARY 0x9552
#define GL_PARAMETER_BUFFER 0x80EE
#define GL_PARAMETER_BUFFER_BINDING 0x80EF
#define GL_CONTEXT_FLAG_NO_ERROR_BIT 0x00000008
#define GL_VERTICES_SUBMITTED 0x82EE
#define GL_PRIMITIVES_SUBMITTED 0x82EF
#define GL_VERTEX_SHADER_INVOCATIONS 0x82F0
#define GL_TESS_CONTROL_SHADER_PATCHES 0x82F1
#define GL_TESS_EVALUATION_SHADER_INVOCATIONS 0x82F2
#define GL_GEOMETRY_SHADER_PRIMITIVES_EMITTED 0x82F3
#define GL_FRAGMENT_SHADER_INVOCATIONS 0x82F4
#define GL_COMPUTE_SHADER_INVOCATIONS 0x82F5
#define GL_CLIPPING_INPUT_PRIMITIVES 0x82F6
#define GL_CLIPPING_OUTPUT_PRIMITIVES 0x82F7
#define GL_POLYGON_OFFSET_CLAMP 0x8E1B
#define GL_SPIR_V_EXTENSIONS 0x9553
#define GL_NUM_SPIR_V_EXTENSIONS 0x9554
#define GL_TEXTURE_MAX_ANISOTROPY 0x84FE
#define GL_MAX_TEXTURE_MAX_ANISOTROPY 0x84FF
#define GL_TRANSFORM_FEEDBACK_OVERFLOW 0x82EC
#define GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW 0x82ED
#define GL_ALIASED_POINT_SIZE_RANGE 0x846D
#define GL_RED_BITS 0x0D52
#define GL_GREEN_BITS 0x0D53
@ -1501,14 +1559,6 @@ typedef void (APIENTRY *GLVULKANPROCNV)(void);
#define GL_HSL_COLOR 0x92AF
#define GL_HSL_LUMINOSITY 0x92B0
#define GL_PRIMITIVE_BOUNDING_BOX 0x92BE
#define GL_CONTEXT_FLAG_ROBUST_ACCESS_BIT 0x00000004
#define GL_LOSE_CONTEXT_ON_RESET 0x8252
#define GL_GUILTY_CONTEXT_RESET 0x8253
#define GL_INNOCENT_CONTEXT_RESET 0x8254
#define GL_UNKNOWN_CONTEXT_RESET 0x8255
#define GL_RESET_NOTIFICATION_STRATEGY 0x8256
#define GL_NO_RESET_NOTIFICATION 0x8261
#define GL_CONTEXT_LOST 0x0507
#define GL_COMPRESSED_RGBA_ASTC_4x4 0x93B0
#define GL_COMPRESSED_RGBA_ASTC_5x4 0x93B1
#define GL_COMPRESSED_RGBA_ASTC_5x5 0x93B2
@ -3324,73 +3374,12 @@ typedef void (APIENTRYP PFNGLBINDVERTEXBUFFERSPROC)(GLuint first, GLsizei count,
GLAPI PFNGLBINDVERTEXBUFFERSPROC glad_glBindVertexBuffers;
#define glBindVertexBuffers glad_glBindVertexBuffers
#endif
#ifndef GL_ES_VERSION_2_0
#define GL_ES_VERSION_2_0 1
GLAPI int GLAD_GL_ES_VERSION_2_0;
#endif
#ifndef GL_ES_VERSION_3_0
#define GL_ES_VERSION_3_0 1
GLAPI int GLAD_GL_ES_VERSION_3_0;
#endif
#ifndef GL_ES_VERSION_3_1
#define GL_ES_VERSION_3_1 1
GLAPI int GLAD_GL_ES_VERSION_3_1;
typedef void (APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC)(GLbitfield barriers);
GLAPI PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion;
#define glMemoryBarrierByRegion glad_glMemoryBarrierByRegion
#endif
#ifndef GL_ES_VERSION_3_2
#define GL_ES_VERSION_3_2 1
GLAPI int GLAD_GL_ES_VERSION_3_2;
typedef void (APIENTRYP PFNGLBLENDBARRIERPROC)(void);
GLAPI PFNGLBLENDBARRIERPROC glad_glBlendBarrier;
#define glBlendBarrier glad_glBlendBarrier
typedef void (APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXPROC)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
GLAPI PFNGLPRIMITIVEBOUNDINGBOXPROC glad_glPrimitiveBoundingBox;
#define glPrimitiveBoundingBox glad_glPrimitiveBoundingBox
typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC)(void);
GLAPI PFNGLGETGRAPHICSRESETSTATUSPROC glad_glGetGraphicsResetStatus;
#define glGetGraphicsResetStatus glad_glGetGraphicsResetStatus
typedef void (APIENTRYP PFNGLREADNPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
GLAPI PFNGLREADNPIXELSPROC glad_glReadnPixels;
#define glReadnPixels glad_glReadnPixels
typedef void (APIENTRYP PFNGLGETNUNIFORMFVPROC)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
GLAPI PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv;
#define glGetnUniformfv glad_glGetnUniformfv
typedef void (APIENTRYP PFNGLGETNUNIFORMIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLint *params);
GLAPI PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv;
#define glGetnUniformiv glad_glGetnUniformiv
typedef void (APIENTRYP PFNGLGETNUNIFORMUIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLuint *params);
GLAPI PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv;
#define glGetnUniformuiv glad_glGetnUniformuiv
#endif
#define GL_TEXTURE_TARGET 0x1006
#define GL_QUERY_TARGET 0x82EA
#define GL_MAP_PERSISTENT_BIT_EXT 0x0040
#define GL_MAP_COHERENT_BIT_EXT 0x0080
#define GL_DYNAMIC_STORAGE_BIT_EXT 0x0100
#define GL_CLIENT_STORAGE_BIT_EXT 0x0200
#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
#define GL_BUFFER_IMMUTABLE_STORAGE_EXT 0x821F
#define GL_BUFFER_STORAGE_FLAGS_EXT 0x8220
#define GL_MAX_CLIP_DISTANCES_EXT 0x0D32
#define GL_MAX_CULL_DISTANCES_EXT 0x82F9
#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA
#define GL_CLIP_DISTANCE0_EXT 0x3000
#define GL_CLIP_DISTANCE1_EXT 0x3001
#define GL_CLIP_DISTANCE2_EXT 0x3002
#define GL_CLIP_DISTANCE3_EXT 0x3003
#define GL_CLIP_DISTANCE4_EXT 0x3004
#define GL_CLIP_DISTANCE5_EXT 0x3005
#define GL_CLIP_DISTANCE6_EXT 0x3006
#define GL_CLIP_DISTANCE7_EXT 0x3007
#ifndef GL_ARB_buffer_storage
#define GL_ARB_buffer_storage 1
GLAPI int GLAD_GL_ARB_buffer_storage;
#endif
#ifndef GL_ARB_direct_state_access
#define GL_ARB_direct_state_access 1
GLAPI int GLAD_GL_ARB_direct_state_access;
#ifndef GL_VERSION_4_5
#define GL_VERSION_4_5 1
GLAPI int GLAD_GL_VERSION_4_5;
typedef void (APIENTRYP PFNGLCLIPCONTROLPROC)(GLenum origin, GLenum depth);
GLAPI PFNGLCLIPCONTROLPROC glad_glClipControl;
#define glClipControl glad_glClipControl
typedef void (APIENTRYP PFNGLCREATETRANSFORMFEEDBACKSPROC)(GLsizei n, GLuint *ids);
GLAPI PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks;
#define glCreateTransformFeedbacks glad_glCreateTransformFeedbacks
@ -3682,6 +3671,158 @@ GLAPI PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v;
typedef void (APIENTRYP PFNGLGETQUERYBUFFEROBJECTUIVPROC)(GLuint id, GLuint buffer, GLenum pname, GLintptr offset);
GLAPI PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv;
#define glGetQueryBufferObjectuiv glad_glGetQueryBufferObjectuiv
typedef void (APIENTRYP PFNGLMEMORYBARRIERBYREGIONPROC)(GLbitfield barriers);
GLAPI PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion;
#define glMemoryBarrierByRegion glad_glMemoryBarrierByRegion
typedef void (APIENTRYP PFNGLGETTEXTURESUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
GLAPI PFNGLGETTEXTURESUBIMAGEPROC glad_glGetTextureSubImage;
#define glGetTextureSubImage glad_glGetTextureSubImage
typedef void (APIENTRYP PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)(GLuint texture, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLsizei bufSize, void *pixels);
GLAPI PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glad_glGetCompressedTextureSubImage;
#define glGetCompressedTextureSubImage glad_glGetCompressedTextureSubImage
typedef GLenum (APIENTRYP PFNGLGETGRAPHICSRESETSTATUSPROC)(void);
GLAPI PFNGLGETGRAPHICSRESETSTATUSPROC glad_glGetGraphicsResetStatus;
#define glGetGraphicsResetStatus glad_glGetGraphicsResetStatus
typedef void (APIENTRYP PFNGLGETNCOMPRESSEDTEXIMAGEPROC)(GLenum target, GLint lod, GLsizei bufSize, void *pixels);
GLAPI PFNGLGETNCOMPRESSEDTEXIMAGEPROC glad_glGetnCompressedTexImage;
#define glGetnCompressedTexImage glad_glGetnCompressedTexImage
typedef void (APIENTRYP PFNGLGETNTEXIMAGEPROC)(GLenum target, GLint level, GLenum format, GLenum type, GLsizei bufSize, void *pixels);
GLAPI PFNGLGETNTEXIMAGEPROC glad_glGetnTexImage;
#define glGetnTexImage glad_glGetnTexImage
typedef void (APIENTRYP PFNGLGETNUNIFORMDVPROC)(GLuint program, GLint location, GLsizei bufSize, GLdouble *params);
GLAPI PFNGLGETNUNIFORMDVPROC glad_glGetnUniformdv;
#define glGetnUniformdv glad_glGetnUniformdv
typedef void (APIENTRYP PFNGLGETNUNIFORMFVPROC)(GLuint program, GLint location, GLsizei bufSize, GLfloat *params);
GLAPI PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv;
#define glGetnUniformfv glad_glGetnUniformfv
typedef void (APIENTRYP PFNGLGETNUNIFORMIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLint *params);
GLAPI PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv;
#define glGetnUniformiv glad_glGetnUniformiv
typedef void (APIENTRYP PFNGLGETNUNIFORMUIVPROC)(GLuint program, GLint location, GLsizei bufSize, GLuint *params);
GLAPI PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv;
#define glGetnUniformuiv glad_glGetnUniformuiv
typedef void (APIENTRYP PFNGLREADNPIXELSPROC)(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
GLAPI PFNGLREADNPIXELSPROC glad_glReadnPixels;
#define glReadnPixels glad_glReadnPixels
typedef void (APIENTRYP PFNGLGETNMAPDVPROC)(GLenum target, GLenum query, GLsizei bufSize, GLdouble *v);
GLAPI PFNGLGETNMAPDVPROC glad_glGetnMapdv;
#define glGetnMapdv glad_glGetnMapdv
typedef void (APIENTRYP PFNGLGETNMAPFVPROC)(GLenum target, GLenum query, GLsizei bufSize, GLfloat *v);
GLAPI PFNGLGETNMAPFVPROC glad_glGetnMapfv;
#define glGetnMapfv glad_glGetnMapfv
typedef void (APIENTRYP PFNGLGETNMAPIVPROC)(GLenum target, GLenum query, GLsizei bufSize, GLint *v);
GLAPI PFNGLGETNMAPIVPROC glad_glGetnMapiv;
#define glGetnMapiv glad_glGetnMapiv
typedef void (APIENTRYP PFNGLGETNPIXELMAPFVPROC)(GLenum map, GLsizei bufSize, GLfloat *values);
GLAPI PFNGLGETNPIXELMAPFVPROC glad_glGetnPixelMapfv;
#define glGetnPixelMapfv glad_glGetnPixelMapfv
typedef void (APIENTRYP PFNGLGETNPIXELMAPUIVPROC)(GLenum map, GLsizei bufSize, GLuint *values);
GLAPI PFNGLGETNPIXELMAPUIVPROC glad_glGetnPixelMapuiv;
#define glGetnPixelMapuiv glad_glGetnPixelMapuiv
typedef void (APIENTRYP PFNGLGETNPIXELMAPUSVPROC)(GLenum map, GLsizei bufSize, GLushort *values);
GLAPI PFNGLGETNPIXELMAPUSVPROC glad_glGetnPixelMapusv;
#define glGetnPixelMapusv glad_glGetnPixelMapusv
typedef void (APIENTRYP PFNGLGETNPOLYGONSTIPPLEPROC)(GLsizei bufSize, GLubyte *pattern);
GLAPI PFNGLGETNPOLYGONSTIPPLEPROC glad_glGetnPolygonStipple;
#define glGetnPolygonStipple glad_glGetnPolygonStipple
typedef void (APIENTRYP PFNGLGETNCOLORTABLEPROC)(GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *table);
GLAPI PFNGLGETNCOLORTABLEPROC glad_glGetnColorTable;
#define glGetnColorTable glad_glGetnColorTable
typedef void (APIENTRYP PFNGLGETNCONVOLUTIONFILTERPROC)(GLenum target, GLenum format, GLenum type, GLsizei bufSize, void *image);
GLAPI PFNGLGETNCONVOLUTIONFILTERPROC glad_glGetnConvolutionFilter;
#define glGetnConvolutionFilter glad_glGetnConvolutionFilter
typedef void (APIENTRYP PFNGLGETNSEPARABLEFILTERPROC)(GLenum target, GLenum format, GLenum type, GLsizei rowBufSize, void *row, GLsizei columnBufSize, void *column, void *span);
GLAPI PFNGLGETNSEPARABLEFILTERPROC glad_glGetnSeparableFilter;
#define glGetnSeparableFilter glad_glGetnSeparableFilter
typedef void (APIENTRYP PFNGLGETNHISTOGRAMPROC)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
GLAPI PFNGLGETNHISTOGRAMPROC glad_glGetnHistogram;
#define glGetnHistogram glad_glGetnHistogram
typedef void (APIENTRYP PFNGLGETNMINMAXPROC)(GLenum target, GLboolean reset, GLenum format, GLenum type, GLsizei bufSize, void *values);
GLAPI PFNGLGETNMINMAXPROC glad_glGetnMinmax;
#define glGetnMinmax glad_glGetnMinmax
typedef void (APIENTRYP PFNGLTEXTUREBARRIERPROC)(void);
GLAPI PFNGLTEXTUREBARRIERPROC glad_glTextureBarrier;
#define glTextureBarrier glad_glTextureBarrier
#endif
#ifndef GL_VERSION_4_6
#define GL_VERSION_4_6 1
GLAPI int GLAD_GL_VERSION_4_6;
typedef void (APIENTRYP PFNGLSPECIALIZESHADERPROC)(GLuint shader, const GLchar *pEntryPoint, GLuint numSpecializationConstants, const GLuint *pConstantIndex, const GLuint *pConstantValue);
GLAPI PFNGLSPECIALIZESHADERPROC glad_glSpecializeShader;
#define glSpecializeShader glad_glSpecializeShader
typedef void (APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC)(GLenum mode, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
GLAPI PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glad_glMultiDrawArraysIndirectCount;
#define glMultiDrawArraysIndirectCount glad_glMultiDrawArraysIndirectCount
typedef void (APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC)(GLenum mode, GLenum type, const void *indirect, GLintptr drawcount, GLsizei maxdrawcount, GLsizei stride);
GLAPI PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glad_glMultiDrawElementsIndirectCount;
#define glMultiDrawElementsIndirectCount glad_glMultiDrawElementsIndirectCount
typedef void (APIENTRYP PFNGLPOLYGONOFFSETCLAMPPROC)(GLfloat factor, GLfloat units, GLfloat clamp);
GLAPI PFNGLPOLYGONOFFSETCLAMPPROC glad_glPolygonOffsetClamp;
#define glPolygonOffsetClamp glad_glPolygonOffsetClamp
#endif
#ifndef GL_ES_VERSION_2_0
#define GL_ES_VERSION_2_0 1
GLAPI int GLAD_GL_ES_VERSION_2_0;
#endif
#ifndef GL_ES_VERSION_3_0
#define GL_ES_VERSION_3_0 1
GLAPI int GLAD_GL_ES_VERSION_3_0;
#endif
#ifndef GL_ES_VERSION_3_1
#define GL_ES_VERSION_3_1 1
GLAPI int GLAD_GL_ES_VERSION_3_1;
#endif
#ifndef GL_ES_VERSION_3_2
#define GL_ES_VERSION_3_2 1
GLAPI int GLAD_GL_ES_VERSION_3_2;
typedef void (APIENTRYP PFNGLBLENDBARRIERPROC)(void);
GLAPI PFNGLBLENDBARRIERPROC glad_glBlendBarrier;
#define glBlendBarrier glad_glBlendBarrier
typedef void (APIENTRYP PFNGLPRIMITIVEBOUNDINGBOXPROC)(GLfloat minX, GLfloat minY, GLfloat minZ, GLfloat minW, GLfloat maxX, GLfloat maxY, GLfloat maxZ, GLfloat maxW);
GLAPI PFNGLPRIMITIVEBOUNDINGBOXPROC glad_glPrimitiveBoundingBox;
#define glPrimitiveBoundingBox glad_glPrimitiveBoundingBox
#endif
#define GL_COMPRESSED_RGBA_BPTC_UNORM_ARB 0x8E8C
#define GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB 0x8E8D
#define GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB 0x8E8E
#define GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB 0x8E8F
#define GL_COMPRESSED_RGB_S3TC_DXT1_EXT 0x83F0
#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT 0x83F1
#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT 0x83F2
#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT 0x83F3
#define GL_MAP_PERSISTENT_BIT_EXT 0x0040
#define GL_MAP_COHERENT_BIT_EXT 0x0080
#define GL_DYNAMIC_STORAGE_BIT_EXT 0x0100
#define GL_CLIENT_STORAGE_BIT_EXT 0x0200
#define GL_CLIENT_MAPPED_BUFFER_BARRIER_BIT_EXT 0x00004000
#define GL_BUFFER_IMMUTABLE_STORAGE_EXT 0x821F
#define GL_BUFFER_STORAGE_FLAGS_EXT 0x8220
#define GL_MAX_CLIP_DISTANCES_EXT 0x0D32
#define GL_MAX_CULL_DISTANCES_EXT 0x82F9
#define GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT 0x82FA
#define GL_CLIP_DISTANCE0_EXT 0x3000
#define GL_CLIP_DISTANCE1_EXT 0x3001
#define GL_CLIP_DISTANCE2_EXT 0x3002
#define GL_CLIP_DISTANCE3_EXT 0x3003
#define GL_CLIP_DISTANCE4_EXT 0x3004
#define GL_CLIP_DISTANCE5_EXT 0x3005
#define GL_CLIP_DISTANCE6_EXT 0x3006
#define GL_CLIP_DISTANCE7_EXT 0x3007
#ifndef GL_ARB_buffer_storage
#define GL_ARB_buffer_storage 1
GLAPI int GLAD_GL_ARB_buffer_storage;
#endif
#ifndef GL_ARB_direct_state_access
#define GL_ARB_direct_state_access 1
GLAPI int GLAD_GL_ARB_direct_state_access;
#endif
#ifndef GL_ARB_texture_compression_bptc
#define GL_ARB_texture_compression_bptc 1
GLAPI int GLAD_GL_ARB_texture_compression_bptc;
#endif
#ifndef GL_EXT_texture_compression_s3tc
#define GL_EXT_texture_compression_s3tc 1
GLAPI int GLAD_GL_EXT_texture_compression_s3tc;
#endif
#ifndef GL_EXT_buffer_storage
#define GL_EXT_buffer_storage 1
@ -3694,6 +3835,10 @@ GLAPI PFNGLBUFFERSTORAGEEXTPROC glad_glBufferStorageEXT;
#define GL_EXT_clip_cull_distance 1
GLAPI int GLAD_GL_EXT_clip_cull_distance;
#endif
#ifndef GL_EXT_texture_compression_s3tc
#define GL_EXT_texture_compression_s3tc 1
GLAPI int GLAD_GL_EXT_texture_compression_s3tc;
#endif
#ifdef __cplusplus
}

View File

@ -1,25 +1,27 @@
/*
OpenGL, OpenGL ES loader generated by glad 0.1.36 on Fri Sep 9 09:22:43 2022.
OpenGL, OpenGL ES loader generated by glad 0.1.36 on Tue Feb 21 16:13:52 2023.
Language/Generator: C/C++
Specification: gl
APIs: gl=4.4, gles2=3.2
APIs: gl=4.6, gles2=3.2
Profile: core
Extensions:
GL_ARB_buffer_storage,
GL_ARB_direct_state_access,
GL_ARB_texture_compression_bptc,
GL_EXT_buffer_storage,
GL_EXT_clip_cull_distance
GL_EXT_clip_cull_distance,
GL_EXT_texture_compression_s3tc
Loader: True
Local files: False
Omit khrplatform: False
Reproducible: False
Commandline:
--profile="core" --api="gl=4.4,gles2=3.2" --generator="c" --spec="gl" --extensions="GL_ARB_buffer_storage,GL_ARB_direct_state_access,GL_EXT_buffer_storage,GL_EXT_clip_cull_distance"
--profile="core" --api="gl=4.6,gles2=3.2" --generator="c" --spec="gl" --extensions="GL_ARB_buffer_storage,GL_ARB_direct_state_access,GL_ARB_texture_compression_bptc,GL_EXT_buffer_storage,GL_EXT_clip_cull_distance,GL_EXT_texture_compression_s3tc"
Online:
https://glad.dav1d.de/#profile=core&language=c&specification=gl&loader=on&api=gl%3D4.4&api=gles2%3D3.2&extensions=GL_ARB_buffer_storage&extensions=GL_ARB_direct_state_access&extensions=GL_EXT_buffer_storage&extensions=GL_EXT_clip_cull_distance
https://glad.dav1d.de/#profile=core&language=c&specification=gl&loader=on&api=gl%3D4.6&api=gles2%3D3.2&extensions=GL_ARB_buffer_storage&extensions=GL_ARB_direct_state_access&extensions=GL_ARB_texture_compression_bptc&extensions=GL_EXT_buffer_storage&extensions=GL_EXT_clip_cull_distance&extensions=GL_EXT_texture_compression_s3tc
*/
#include <stdio.h>
@ -275,6 +277,8 @@ int GLAD_GL_VERSION_4_1 = 0;
int GLAD_GL_VERSION_4_2 = 0;
int GLAD_GL_VERSION_4_3 = 0;
int GLAD_GL_VERSION_4_4 = 0;
int GLAD_GL_VERSION_4_5 = 0;
int GLAD_GL_VERSION_4_6 = 0;
int GLAD_GL_ES_VERSION_2_0 = 0;
int GLAD_GL_ES_VERSION_3_0 = 0;
int GLAD_GL_ES_VERSION_3_1 = 0;
@ -302,6 +306,7 @@ PFNGLBINDRENDERBUFFERPROC glad_glBindRenderbuffer = NULL;
PFNGLBINDSAMPLERPROC glad_glBindSampler = NULL;
PFNGLBINDSAMPLERSPROC glad_glBindSamplers = NULL;
PFNGLBINDTEXTUREPROC glad_glBindTexture = NULL;
PFNGLBINDTEXTUREUNITPROC glad_glBindTextureUnit = NULL;
PFNGLBINDTEXTURESPROC glad_glBindTextures = NULL;
PFNGLBINDTRANSFORMFEEDBACKPROC glad_glBindTransformFeedback = NULL;
PFNGLBINDVERTEXARRAYPROC glad_glBindVertexArray = NULL;
@ -318,10 +323,12 @@ PFNGLBLENDFUNCSEPARATEPROC glad_glBlendFuncSeparate = NULL;
PFNGLBLENDFUNCSEPARATEIPROC glad_glBlendFuncSeparatei = NULL;
PFNGLBLENDFUNCIPROC glad_glBlendFunci = NULL;
PFNGLBLITFRAMEBUFFERPROC glad_glBlitFramebuffer = NULL;
PFNGLBLITNAMEDFRAMEBUFFERPROC glad_glBlitNamedFramebuffer = NULL;
PFNGLBUFFERDATAPROC glad_glBufferData = NULL;
PFNGLBUFFERSTORAGEPROC glad_glBufferStorage = NULL;
PFNGLBUFFERSUBDATAPROC glad_glBufferSubData = NULL;
PFNGLCHECKFRAMEBUFFERSTATUSPROC glad_glCheckFramebufferStatus = NULL;
PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glad_glCheckNamedFramebufferStatus = NULL;
PFNGLCLAMPCOLORPROC glad_glClampColor = NULL;
PFNGLCLEARPROC glad_glClear = NULL;
PFNGLCLEARBUFFERDATAPROC glad_glClearBufferData = NULL;
@ -333,10 +340,17 @@ PFNGLCLEARBUFFERUIVPROC glad_glClearBufferuiv = NULL;
PFNGLCLEARCOLORPROC glad_glClearColor = NULL;
PFNGLCLEARDEPTHPROC glad_glClearDepth = NULL;
PFNGLCLEARDEPTHFPROC glad_glClearDepthf = NULL;
PFNGLCLEARNAMEDBUFFERDATAPROC glad_glClearNamedBufferData = NULL;
PFNGLCLEARNAMEDBUFFERSUBDATAPROC glad_glClearNamedBufferSubData = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glad_glClearNamedFramebufferfi = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glad_glClearNamedFramebufferfv = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glad_glClearNamedFramebufferiv = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glad_glClearNamedFramebufferuiv = NULL;
PFNGLCLEARSTENCILPROC glad_glClearStencil = NULL;
PFNGLCLEARTEXIMAGEPROC glad_glClearTexImage = NULL;
PFNGLCLEARTEXSUBIMAGEPROC glad_glClearTexSubImage = NULL;
PFNGLCLIENTWAITSYNCPROC glad_glClientWaitSync = NULL;
PFNGLCLIPCONTROLPROC glad_glClipControl = NULL;
PFNGLCOLORMASKPROC glad_glColorMask = NULL;
PFNGLCOLORMASKIPROC glad_glColorMaski = NULL;
PFNGLCOLORP3UIPROC glad_glColorP3ui = NULL;
@ -350,16 +364,32 @@ PFNGLCOMPRESSEDTEXIMAGE3DPROC glad_glCompressedTexImage3D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE1DPROC glad_glCompressedTexSubImage1D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE2DPROC glad_glCompressedTexSubImage2D = NULL;
PFNGLCOMPRESSEDTEXSUBIMAGE3DPROC glad_glCompressedTexSubImage3D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glad_glCompressedTextureSubImage1D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glad_glCompressedTextureSubImage2D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glad_glCompressedTextureSubImage3D = NULL;
PFNGLCOPYBUFFERSUBDATAPROC glad_glCopyBufferSubData = NULL;
PFNGLCOPYIMAGESUBDATAPROC glad_glCopyImageSubData = NULL;
PFNGLCOPYNAMEDBUFFERSUBDATAPROC glad_glCopyNamedBufferSubData = NULL;
PFNGLCOPYTEXIMAGE1DPROC glad_glCopyTexImage1D = NULL;
PFNGLCOPYTEXIMAGE2DPROC glad_glCopyTexImage2D = NULL;
PFNGLCOPYTEXSUBIMAGE1DPROC glad_glCopyTexSubImage1D = NULL;
PFNGLCOPYTEXSUBIMAGE2DPROC glad_glCopyTexSubImage2D = NULL;
PFNGLCOPYTEXSUBIMAGE3DPROC glad_glCopyTexSubImage3D = NULL;
PFNGLCOPYTEXTURESUBIMAGE1DPROC glad_glCopyTextureSubImage1D = NULL;
PFNGLCOPYTEXTURESUBIMAGE2DPROC glad_glCopyTextureSubImage2D = NULL;
PFNGLCOPYTEXTURESUBIMAGE3DPROC glad_glCopyTextureSubImage3D = NULL;
PFNGLCREATEBUFFERSPROC glad_glCreateBuffers = NULL;
PFNGLCREATEFRAMEBUFFERSPROC glad_glCreateFramebuffers = NULL;
PFNGLCREATEPROGRAMPROC glad_glCreateProgram = NULL;
PFNGLCREATEPROGRAMPIPELINESPROC glad_glCreateProgramPipelines = NULL;
PFNGLCREATEQUERIESPROC glad_glCreateQueries = NULL;
PFNGLCREATERENDERBUFFERSPROC glad_glCreateRenderbuffers = NULL;
PFNGLCREATESAMPLERSPROC glad_glCreateSamplers = NULL;
PFNGLCREATESHADERPROC glad_glCreateShader = NULL;
PFNGLCREATESHADERPROGRAMVPROC glad_glCreateShaderProgramv = NULL;
PFNGLCREATETEXTURESPROC glad_glCreateTextures = NULL;
PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks = NULL;
PFNGLCREATEVERTEXARRAYSPROC glad_glCreateVertexArrays = NULL;
PFNGLCULLFACEPROC glad_glCullFace = NULL;
PFNGLDEBUGMESSAGECALLBACKPROC glad_glDebugMessageCallback = NULL;
PFNGLDEBUGMESSAGECONTROLPROC glad_glDebugMessageControl = NULL;
@ -384,6 +414,7 @@ PFNGLDEPTHRANGEINDEXEDPROC glad_glDepthRangeIndexed = NULL;
PFNGLDEPTHRANGEFPROC glad_glDepthRangef = NULL;
PFNGLDETACHSHADERPROC glad_glDetachShader = NULL;
PFNGLDISABLEPROC glad_glDisable = NULL;
PFNGLDISABLEVERTEXARRAYATTRIBPROC glad_glDisableVertexArrayAttrib = NULL;
PFNGLDISABLEVERTEXATTRIBARRAYPROC glad_glDisableVertexAttribArray = NULL;
PFNGLDISABLEIPROC glad_glDisablei = NULL;
PFNGLDISPATCHCOMPUTEPROC glad_glDispatchCompute = NULL;
@ -408,6 +439,7 @@ PFNGLDRAWTRANSFORMFEEDBACKINSTANCEDPROC glad_glDrawTransformFeedbackInstanced =
PFNGLDRAWTRANSFORMFEEDBACKSTREAMPROC glad_glDrawTransformFeedbackStream = NULL;
PFNGLDRAWTRANSFORMFEEDBACKSTREAMINSTANCEDPROC glad_glDrawTransformFeedbackStreamInstanced = NULL;
PFNGLENABLEPROC glad_glEnable = NULL;
PFNGLENABLEVERTEXARRAYATTRIBPROC glad_glEnableVertexArrayAttrib = NULL;
PFNGLENABLEVERTEXATTRIBARRAYPROC glad_glEnableVertexAttribArray = NULL;
PFNGLENABLEIPROC glad_glEnablei = NULL;
PFNGLENDCONDITIONALRENDERPROC glad_glEndConditionalRender = NULL;
@ -418,6 +450,7 @@ PFNGLFENCESYNCPROC glad_glFenceSync = NULL;
PFNGLFINISHPROC glad_glFinish = NULL;
PFNGLFLUSHPROC glad_glFlush = NULL;
PFNGLFLUSHMAPPEDBUFFERRANGEPROC glad_glFlushMappedBufferRange = NULL;
PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glad_glFlushMappedNamedBufferRange = NULL;
PFNGLFRAMEBUFFERPARAMETERIPROC glad_glFramebufferParameteri = NULL;
PFNGLFRAMEBUFFERRENDERBUFFERPROC glad_glFramebufferRenderbuffer = NULL;
PFNGLFRAMEBUFFERTEXTUREPROC glad_glFramebufferTexture = NULL;
@ -436,6 +469,7 @@ PFNGLGENTEXTURESPROC glad_glGenTextures = NULL;
PFNGLGENTRANSFORMFEEDBACKSPROC glad_glGenTransformFeedbacks = NULL;
PFNGLGENVERTEXARRAYSPROC glad_glGenVertexArrays = NULL;
PFNGLGENERATEMIPMAPPROC glad_glGenerateMipmap = NULL;
PFNGLGENERATETEXTUREMIPMAPPROC glad_glGenerateTextureMipmap = NULL;
PFNGLGETACTIVEATOMICCOUNTERBUFFERIVPROC glad_glGetActiveAtomicCounterBufferiv = NULL;
PFNGLGETACTIVEATTRIBPROC glad_glGetActiveAttrib = NULL;
PFNGLGETACTIVESUBROUTINENAMEPROC glad_glGetActiveSubroutineName = NULL;
@ -455,6 +489,8 @@ PFNGLGETBUFFERPARAMETERIVPROC glad_glGetBufferParameteriv = NULL;
PFNGLGETBUFFERPOINTERVPROC glad_glGetBufferPointerv = NULL;
PFNGLGETBUFFERSUBDATAPROC glad_glGetBufferSubData = NULL;
PFNGLGETCOMPRESSEDTEXIMAGEPROC glad_glGetCompressedTexImage = NULL;
PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glad_glGetCompressedTextureImage = NULL;
PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC glad_glGetCompressedTextureSubImage = NULL;
PFNGLGETDEBUGMESSAGELOGPROC glad_glGetDebugMessageLog = NULL;
PFNGLGETDOUBLEI_VPROC glad_glGetDoublei_v = NULL;
PFNGLGETDOUBLEVPROC glad_glGetDoublev = NULL;
@ -473,6 +509,13 @@ PFNGLGETINTEGERVPROC glad_glGetIntegerv = NULL;
PFNGLGETINTERNALFORMATI64VPROC glad_glGetInternalformati64v = NULL;
PFNGLGETINTERNALFORMATIVPROC glad_glGetInternalformativ = NULL;
PFNGLGETMULTISAMPLEFVPROC glad_glGetMultisamplefv = NULL;
PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glad_glGetNamedBufferParameteri64v = NULL;
PFNGLGETNAMEDBUFFERPARAMETERIVPROC glad_glGetNamedBufferParameteriv = NULL;
PFNGLGETNAMEDBUFFERPOINTERVPROC glad_glGetNamedBufferPointerv = NULL;
PFNGLGETNAMEDBUFFERSUBDATAPROC glad_glGetNamedBufferSubData = NULL;
PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetNamedFramebufferAttachmentParameteriv = NULL;
PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glad_glGetNamedFramebufferParameteriv = NULL;
PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glad_glGetNamedRenderbufferParameteriv = NULL;
PFNGLGETOBJECTLABELPROC glad_glGetObjectLabel = NULL;
PFNGLGETOBJECTPTRLABELPROC glad_glGetObjectPtrLabel = NULL;
PFNGLGETPOINTERVPROC glad_glGetPointerv = NULL;
@ -488,6 +531,10 @@ PFNGLGETPROGRAMRESOURCENAMEPROC glad_glGetProgramResourceName = NULL;
PFNGLGETPROGRAMRESOURCEIVPROC glad_glGetProgramResourceiv = NULL;
PFNGLGETPROGRAMSTAGEIVPROC glad_glGetProgramStageiv = NULL;
PFNGLGETPROGRAMIVPROC glad_glGetProgramiv = NULL;
PFNGLGETQUERYBUFFEROBJECTI64VPROC glad_glGetQueryBufferObjecti64v = NULL;
PFNGLGETQUERYBUFFEROBJECTIVPROC glad_glGetQueryBufferObjectiv = NULL;
PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v = NULL;
PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv = NULL;
PFNGLGETQUERYINDEXEDIVPROC glad_glGetQueryIndexediv = NULL;
PFNGLGETQUERYOBJECTI64VPROC glad_glGetQueryObjecti64v = NULL;
PFNGLGETQUERYOBJECTIVPROC glad_glGetQueryObjectiv = NULL;
@ -515,7 +562,18 @@ PFNGLGETTEXPARAMETERIIVPROC glad_glGetTexParameterIiv = NULL;
PFNGLGETTEXPARAMETERIUIVPROC glad_glGetTexParameterIuiv = NULL;
PFNGLGETTEXPARAMETERFVPROC glad_glGetTexParameterfv = NULL;
PFNGLGETTEXPARAMETERIVPROC glad_glGetTexParameteriv = NULL;
PFNGLGETTEXTUREIMAGEPROC glad_glGetTextureImage = NULL;
PFNGLGETTEXTURELEVELPARAMETERFVPROC glad_glGetTextureLevelParameterfv = NULL;
PFNGLGETTEXTURELEVELPARAMETERIVPROC glad_glGetTextureLevelParameteriv = NULL;
PFNGLGETTEXTUREPARAMETERIIVPROC glad_glGetTextureParameterIiv = NULL;
PFNGLGETTEXTUREPARAMETERIUIVPROC glad_glGetTextureParameterIuiv = NULL;
PFNGLGETTEXTUREPARAMETERFVPROC glad_glGetTextureParameterfv = NULL;
PFNGLGETTEXTUREPARAMETERIVPROC glad_glGetTextureParameteriv = NULL;
PFNGLGETTEXTURESUBIMAGEPROC glad_glGetTextureSubImage = NULL;
PFNGLGETTRANSFORMFEEDBACKVARYINGPROC glad_glGetTransformFeedbackVarying = NULL;
PFNGLGETTRANSFORMFEEDBACKI64_VPROC glad_glGetTransformFeedbacki64_v = NULL;
PFNGLGETTRANSFORMFEEDBACKI_VPROC glad_glGetTransformFeedbacki_v = NULL;
PFNGLGETTRANSFORMFEEDBACKIVPROC glad_glGetTransformFeedbackiv = NULL;
PFNGLGETUNIFORMBLOCKINDEXPROC glad_glGetUniformBlockIndex = NULL;
PFNGLGETUNIFORMINDICESPROC glad_glGetUniformIndices = NULL;
PFNGLGETUNIFORMLOCATIONPROC glad_glGetUniformLocation = NULL;
@ -524,6 +582,9 @@ PFNGLGETUNIFORMDVPROC glad_glGetUniformdv = NULL;
PFNGLGETUNIFORMFVPROC glad_glGetUniformfv = NULL;
PFNGLGETUNIFORMIVPROC glad_glGetUniformiv = NULL;
PFNGLGETUNIFORMUIVPROC glad_glGetUniformuiv = NULL;
PFNGLGETVERTEXARRAYINDEXED64IVPROC glad_glGetVertexArrayIndexed64iv = NULL;
PFNGLGETVERTEXARRAYINDEXEDIVPROC glad_glGetVertexArrayIndexediv = NULL;
PFNGLGETVERTEXARRAYIVPROC glad_glGetVertexArrayiv = NULL;
PFNGLGETVERTEXATTRIBIIVPROC glad_glGetVertexAttribIiv = NULL;
PFNGLGETVERTEXATTRIBIUIVPROC glad_glGetVertexAttribIuiv = NULL;
PFNGLGETVERTEXATTRIBLDVPROC glad_glGetVertexAttribLdv = NULL;
@ -531,6 +592,21 @@ PFNGLGETVERTEXATTRIBPOINTERVPROC glad_glGetVertexAttribPointerv = NULL;
PFNGLGETVERTEXATTRIBDVPROC glad_glGetVertexAttribdv = NULL;
PFNGLGETVERTEXATTRIBFVPROC glad_glGetVertexAttribfv = NULL;
PFNGLGETVERTEXATTRIBIVPROC glad_glGetVertexAttribiv = NULL;
PFNGLGETNCOLORTABLEPROC glad_glGetnColorTable = NULL;
PFNGLGETNCOMPRESSEDTEXIMAGEPROC glad_glGetnCompressedTexImage = NULL;
PFNGLGETNCONVOLUTIONFILTERPROC glad_glGetnConvolutionFilter = NULL;
PFNGLGETNHISTOGRAMPROC glad_glGetnHistogram = NULL;
PFNGLGETNMAPDVPROC glad_glGetnMapdv = NULL;
PFNGLGETNMAPFVPROC glad_glGetnMapfv = NULL;
PFNGLGETNMAPIVPROC glad_glGetnMapiv = NULL;
PFNGLGETNMINMAXPROC glad_glGetnMinmax = NULL;
PFNGLGETNPIXELMAPFVPROC glad_glGetnPixelMapfv = NULL;
PFNGLGETNPIXELMAPUIVPROC glad_glGetnPixelMapuiv = NULL;
PFNGLGETNPIXELMAPUSVPROC glad_glGetnPixelMapusv = NULL;
PFNGLGETNPOLYGONSTIPPLEPROC glad_glGetnPolygonStipple = NULL;
PFNGLGETNSEPARABLEFILTERPROC glad_glGetnSeparableFilter = NULL;
PFNGLGETNTEXIMAGEPROC glad_glGetnTexImage = NULL;
PFNGLGETNUNIFORMDVPROC glad_glGetnUniformdv = NULL;
PFNGLGETNUNIFORMFVPROC glad_glGetnUniformfv = NULL;
PFNGLGETNUNIFORMIVPROC glad_glGetnUniformiv = NULL;
PFNGLGETNUNIFORMUIVPROC glad_glGetnUniformuiv = NULL;
@ -538,6 +614,8 @@ PFNGLHINTPROC glad_glHint = NULL;
PFNGLINVALIDATEBUFFERDATAPROC glad_glInvalidateBufferData = NULL;
PFNGLINVALIDATEBUFFERSUBDATAPROC glad_glInvalidateBufferSubData = NULL;
PFNGLINVALIDATEFRAMEBUFFERPROC glad_glInvalidateFramebuffer = NULL;
PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glad_glInvalidateNamedFramebufferData = NULL;
PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glad_glInvalidateNamedFramebufferSubData = NULL;
PFNGLINVALIDATESUBFRAMEBUFFERPROC glad_glInvalidateSubFramebuffer = NULL;
PFNGLINVALIDATETEXIMAGEPROC glad_glInvalidateTexImage = NULL;
PFNGLINVALIDATETEXSUBIMAGEPROC glad_glInvalidateTexSubImage = NULL;
@ -560,14 +638,18 @@ PFNGLLINKPROGRAMPROC glad_glLinkProgram = NULL;
PFNGLLOGICOPPROC glad_glLogicOp = NULL;
PFNGLMAPBUFFERPROC glad_glMapBuffer = NULL;
PFNGLMAPBUFFERRANGEPROC glad_glMapBufferRange = NULL;
PFNGLMAPNAMEDBUFFERPROC glad_glMapNamedBuffer = NULL;
PFNGLMAPNAMEDBUFFERRANGEPROC glad_glMapNamedBufferRange = NULL;
PFNGLMEMORYBARRIERPROC glad_glMemoryBarrier = NULL;
PFNGLMEMORYBARRIERBYREGIONPROC glad_glMemoryBarrierByRegion = NULL;
PFNGLMINSAMPLESHADINGPROC glad_glMinSampleShading = NULL;
PFNGLMULTIDRAWARRAYSPROC glad_glMultiDrawArrays = NULL;
PFNGLMULTIDRAWARRAYSINDIRECTPROC glad_glMultiDrawArraysIndirect = NULL;
PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC glad_glMultiDrawArraysIndirectCount = NULL;
PFNGLMULTIDRAWELEMENTSPROC glad_glMultiDrawElements = NULL;
PFNGLMULTIDRAWELEMENTSBASEVERTEXPROC glad_glMultiDrawElementsBaseVertex = NULL;
PFNGLMULTIDRAWELEMENTSINDIRECTPROC glad_glMultiDrawElementsIndirect = NULL;
PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC glad_glMultiDrawElementsIndirectCount = NULL;
PFNGLMULTITEXCOORDP1UIPROC glad_glMultiTexCoordP1ui = NULL;
PFNGLMULTITEXCOORDP1UIVPROC glad_glMultiTexCoordP1uiv = NULL;
PFNGLMULTITEXCOORDP2UIPROC glad_glMultiTexCoordP2ui = NULL;
@ -576,6 +658,18 @@ PFNGLMULTITEXCOORDP3UIPROC glad_glMultiTexCoordP3ui = NULL;
PFNGLMULTITEXCOORDP3UIVPROC glad_glMultiTexCoordP3uiv = NULL;
PFNGLMULTITEXCOORDP4UIPROC glad_glMultiTexCoordP4ui = NULL;
PFNGLMULTITEXCOORDP4UIVPROC glad_glMultiTexCoordP4uiv = NULL;
PFNGLNAMEDBUFFERDATAPROC glad_glNamedBufferData = NULL;
PFNGLNAMEDBUFFERSTORAGEPROC glad_glNamedBufferStorage = NULL;
PFNGLNAMEDBUFFERSUBDATAPROC glad_glNamedBufferSubData = NULL;
PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glad_glNamedFramebufferDrawBuffer = NULL;
PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glad_glNamedFramebufferDrawBuffers = NULL;
PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glad_glNamedFramebufferParameteri = NULL;
PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glad_glNamedFramebufferReadBuffer = NULL;
PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glad_glNamedFramebufferRenderbuffer = NULL;
PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glad_glNamedFramebufferTexture = NULL;
PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glad_glNamedFramebufferTextureLayer = NULL;
PFNGLNAMEDRENDERBUFFERSTORAGEPROC glad_glNamedRenderbufferStorage = NULL;
PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glNamedRenderbufferStorageMultisample = NULL;
PFNGLNORMALP3UIPROC glad_glNormalP3ui = NULL;
PFNGLNORMALP3UIVPROC glad_glNormalP3uiv = NULL;
PFNGLOBJECTLABELPROC glad_glObjectLabel = NULL;
@ -592,6 +686,7 @@ PFNGLPOINTPARAMETERIVPROC glad_glPointParameteriv = NULL;
PFNGLPOINTSIZEPROC glad_glPointSize = NULL;
PFNGLPOLYGONMODEPROC glad_glPolygonMode = NULL;
PFNGLPOLYGONOFFSETPROC glad_glPolygonOffset = NULL;
PFNGLPOLYGONOFFSETCLAMPPROC glad_glPolygonOffsetClamp = NULL;
PFNGLPOPDEBUGGROUPPROC glad_glPopDebugGroup = NULL;
PFNGLPRIMITIVEBOUNDINGBOXPROC glad_glPrimitiveBoundingBox = NULL;
PFNGLPRIMITIVERESTARTINDEXPROC glad_glPrimitiveRestartIndex = NULL;
@ -674,6 +769,7 @@ PFNGLSECONDARYCOLORP3UIVPROC glad_glSecondaryColorP3uiv = NULL;
PFNGLSHADERBINARYPROC glad_glShaderBinary = NULL;
PFNGLSHADERSOURCEPROC glad_glShaderSource = NULL;
PFNGLSHADERSTORAGEBLOCKBINDINGPROC glad_glShaderStorageBlockBinding = NULL;
PFNGLSPECIALIZESHADERPROC glad_glSpecializeShader = NULL;
PFNGLSTENCILFUNCPROC glad_glStencilFunc = NULL;
PFNGLSTENCILFUNCSEPARATEPROC glad_glStencilFuncSeparate = NULL;
PFNGLSTENCILMASKPROC glad_glStencilMask = NULL;
@ -709,7 +805,26 @@ PFNGLTEXSTORAGE3DMULTISAMPLEPROC glad_glTexStorage3DMultisample = NULL;
PFNGLTEXSUBIMAGE1DPROC glad_glTexSubImage1D = NULL;
PFNGLTEXSUBIMAGE2DPROC glad_glTexSubImage2D = NULL;
PFNGLTEXSUBIMAGE3DPROC glad_glTexSubImage3D = NULL;
PFNGLTEXTUREBARRIERPROC glad_glTextureBarrier = NULL;
PFNGLTEXTUREBUFFERPROC glad_glTextureBuffer = NULL;
PFNGLTEXTUREBUFFERRANGEPROC glad_glTextureBufferRange = NULL;
PFNGLTEXTUREPARAMETERIIVPROC glad_glTextureParameterIiv = NULL;
PFNGLTEXTUREPARAMETERIUIVPROC glad_glTextureParameterIuiv = NULL;
PFNGLTEXTUREPARAMETERFPROC glad_glTextureParameterf = NULL;
PFNGLTEXTUREPARAMETERFVPROC glad_glTextureParameterfv = NULL;
PFNGLTEXTUREPARAMETERIPROC glad_glTextureParameteri = NULL;
PFNGLTEXTUREPARAMETERIVPROC glad_glTextureParameteriv = NULL;
PFNGLTEXTURESTORAGE1DPROC glad_glTextureStorage1D = NULL;
PFNGLTEXTURESTORAGE2DPROC glad_glTextureStorage2D = NULL;
PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glad_glTextureStorage2DMultisample = NULL;
PFNGLTEXTURESTORAGE3DPROC glad_glTextureStorage3D = NULL;
PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glad_glTextureStorage3DMultisample = NULL;
PFNGLTEXTURESUBIMAGE1DPROC glad_glTextureSubImage1D = NULL;
PFNGLTEXTURESUBIMAGE2DPROC glad_glTextureSubImage2D = NULL;
PFNGLTEXTURESUBIMAGE3DPROC glad_glTextureSubImage3D = NULL;
PFNGLTEXTUREVIEWPROC glad_glTextureView = NULL;
PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glad_glTransformFeedbackBufferBase = NULL;
PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glad_glTransformFeedbackBufferRange = NULL;
PFNGLTRANSFORMFEEDBACKVARYINGSPROC glad_glTransformFeedbackVaryings = NULL;
PFNGLUNIFORM1DPROC glad_glUniform1d = NULL;
PFNGLUNIFORM1DVPROC glad_glUniform1dv = NULL;
@ -764,10 +879,19 @@ PFNGLUNIFORMMATRIX4X3DVPROC glad_glUniformMatrix4x3dv = NULL;
PFNGLUNIFORMMATRIX4X3FVPROC glad_glUniformMatrix4x3fv = NULL;
PFNGLUNIFORMSUBROUTINESUIVPROC glad_glUniformSubroutinesuiv = NULL;
PFNGLUNMAPBUFFERPROC glad_glUnmapBuffer = NULL;
PFNGLUNMAPNAMEDBUFFERPROC glad_glUnmapNamedBuffer = NULL;
PFNGLUSEPROGRAMPROC glad_glUseProgram = NULL;
PFNGLUSEPROGRAMSTAGESPROC glad_glUseProgramStages = NULL;
PFNGLVALIDATEPROGRAMPROC glad_glValidateProgram = NULL;
PFNGLVALIDATEPROGRAMPIPELINEPROC glad_glValidateProgramPipeline = NULL;
PFNGLVERTEXARRAYATTRIBBINDINGPROC glad_glVertexArrayAttribBinding = NULL;
PFNGLVERTEXARRAYATTRIBFORMATPROC glad_glVertexArrayAttribFormat = NULL;
PFNGLVERTEXARRAYATTRIBIFORMATPROC glad_glVertexArrayAttribIFormat = NULL;
PFNGLVERTEXARRAYATTRIBLFORMATPROC glad_glVertexArrayAttribLFormat = NULL;
PFNGLVERTEXARRAYBINDINGDIVISORPROC glad_glVertexArrayBindingDivisor = NULL;
PFNGLVERTEXARRAYELEMENTBUFFERPROC glad_glVertexArrayElementBuffer = NULL;
PFNGLVERTEXARRAYVERTEXBUFFERPROC glad_glVertexArrayVertexBuffer = NULL;
PFNGLVERTEXARRAYVERTEXBUFFERSPROC glad_glVertexArrayVertexBuffers = NULL;
PFNGLVERTEXATTRIB1DPROC glad_glVertexAttrib1d = NULL;
PFNGLVERTEXATTRIB1DVPROC glad_glVertexAttrib1dv = NULL;
PFNGLVERTEXATTRIB1FPROC glad_glVertexAttrib1f = NULL;
@ -862,105 +986,10 @@ PFNGLVIEWPORTINDEXEDFVPROC glad_glViewportIndexedfv = NULL;
PFNGLWAITSYNCPROC glad_glWaitSync = NULL;
int GLAD_GL_ARB_buffer_storage = 0;
int GLAD_GL_ARB_direct_state_access = 0;
int GLAD_GL_ARB_texture_compression_bptc = 0;
int GLAD_GL_EXT_buffer_storage = 0;
int GLAD_GL_EXT_clip_cull_distance = 0;
PFNGLCREATETRANSFORMFEEDBACKSPROC glad_glCreateTransformFeedbacks = NULL;
PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC glad_glTransformFeedbackBufferBase = NULL;
PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC glad_glTransformFeedbackBufferRange = NULL;
PFNGLGETTRANSFORMFEEDBACKIVPROC glad_glGetTransformFeedbackiv = NULL;
PFNGLGETTRANSFORMFEEDBACKI_VPROC glad_glGetTransformFeedbacki_v = NULL;
PFNGLGETTRANSFORMFEEDBACKI64_VPROC glad_glGetTransformFeedbacki64_v = NULL;
PFNGLCREATEBUFFERSPROC glad_glCreateBuffers = NULL;
PFNGLNAMEDBUFFERSTORAGEPROC glad_glNamedBufferStorage = NULL;
PFNGLNAMEDBUFFERDATAPROC glad_glNamedBufferData = NULL;
PFNGLNAMEDBUFFERSUBDATAPROC glad_glNamedBufferSubData = NULL;
PFNGLCOPYNAMEDBUFFERSUBDATAPROC glad_glCopyNamedBufferSubData = NULL;
PFNGLCLEARNAMEDBUFFERDATAPROC glad_glClearNamedBufferData = NULL;
PFNGLCLEARNAMEDBUFFERSUBDATAPROC glad_glClearNamedBufferSubData = NULL;
PFNGLMAPNAMEDBUFFERPROC glad_glMapNamedBuffer = NULL;
PFNGLMAPNAMEDBUFFERRANGEPROC glad_glMapNamedBufferRange = NULL;
PFNGLUNMAPNAMEDBUFFERPROC glad_glUnmapNamedBuffer = NULL;
PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC glad_glFlushMappedNamedBufferRange = NULL;
PFNGLGETNAMEDBUFFERPARAMETERIVPROC glad_glGetNamedBufferParameteriv = NULL;
PFNGLGETNAMEDBUFFERPARAMETERI64VPROC glad_glGetNamedBufferParameteri64v = NULL;
PFNGLGETNAMEDBUFFERPOINTERVPROC glad_glGetNamedBufferPointerv = NULL;
PFNGLGETNAMEDBUFFERSUBDATAPROC glad_glGetNamedBufferSubData = NULL;
PFNGLCREATEFRAMEBUFFERSPROC glad_glCreateFramebuffers = NULL;
PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC glad_glNamedFramebufferRenderbuffer = NULL;
PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC glad_glNamedFramebufferParameteri = NULL;
PFNGLNAMEDFRAMEBUFFERTEXTUREPROC glad_glNamedFramebufferTexture = NULL;
PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC glad_glNamedFramebufferTextureLayer = NULL;
PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC glad_glNamedFramebufferDrawBuffer = NULL;
PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC glad_glNamedFramebufferDrawBuffers = NULL;
PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC glad_glNamedFramebufferReadBuffer = NULL;
PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC glad_glInvalidateNamedFramebufferData = NULL;
PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC glad_glInvalidateNamedFramebufferSubData = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERIVPROC glad_glClearNamedFramebufferiv = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC glad_glClearNamedFramebufferuiv = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERFVPROC glad_glClearNamedFramebufferfv = NULL;
PFNGLCLEARNAMEDFRAMEBUFFERFIPROC glad_glClearNamedFramebufferfi = NULL;
PFNGLBLITNAMEDFRAMEBUFFERPROC glad_glBlitNamedFramebuffer = NULL;
PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC glad_glCheckNamedFramebufferStatus = NULL;
PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC glad_glGetNamedFramebufferParameteriv = NULL;
PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC glad_glGetNamedFramebufferAttachmentParameteriv = NULL;
PFNGLCREATERENDERBUFFERSPROC glad_glCreateRenderbuffers = NULL;
PFNGLNAMEDRENDERBUFFERSTORAGEPROC glad_glNamedRenderbufferStorage = NULL;
PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC glad_glNamedRenderbufferStorageMultisample = NULL;
PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC glad_glGetNamedRenderbufferParameteriv = NULL;
PFNGLCREATETEXTURESPROC glad_glCreateTextures = NULL;
PFNGLTEXTUREBUFFERPROC glad_glTextureBuffer = NULL;
PFNGLTEXTUREBUFFERRANGEPROC glad_glTextureBufferRange = NULL;
PFNGLTEXTURESTORAGE1DPROC glad_glTextureStorage1D = NULL;
PFNGLTEXTURESTORAGE2DPROC glad_glTextureStorage2D = NULL;
PFNGLTEXTURESTORAGE3DPROC glad_glTextureStorage3D = NULL;
PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC glad_glTextureStorage2DMultisample = NULL;
PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC glad_glTextureStorage3DMultisample = NULL;
PFNGLTEXTURESUBIMAGE1DPROC glad_glTextureSubImage1D = NULL;
PFNGLTEXTURESUBIMAGE2DPROC glad_glTextureSubImage2D = NULL;
PFNGLTEXTURESUBIMAGE3DPROC glad_glTextureSubImage3D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC glad_glCompressedTextureSubImage1D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC glad_glCompressedTextureSubImage2D = NULL;
PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC glad_glCompressedTextureSubImage3D = NULL;
PFNGLCOPYTEXTURESUBIMAGE1DPROC glad_glCopyTextureSubImage1D = NULL;
PFNGLCOPYTEXTURESUBIMAGE2DPROC glad_glCopyTextureSubImage2D = NULL;
PFNGLCOPYTEXTURESUBIMAGE3DPROC glad_glCopyTextureSubImage3D = NULL;
PFNGLTEXTUREPARAMETERFPROC glad_glTextureParameterf = NULL;
PFNGLTEXTUREPARAMETERFVPROC glad_glTextureParameterfv = NULL;
PFNGLTEXTUREPARAMETERIPROC glad_glTextureParameteri = NULL;
PFNGLTEXTUREPARAMETERIIVPROC glad_glTextureParameterIiv = NULL;
PFNGLTEXTUREPARAMETERIUIVPROC glad_glTextureParameterIuiv = NULL;
PFNGLTEXTUREPARAMETERIVPROC glad_glTextureParameteriv = NULL;
PFNGLGENERATETEXTUREMIPMAPPROC glad_glGenerateTextureMipmap = NULL;
PFNGLBINDTEXTUREUNITPROC glad_glBindTextureUnit = NULL;
PFNGLGETTEXTUREIMAGEPROC glad_glGetTextureImage = NULL;
PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC glad_glGetCompressedTextureImage = NULL;
PFNGLGETTEXTURELEVELPARAMETERFVPROC glad_glGetTextureLevelParameterfv = NULL;
PFNGLGETTEXTURELEVELPARAMETERIVPROC glad_glGetTextureLevelParameteriv = NULL;
PFNGLGETTEXTUREPARAMETERFVPROC glad_glGetTextureParameterfv = NULL;
PFNGLGETTEXTUREPARAMETERIIVPROC glad_glGetTextureParameterIiv = NULL;
PFNGLGETTEXTUREPARAMETERIUIVPROC glad_glGetTextureParameterIuiv = NULL;
PFNGLGETTEXTUREPARAMETERIVPROC glad_glGetTextureParameteriv = NULL;
PFNGLCREATEVERTEXARRAYSPROC glad_glCreateVertexArrays = NULL;
PFNGLDISABLEVERTEXARRAYATTRIBPROC glad_glDisableVertexArrayAttrib = NULL;
PFNGLENABLEVERTEXARRAYATTRIBPROC glad_glEnableVertexArrayAttrib = NULL;
PFNGLVERTEXARRAYELEMENTBUFFERPROC glad_glVertexArrayElementBuffer = NULL;
PFNGLVERTEXARRAYVERTEXBUFFERPROC glad_glVertexArrayVertexBuffer = NULL;
PFNGLVERTEXARRAYVERTEXBUFFERSPROC glad_glVertexArrayVertexBuffers = NULL;
PFNGLVERTEXARRAYATTRIBBINDINGPROC glad_glVertexArrayAttribBinding = NULL;
PFNGLVERTEXARRAYATTRIBFORMATPROC glad_glVertexArrayAttribFormat = NULL;
PFNGLVERTEXARRAYATTRIBIFORMATPROC glad_glVertexArrayAttribIFormat = NULL;
PFNGLVERTEXARRAYATTRIBLFORMATPROC glad_glVertexArrayAttribLFormat = NULL;
PFNGLVERTEXARRAYBINDINGDIVISORPROC glad_glVertexArrayBindingDivisor = NULL;
PFNGLGETVERTEXARRAYIVPROC glad_glGetVertexArrayiv = NULL;
PFNGLGETVERTEXARRAYINDEXEDIVPROC glad_glGetVertexArrayIndexediv = NULL;
PFNGLGETVERTEXARRAYINDEXED64IVPROC glad_glGetVertexArrayIndexed64iv = NULL;
PFNGLCREATESAMPLERSPROC glad_glCreateSamplers = NULL;
PFNGLCREATEPROGRAMPIPELINESPROC glad_glCreateProgramPipelines = NULL;
PFNGLCREATEQUERIESPROC glad_glCreateQueries = NULL;
PFNGLGETQUERYBUFFEROBJECTI64VPROC glad_glGetQueryBufferObjecti64v = NULL;
PFNGLGETQUERYBUFFEROBJECTIVPROC glad_glGetQueryBufferObjectiv = NULL;
PFNGLGETQUERYBUFFEROBJECTUI64VPROC glad_glGetQueryBufferObjectui64v = NULL;
PFNGLGETQUERYBUFFEROBJECTUIVPROC glad_glGetQueryBufferObjectuiv = NULL;
int GLAD_GL_EXT_texture_compression_s3tc = 0;
PFNGLBUFFERSTORAGEEXTPROC glad_glBufferStorageEXT = NULL;
static void load_GL_VERSION_1_0(GLADloadproc load) {
if(!GLAD_GL_VERSION_1_0) return;
@ -1590,6 +1619,138 @@ static void load_GL_VERSION_4_4(GLADloadproc load) {
glad_glBindImageTextures = (PFNGLBINDIMAGETEXTURESPROC)load("glBindImageTextures");
glad_glBindVertexBuffers = (PFNGLBINDVERTEXBUFFERSPROC)load("glBindVertexBuffers");
}
static void load_GL_VERSION_4_5(GLADloadproc load) {
if(!GLAD_GL_VERSION_4_5) return;
glad_glClipControl = (PFNGLCLIPCONTROLPROC)load("glClipControl");
glad_glCreateTransformFeedbacks = (PFNGLCREATETRANSFORMFEEDBACKSPROC)load("glCreateTransformFeedbacks");
glad_glTransformFeedbackBufferBase = (PFNGLTRANSFORMFEEDBACKBUFFERBASEPROC)load("glTransformFeedbackBufferBase");
glad_glTransformFeedbackBufferRange = (PFNGLTRANSFORMFEEDBACKBUFFERRANGEPROC)load("glTransformFeedbackBufferRange");
glad_glGetTransformFeedbackiv = (PFNGLGETTRANSFORMFEEDBACKIVPROC)load("glGetTransformFeedbackiv");
glad_glGetTransformFeedbacki_v = (PFNGLGETTRANSFORMFEEDBACKI_VPROC)load("glGetTransformFeedbacki_v");
glad_glGetTransformFeedbacki64_v = (PFNGLGETTRANSFORMFEEDBACKI64_VPROC)load("glGetTransformFeedbacki64_v");
glad_glCreateBuffers = (PFNGLCREATEBUFFERSPROC)load("glCreateBuffers");
glad_glNamedBufferStorage = (PFNGLNAMEDBUFFERSTORAGEPROC)load("glNamedBufferStorage");
glad_glNamedBufferData = (PFNGLNAMEDBUFFERDATAPROC)load("glNamedBufferData");
glad_glNamedBufferSubData = (PFNGLNAMEDBUFFERSUBDATAPROC)load("glNamedBufferSubData");
glad_glCopyNamedBufferSubData = (PFNGLCOPYNAMEDBUFFERSUBDATAPROC)load("glCopyNamedBufferSubData");
glad_glClearNamedBufferData = (PFNGLCLEARNAMEDBUFFERDATAPROC)load("glClearNamedBufferData");
glad_glClearNamedBufferSubData = (PFNGLCLEARNAMEDBUFFERSUBDATAPROC)load("glClearNamedBufferSubData");
glad_glMapNamedBuffer = (PFNGLMAPNAMEDBUFFERPROC)load("glMapNamedBuffer");
glad_glMapNamedBufferRange = (PFNGLMAPNAMEDBUFFERRANGEPROC)load("glMapNamedBufferRange");
glad_glUnmapNamedBuffer = (PFNGLUNMAPNAMEDBUFFERPROC)load("glUnmapNamedBuffer");
glad_glFlushMappedNamedBufferRange = (PFNGLFLUSHMAPPEDNAMEDBUFFERRANGEPROC)load("glFlushMappedNamedBufferRange");
glad_glGetNamedBufferParameteriv = (PFNGLGETNAMEDBUFFERPARAMETERIVPROC)load("glGetNamedBufferParameteriv");
glad_glGetNamedBufferParameteri64v = (PFNGLGETNAMEDBUFFERPARAMETERI64VPROC)load("glGetNamedBufferParameteri64v");
glad_glGetNamedBufferPointerv = (PFNGLGETNAMEDBUFFERPOINTERVPROC)load("glGetNamedBufferPointerv");
glad_glGetNamedBufferSubData = (PFNGLGETNAMEDBUFFERSUBDATAPROC)load("glGetNamedBufferSubData");
glad_glCreateFramebuffers = (PFNGLCREATEFRAMEBUFFERSPROC)load("glCreateFramebuffers");
glad_glNamedFramebufferRenderbuffer = (PFNGLNAMEDFRAMEBUFFERRENDERBUFFERPROC)load("glNamedFramebufferRenderbuffer");
glad_glNamedFramebufferParameteri = (PFNGLNAMEDFRAMEBUFFERPARAMETERIPROC)load("glNamedFramebufferParameteri");
glad_glNamedFramebufferTexture = (PFNGLNAMEDFRAMEBUFFERTEXTUREPROC)load("glNamedFramebufferTexture");
glad_glNamedFramebufferTextureLayer = (PFNGLNAMEDFRAMEBUFFERTEXTURELAYERPROC)load("glNamedFramebufferTextureLayer");
glad_glNamedFramebufferDrawBuffer = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERPROC)load("glNamedFramebufferDrawBuffer");
glad_glNamedFramebufferDrawBuffers = (PFNGLNAMEDFRAMEBUFFERDRAWBUFFERSPROC)load("glNamedFramebufferDrawBuffers");
glad_glNamedFramebufferReadBuffer = (PFNGLNAMEDFRAMEBUFFERREADBUFFERPROC)load("glNamedFramebufferReadBuffer");
glad_glInvalidateNamedFramebufferData = (PFNGLINVALIDATENAMEDFRAMEBUFFERDATAPROC)load("glInvalidateNamedFramebufferData");
glad_glInvalidateNamedFramebufferSubData = (PFNGLINVALIDATENAMEDFRAMEBUFFERSUBDATAPROC)load("glInvalidateNamedFramebufferSubData");
glad_glClearNamedFramebufferiv = (PFNGLCLEARNAMEDFRAMEBUFFERIVPROC)load("glClearNamedFramebufferiv");
glad_glClearNamedFramebufferuiv = (PFNGLCLEARNAMEDFRAMEBUFFERUIVPROC)load("glClearNamedFramebufferuiv");
glad_glClearNamedFramebufferfv = (PFNGLCLEARNAMEDFRAMEBUFFERFVPROC)load("glClearNamedFramebufferfv");
glad_glClearNamedFramebufferfi = (PFNGLCLEARNAMEDFRAMEBUFFERFIPROC)load("glClearNamedFramebufferfi");
glad_glBlitNamedFramebuffer = (PFNGLBLITNAMEDFRAMEBUFFERPROC)load("glBlitNamedFramebuffer");
glad_glCheckNamedFramebufferStatus = (PFNGLCHECKNAMEDFRAMEBUFFERSTATUSPROC)load("glCheckNamedFramebufferStatus");
glad_glGetNamedFramebufferParameteriv = (PFNGLGETNAMEDFRAMEBUFFERPARAMETERIVPROC)load("glGetNamedFramebufferParameteriv");
glad_glGetNamedFramebufferAttachmentParameteriv = (PFNGLGETNAMEDFRAMEBUFFERATTACHMENTPARAMETERIVPROC)load("glGetNamedFramebufferAttachmentParameteriv");
glad_glCreateRenderbuffers = (PFNGLCREATERENDERBUFFERSPROC)load("glCreateRenderbuffers");
glad_glNamedRenderbufferStorage = (PFNGLNAMEDRENDERBUFFERSTORAGEPROC)load("glNamedRenderbufferStorage");
glad_glNamedRenderbufferStorageMultisample = (PFNGLNAMEDRENDERBUFFERSTORAGEMULTISAMPLEPROC)load("glNamedRenderbufferStorageMultisample");
glad_glGetNamedRenderbufferParameteriv = (PFNGLGETNAMEDRENDERBUFFERPARAMETERIVPROC)load("glGetNamedRenderbufferParameteriv");
glad_glCreateTextures = (PFNGLCREATETEXTURESPROC)load("glCreateTextures");
glad_glTextureBuffer = (PFNGLTEXTUREBUFFERPROC)load("glTextureBuffer");
glad_glTextureBufferRange = (PFNGLTEXTUREBUFFERRANGEPROC)load("glTextureBufferRange");
glad_glTextureStorage1D = (PFNGLTEXTURESTORAGE1DPROC)load("glTextureStorage1D");
glad_glTextureStorage2D = (PFNGLTEXTURESTORAGE2DPROC)load("glTextureStorage2D");
glad_glTextureStorage3D = (PFNGLTEXTURESTORAGE3DPROC)load("glTextureStorage3D");
glad_glTextureStorage2DMultisample = (PFNGLTEXTURESTORAGE2DMULTISAMPLEPROC)load("glTextureStorage2DMultisample");
glad_glTextureStorage3DMultisample = (PFNGLTEXTURESTORAGE3DMULTISAMPLEPROC)load("glTextureStorage3DMultisample");
glad_glTextureSubImage1D = (PFNGLTEXTURESUBIMAGE1DPROC)load("glTextureSubImage1D");
glad_glTextureSubImage2D = (PFNGLTEXTURESUBIMAGE2DPROC)load("glTextureSubImage2D");
glad_glTextureSubImage3D = (PFNGLTEXTURESUBIMAGE3DPROC)load("glTextureSubImage3D");
glad_glCompressedTextureSubImage1D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE1DPROC)load("glCompressedTextureSubImage1D");
glad_glCompressedTextureSubImage2D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE2DPROC)load("glCompressedTextureSubImage2D");
glad_glCompressedTextureSubImage3D = (PFNGLCOMPRESSEDTEXTURESUBIMAGE3DPROC)load("glCompressedTextureSubImage3D");
glad_glCopyTextureSubImage1D = (PFNGLCOPYTEXTURESUBIMAGE1DPROC)load("glCopyTextureSubImage1D");
glad_glCopyTextureSubImage2D = (PFNGLCOPYTEXTURESUBIMAGE2DPROC)load("glCopyTextureSubImage2D");
glad_glCopyTextureSubImage3D = (PFNGLCOPYTEXTURESUBIMAGE3DPROC)load("glCopyTextureSubImage3D");
glad_glTextureParameterf = (PFNGLTEXTUREPARAMETERFPROC)load("glTextureParameterf");
glad_glTextureParameterfv = (PFNGLTEXTUREPARAMETERFVPROC)load("glTextureParameterfv");
glad_glTextureParameteri = (PFNGLTEXTUREPARAMETERIPROC)load("glTextureParameteri");
glad_glTextureParameterIiv = (PFNGLTEXTUREPARAMETERIIVPROC)load("glTextureParameterIiv");
glad_glTextureParameterIuiv = (PFNGLTEXTUREPARAMETERIUIVPROC)load("glTextureParameterIuiv");
glad_glTextureParameteriv = (PFNGLTEXTUREPARAMETERIVPROC)load("glTextureParameteriv");
glad_glGenerateTextureMipmap = (PFNGLGENERATETEXTUREMIPMAPPROC)load("glGenerateTextureMipmap");
glad_glBindTextureUnit = (PFNGLBINDTEXTUREUNITPROC)load("glBindTextureUnit");
glad_glGetTextureImage = (PFNGLGETTEXTUREIMAGEPROC)load("glGetTextureImage");
glad_glGetCompressedTextureImage = (PFNGLGETCOMPRESSEDTEXTUREIMAGEPROC)load("glGetCompressedTextureImage");
glad_glGetTextureLevelParameterfv = (PFNGLGETTEXTURELEVELPARAMETERFVPROC)load("glGetTextureLevelParameterfv");
glad_glGetTextureLevelParameteriv = (PFNGLGETTEXTURELEVELPARAMETERIVPROC)load("glGetTextureLevelParameteriv");
glad_glGetTextureParameterfv = (PFNGLGETTEXTUREPARAMETERFVPROC)load("glGetTextureParameterfv");
glad_glGetTextureParameterIiv = (PFNGLGETTEXTUREPARAMETERIIVPROC)load("glGetTextureParameterIiv");
glad_glGetTextureParameterIuiv = (PFNGLGETTEXTUREPARAMETERIUIVPROC)load("glGetTextureParameterIuiv");
glad_glGetTextureParameteriv = (PFNGLGETTEXTUREPARAMETERIVPROC)load("glGetTextureParameteriv");
glad_glCreateVertexArrays = (PFNGLCREATEVERTEXARRAYSPROC)load("glCreateVertexArrays");
glad_glDisableVertexArrayAttrib = (PFNGLDISABLEVERTEXARRAYATTRIBPROC)load("glDisableVertexArrayAttrib");
glad_glEnableVertexArrayAttrib = (PFNGLENABLEVERTEXARRAYATTRIBPROC)load("glEnableVertexArrayAttrib");
glad_glVertexArrayElementBuffer = (PFNGLVERTEXARRAYELEMENTBUFFERPROC)load("glVertexArrayElementBuffer");
glad_glVertexArrayVertexBuffer = (PFNGLVERTEXARRAYVERTEXBUFFERPROC)load("glVertexArrayVertexBuffer");
glad_glVertexArrayVertexBuffers = (PFNGLVERTEXARRAYVERTEXBUFFERSPROC)load("glVertexArrayVertexBuffers");
glad_glVertexArrayAttribBinding = (PFNGLVERTEXARRAYATTRIBBINDINGPROC)load("glVertexArrayAttribBinding");
glad_glVertexArrayAttribFormat = (PFNGLVERTEXARRAYATTRIBFORMATPROC)load("glVertexArrayAttribFormat");
glad_glVertexArrayAttribIFormat = (PFNGLVERTEXARRAYATTRIBIFORMATPROC)load("glVertexArrayAttribIFormat");
glad_glVertexArrayAttribLFormat = (PFNGLVERTEXARRAYATTRIBLFORMATPROC)load("glVertexArrayAttribLFormat");
glad_glVertexArrayBindingDivisor = (PFNGLVERTEXARRAYBINDINGDIVISORPROC)load("glVertexArrayBindingDivisor");
glad_glGetVertexArrayiv = (PFNGLGETVERTEXARRAYIVPROC)load("glGetVertexArrayiv");
glad_glGetVertexArrayIndexediv = (PFNGLGETVERTEXARRAYINDEXEDIVPROC)load("glGetVertexArrayIndexediv");
glad_glGetVertexArrayIndexed64iv = (PFNGLGETVERTEXARRAYINDEXED64IVPROC)load("glGetVertexArrayIndexed64iv");
glad_glCreateSamplers = (PFNGLCREATESAMPLERSPROC)load("glCreateSamplers");
glad_glCreateProgramPipelines = (PFNGLCREATEPROGRAMPIPELINESPROC)load("glCreateProgramPipelines");
glad_glCreateQueries = (PFNGLCREATEQUERIESPROC)load("glCreateQueries");
glad_glGetQueryBufferObjecti64v = (PFNGLGETQUERYBUFFEROBJECTI64VPROC)load("glGetQueryBufferObjecti64v");
glad_glGetQueryBufferObjectiv = (PFNGLGETQUERYBUFFEROBJECTIVPROC)load("glGetQueryBufferObjectiv");
glad_glGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECTUI64VPROC)load("glGetQueryBufferObjectui64v");
glad_glGetQueryBufferObjectuiv = (PFNGLGETQUERYBUFFEROBJECTUIVPROC)load("glGetQueryBufferObjectuiv");
glad_glMemoryBarrierByRegion = (PFNGLMEMORYBARRIERBYREGIONPROC)load("glMemoryBarrierByRegion");
glad_glGetTextureSubImage = (PFNGLGETTEXTURESUBIMAGEPROC)load("glGetTextureSubImage");
glad_glGetCompressedTextureSubImage = (PFNGLGETCOMPRESSEDTEXTURESUBIMAGEPROC)load("glGetCompressedTextureSubImage");
glad_glGetGraphicsResetStatus = (PFNGLGETGRAPHICSRESETSTATUSPROC)load("glGetGraphicsResetStatus");
glad_glGetnCompressedTexImage = (PFNGLGETNCOMPRESSEDTEXIMAGEPROC)load("glGetnCompressedTexImage");
glad_glGetnTexImage = (PFNGLGETNTEXIMAGEPROC)load("glGetnTexImage");
glad_glGetnUniformdv = (PFNGLGETNUNIFORMDVPROC)load("glGetnUniformdv");
glad_glGetnUniformfv = (PFNGLGETNUNIFORMFVPROC)load("glGetnUniformfv");
glad_glGetnUniformiv = (PFNGLGETNUNIFORMIVPROC)load("glGetnUniformiv");
glad_glGetnUniformuiv = (PFNGLGETNUNIFORMUIVPROC)load("glGetnUniformuiv");
glad_glReadnPixels = (PFNGLREADNPIXELSPROC)load("glReadnPixels");
glad_glGetnMapdv = (PFNGLGETNMAPDVPROC)load("glGetnMapdv");
glad_glGetnMapfv = (PFNGLGETNMAPFVPROC)load("glGetnMapfv");
glad_glGetnMapiv = (PFNGLGETNMAPIVPROC)load("glGetnMapiv");
glad_glGetnPixelMapfv = (PFNGLGETNPIXELMAPFVPROC)load("glGetnPixelMapfv");
glad_glGetnPixelMapuiv = (PFNGLGETNPIXELMAPUIVPROC)load("glGetnPixelMapuiv");
glad_glGetnPixelMapusv = (PFNGLGETNPIXELMAPUSVPROC)load("glGetnPixelMapusv");
glad_glGetnPolygonStipple = (PFNGLGETNPOLYGONSTIPPLEPROC)load("glGetnPolygonStipple");
glad_glGetnColorTable = (PFNGLGETNCOLORTABLEPROC)load("glGetnColorTable");
glad_glGetnConvolutionFilter = (PFNGLGETNCONVOLUTIONFILTERPROC)load("glGetnConvolutionFilter");
glad_glGetnSeparableFilter = (PFNGLGETNSEPARABLEFILTERPROC)load("glGetnSeparableFilter");
glad_glGetnHistogram = (PFNGLGETNHISTOGRAMPROC)load("glGetnHistogram");
glad_glGetnMinmax = (PFNGLGETNMINMAXPROC)load("glGetnMinmax");
glad_glTextureBarrier = (PFNGLTEXTUREBARRIERPROC)load("glTextureBarrier");
}
static void load_GL_VERSION_4_6(GLADloadproc load) {
if(!GLAD_GL_VERSION_4_6) return;
glad_glSpecializeShader = (PFNGLSPECIALIZESHADERPROC)load("glSpecializeShader");
glad_glMultiDrawArraysIndirectCount = (PFNGLMULTIDRAWARRAYSINDIRECTCOUNTPROC)load("glMultiDrawArraysIndirectCount");
glad_glMultiDrawElementsIndirectCount = (PFNGLMULTIDRAWELEMENTSINDIRECTCOUNTPROC)load("glMultiDrawElementsIndirectCount");
glad_glPolygonOffsetClamp = (PFNGLPOLYGONOFFSETCLAMPPROC)load("glPolygonOffsetClamp");
}
static void load_GL_ARB_buffer_storage(GLADloadproc load) {
if(!GLAD_GL_ARB_buffer_storage) return;
glad_glBufferStorage = (PFNGLBUFFERSTORAGEPROC)load("glBufferStorage");
@ -1698,6 +1859,8 @@ static int find_extensionsGL(void) {
if (!get_exts()) return 0;
GLAD_GL_ARB_buffer_storage = has_ext("GL_ARB_buffer_storage");
GLAD_GL_ARB_direct_state_access = has_ext("GL_ARB_direct_state_access");
GLAD_GL_ARB_texture_compression_bptc = has_ext("GL_ARB_texture_compression_bptc");
GLAD_GL_EXT_texture_compression_s3tc = has_ext("GL_EXT_texture_compression_s3tc");
free_exts();
return 1;
}
@ -1755,9 +1918,11 @@ static void find_coreGL(void) {
GLAD_GL_VERSION_4_2 = (major == 4 && minor >= 2) || major > 4;
GLAD_GL_VERSION_4_3 = (major == 4 && minor >= 3) || major > 4;
GLAD_GL_VERSION_4_4 = (major == 4 && minor >= 4) || major > 4;
if (GLVersion.major > 4 || (GLVersion.major >= 4 && GLVersion.minor >= 4)) {
GLAD_GL_VERSION_4_5 = (major == 4 && minor >= 5) || major > 4;
GLAD_GL_VERSION_4_6 = (major == 4 && minor >= 6) || major > 4;
if (GLVersion.major > 4 || (GLVersion.major >= 4 && GLVersion.minor >= 6)) {
max_loaded_major = 4;
max_loaded_minor = 4;
max_loaded_minor = 6;
}
}
@ -1784,6 +1949,8 @@ int gladLoadGLLoader(GLADloadproc load) {
load_GL_VERSION_4_2(load);
load_GL_VERSION_4_3(load);
load_GL_VERSION_4_4(load);
load_GL_VERSION_4_5(load);
load_GL_VERSION_4_6(load);
if (!find_extensionsGL()) return 0;
load_GL_ARB_buffer_storage(load);
@ -2169,6 +2336,7 @@ static int find_extensionsGLES2(void) {
if (!get_exts()) return 0;
GLAD_GL_EXT_buffer_storage = has_ext("GL_EXT_buffer_storage");
GLAD_GL_EXT_clip_cull_distance = has_ext("GL_EXT_clip_cull_distance");
GLAD_GL_EXT_texture_compression_s3tc = has_ext("GL_EXT_texture_compression_s3tc");
free_exts();
return 1;
}

14
externals/libspng/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,14 @@
add_library(spng STATIC spng.h spng.c)
target_compile_definitions(spng PUBLIC SPNG_STATIC)
target_include_directories(spng PUBLIC ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(spng PRIVATE ZLIB::ZLIB)
# Enable SSE4.1 on x64
if ("x86_64" IN_LIST ARCHITECTURE)
target_compile_definitions(spng PRIVATE SPNG_SSE=4)
if (NOT MSVC)
target_compile_options(spng PRIVATE -msse4.1)
endif()
endif()
add_library(spng::spng ALIAS spng)

6979
externals/libspng/spng.c vendored Normal file

File diff suppressed because it is too large Load Diff

537
externals/libspng/spng.h vendored Normal file
View File

@ -0,0 +1,537 @@
/* SPDX-License-Identifier: BSD-2-Clause */
#ifndef SPNG_H
#define SPNG_H
#ifdef __cplusplus
extern "C" {
#endif
#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(SPNG_STATIC)
#if defined(SPNG__BUILD)
#define SPNG_API __declspec(dllexport)
#else
#define SPNG_API __declspec(dllimport)
#endif
#else
#define SPNG_API
#endif
#if defined(_MSC_VER)
#define SPNG_CDECL __cdecl
#else
#define SPNG_CDECL
#endif
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#define SPNG_VERSION_MAJOR 0
#define SPNG_VERSION_MINOR 7
#define SPNG_VERSION_PATCH 3
enum spng_errno
{
SPNG_IO_ERROR = -2,
SPNG_IO_EOF = -1,
SPNG_OK = 0,
SPNG_EINVAL,
SPNG_EMEM,
SPNG_EOVERFLOW,
SPNG_ESIGNATURE,
SPNG_EWIDTH,
SPNG_EHEIGHT,
SPNG_EUSER_WIDTH,
SPNG_EUSER_HEIGHT,
SPNG_EBIT_DEPTH,
SPNG_ECOLOR_TYPE,
SPNG_ECOMPRESSION_METHOD,
SPNG_EFILTER_METHOD,
SPNG_EINTERLACE_METHOD,
SPNG_EIHDR_SIZE,
SPNG_ENOIHDR,
SPNG_ECHUNK_POS,
SPNG_ECHUNK_SIZE,
SPNG_ECHUNK_CRC,
SPNG_ECHUNK_TYPE,
SPNG_ECHUNK_UNKNOWN_CRITICAL,
SPNG_EDUP_PLTE,
SPNG_EDUP_CHRM,
SPNG_EDUP_GAMA,
SPNG_EDUP_ICCP,
SPNG_EDUP_SBIT,
SPNG_EDUP_SRGB,
SPNG_EDUP_BKGD,
SPNG_EDUP_HIST,
SPNG_EDUP_TRNS,
SPNG_EDUP_PHYS,
SPNG_EDUP_TIME,
SPNG_EDUP_OFFS,
SPNG_EDUP_EXIF,
SPNG_ECHRM,
SPNG_EPLTE_IDX,
SPNG_ETRNS_COLOR_TYPE,
SPNG_ETRNS_NO_PLTE,
SPNG_EGAMA,
SPNG_EICCP_NAME,
SPNG_EICCP_COMPRESSION_METHOD,
SPNG_ESBIT,
SPNG_ESRGB,
SPNG_ETEXT,
SPNG_ETEXT_KEYWORD,
SPNG_EZTXT,
SPNG_EZTXT_COMPRESSION_METHOD,
SPNG_EITXT,
SPNG_EITXT_COMPRESSION_FLAG,
SPNG_EITXT_COMPRESSION_METHOD,
SPNG_EITXT_LANG_TAG,
SPNG_EITXT_TRANSLATED_KEY,
SPNG_EBKGD_NO_PLTE,
SPNG_EBKGD_PLTE_IDX,
SPNG_EHIST_NO_PLTE,
SPNG_EPHYS,
SPNG_ESPLT_NAME,
SPNG_ESPLT_DUP_NAME,
SPNG_ESPLT_DEPTH,
SPNG_ETIME,
SPNG_EOFFS,
SPNG_EEXIF,
SPNG_EIDAT_TOO_SHORT,
SPNG_EIDAT_STREAM,
SPNG_EZLIB,
SPNG_EFILTER,
SPNG_EBUFSIZ,
SPNG_EIO,
SPNG_EOF,
SPNG_EBUF_SET,
SPNG_EBADSTATE,
SPNG_EFMT,
SPNG_EFLAGS,
SPNG_ECHUNKAVAIL,
SPNG_ENCODE_ONLY,
SPNG_EOI,
SPNG_ENOPLTE,
SPNG_ECHUNK_LIMITS,
SPNG_EZLIB_INIT,
SPNG_ECHUNK_STDLEN,
SPNG_EINTERNAL,
SPNG_ECTXTYPE,
SPNG_ENOSRC,
SPNG_ENODST,
SPNG_EOPSTATE,
SPNG_ENOTFINAL,
};
enum spng_text_type
{
SPNG_TEXT = 1,
SPNG_ZTXT = 2,
SPNG_ITXT = 3
};
enum spng_color_type
{
SPNG_COLOR_TYPE_GRAYSCALE = 0,
SPNG_COLOR_TYPE_TRUECOLOR = 2,
SPNG_COLOR_TYPE_INDEXED = 3,
SPNG_COLOR_TYPE_GRAYSCALE_ALPHA = 4,
SPNG_COLOR_TYPE_TRUECOLOR_ALPHA = 6
};
enum spng_filter
{
SPNG_FILTER_NONE = 0,
SPNG_FILTER_SUB = 1,
SPNG_FILTER_UP = 2,
SPNG_FILTER_AVERAGE = 3,
SPNG_FILTER_PAETH = 4
};
enum spng_filter_choice
{
SPNG_DISABLE_FILTERING = 0,
SPNG_FILTER_CHOICE_NONE = 8,
SPNG_FILTER_CHOICE_SUB = 16,
SPNG_FILTER_CHOICE_UP = 32,
SPNG_FILTER_CHOICE_AVG = 64,
SPNG_FILTER_CHOICE_PAETH = 128,
SPNG_FILTER_CHOICE_ALL = (8|16|32|64|128)
};
enum spng_interlace_method
{
SPNG_INTERLACE_NONE = 0,
SPNG_INTERLACE_ADAM7 = 1
};
/* Channels are always in byte-order */
enum spng_format
{
SPNG_FMT_RGBA8 = 1,
SPNG_FMT_RGBA16 = 2,
SPNG_FMT_RGB8 = 4,
/* Partially implemented, see documentation */
SPNG_FMT_GA8 = 16,
SPNG_FMT_GA16 = 32,
SPNG_FMT_G8 = 64,
/* No conversion or scaling */
SPNG_FMT_PNG = 256,
SPNG_FMT_RAW = 512 /* big-endian (everything else is host-endian) */
};
enum spng_ctx_flags
{
SPNG_CTX_IGNORE_ADLER32 = 1, /* Ignore checksum in DEFLATE streams */
SPNG_CTX_ENCODER = 2 /* Create an encoder context */
};
enum spng_decode_flags
{
SPNG_DECODE_USE_TRNS = 1, /* Deprecated */
SPNG_DECODE_USE_GAMA = 2, /* Deprecated */
SPNG_DECODE_USE_SBIT = 8, /* Undocumented */
SPNG_DECODE_TRNS = 1, /* Apply transparency */
SPNG_DECODE_GAMMA = 2, /* Apply gamma correction */
SPNG_DECODE_PROGRESSIVE = 256 /* Initialize for progressive reads */
};
enum spng_crc_action
{
/* Default for critical chunks */
SPNG_CRC_ERROR = 0,
/* Discard chunk, invalid for critical chunks.
Since v0.6.2: default for ancillary chunks */
SPNG_CRC_DISCARD = 1,
/* Ignore and don't calculate checksum.
Since v0.6.2: also ignores checksums in DEFLATE streams */
SPNG_CRC_USE = 2
};
enum spng_encode_flags
{
SPNG_ENCODE_PROGRESSIVE = 1, /* Initialize for progressive writes */
SPNG_ENCODE_FINALIZE = 2, /* Finalize PNG after encoding image */
};
struct spng_ihdr
{
uint32_t width;
uint32_t height;
uint8_t bit_depth;
uint8_t color_type;
uint8_t compression_method;
uint8_t filter_method;
uint8_t interlace_method;
};
struct spng_plte_entry
{
uint8_t red;
uint8_t green;
uint8_t blue;
uint8_t alpha; /* Reserved for internal use */
};
struct spng_plte
{
uint32_t n_entries;
struct spng_plte_entry entries[256];
};
struct spng_trns
{
uint16_t gray;
uint16_t red;
uint16_t green;
uint16_t blue;
uint32_t n_type3_entries;
uint8_t type3_alpha[256];
};
struct spng_chrm_int
{
uint32_t white_point_x;
uint32_t white_point_y;
uint32_t red_x;
uint32_t red_y;
uint32_t green_x;
uint32_t green_y;
uint32_t blue_x;
uint32_t blue_y;
};
struct spng_chrm
{
double white_point_x;
double white_point_y;
double red_x;
double red_y;
double green_x;
double green_y;
double blue_x;
double blue_y;
};
struct spng_iccp
{
char profile_name[80];
size_t profile_len;
char *profile;
};
struct spng_sbit
{
uint8_t grayscale_bits;
uint8_t red_bits;
uint8_t green_bits;
uint8_t blue_bits;
uint8_t alpha_bits;
};
struct spng_text
{
char keyword[80];
int type;
size_t length;
char *text;
uint8_t compression_flag; /* iTXt only */
uint8_t compression_method; /* iTXt, ztXt only */
char *language_tag; /* iTXt only */
char *translated_keyword; /* iTXt only */
};
struct spng_bkgd
{
uint16_t gray; /* Only for gray/gray alpha */
uint16_t red;
uint16_t green;
uint16_t blue;
uint16_t plte_index; /* Only for indexed color */
};
struct spng_hist
{
uint16_t frequency[256];
};
struct spng_phys
{
uint32_t ppu_x, ppu_y;
uint8_t unit_specifier;
};
struct spng_splt_entry
{
uint16_t red;
uint16_t green;
uint16_t blue;
uint16_t alpha;
uint16_t frequency;
};
struct spng_splt
{
char name[80];
uint8_t sample_depth;
uint32_t n_entries;
struct spng_splt_entry *entries;
};
struct spng_time
{
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
uint8_t second;
};
struct spng_offs
{
int32_t x, y;
uint8_t unit_specifier;
};
struct spng_exif
{
size_t length;
char *data;
};
struct spng_chunk
{
size_t offset;
uint32_t length;
uint8_t type[4];
uint32_t crc;
};
enum spng_location
{
SPNG_AFTER_IHDR = 1,
SPNG_AFTER_PLTE = 2,
SPNG_AFTER_IDAT = 8,
};
struct spng_unknown_chunk
{
uint8_t type[4];
size_t length;
void *data;
enum spng_location location;
};
enum spng_option
{
SPNG_KEEP_UNKNOWN_CHUNKS = 1,
SPNG_IMG_COMPRESSION_LEVEL,
SPNG_IMG_WINDOW_BITS,
SPNG_IMG_MEM_LEVEL,
SPNG_IMG_COMPRESSION_STRATEGY,
SPNG_TEXT_COMPRESSION_LEVEL,
SPNG_TEXT_WINDOW_BITS,
SPNG_TEXT_MEM_LEVEL,
SPNG_TEXT_COMPRESSION_STRATEGY,
SPNG_FILTER_CHOICE,
SPNG_CHUNK_COUNT_LIMIT,
SPNG_ENCODE_TO_BUFFER,
};
typedef void* SPNG_CDECL spng_malloc_fn(size_t size);
typedef void* SPNG_CDECL spng_realloc_fn(void* ptr, size_t size);
typedef void* SPNG_CDECL spng_calloc_fn(size_t count, size_t size);
typedef void SPNG_CDECL spng_free_fn(void* ptr);
struct spng_alloc
{
spng_malloc_fn *malloc_fn;
spng_realloc_fn *realloc_fn;
spng_calloc_fn *calloc_fn;
spng_free_fn *free_fn;
};
struct spng_row_info
{
uint32_t scanline_idx;
uint32_t row_num; /* deinterlaced row index */
int pass;
uint8_t filter;
};
typedef struct spng_ctx spng_ctx;
typedef int spng_read_fn(spng_ctx *ctx, void *user, void *dest, size_t length);
typedef int spng_write_fn(spng_ctx *ctx, void *user, void *src, size_t length);
typedef int spng_rw_fn(spng_ctx *ctx, void *user, void *dst_src, size_t length);
SPNG_API spng_ctx *spng_ctx_new(int flags);
SPNG_API spng_ctx *spng_ctx_new2(struct spng_alloc *alloc, int flags);
SPNG_API void spng_ctx_free(spng_ctx *ctx);
SPNG_API int spng_set_png_buffer(spng_ctx *ctx, const void *buf, size_t size);
SPNG_API int spng_set_png_stream(spng_ctx *ctx, spng_rw_fn *rw_func, void *user);
SPNG_API int spng_set_png_file(spng_ctx *ctx, FILE *file);
SPNG_API void *spng_get_png_buffer(spng_ctx *ctx, size_t *len, int *error);
SPNG_API int spng_set_image_limits(spng_ctx *ctx, uint32_t width, uint32_t height);
SPNG_API int spng_get_image_limits(spng_ctx *ctx, uint32_t *width, uint32_t *height);
SPNG_API int spng_set_chunk_limits(spng_ctx *ctx, size_t chunk_size, size_t cache_size);
SPNG_API int spng_get_chunk_limits(spng_ctx *ctx, size_t *chunk_size, size_t *cache_size);
SPNG_API int spng_set_crc_action(spng_ctx *ctx, int critical, int ancillary);
SPNG_API int spng_set_option(spng_ctx *ctx, enum spng_option option, int value);
SPNG_API int spng_get_option(spng_ctx *ctx, enum spng_option option, int *value);
SPNG_API int spng_decoded_image_size(spng_ctx *ctx, int fmt, size_t *len);
/* Decode */
SPNG_API int spng_decode_image(spng_ctx *ctx, void *out, size_t len, int fmt, int flags);
/* Progressive decode */
SPNG_API int spng_decode_scanline(spng_ctx *ctx, void *out, size_t len);
SPNG_API int spng_decode_row(spng_ctx *ctx, void *out, size_t len);
SPNG_API int spng_decode_chunks(spng_ctx *ctx);
/* Encode/decode */
SPNG_API int spng_get_row_info(spng_ctx *ctx, struct spng_row_info *row_info);
/* Encode */
SPNG_API int spng_encode_image(spng_ctx *ctx, const void *img, size_t len, int fmt, int flags);
/* Progressive encode */
SPNG_API int spng_encode_scanline(spng_ctx *ctx, const void *scanline, size_t len);
SPNG_API int spng_encode_row(spng_ctx *ctx, const void *row, size_t len);
SPNG_API int spng_encode_chunks(spng_ctx *ctx);
SPNG_API int spng_get_ihdr(spng_ctx *ctx, struct spng_ihdr *ihdr);
SPNG_API int spng_get_plte(spng_ctx *ctx, struct spng_plte *plte);
SPNG_API int spng_get_trns(spng_ctx *ctx, struct spng_trns *trns);
SPNG_API int spng_get_chrm(spng_ctx *ctx, struct spng_chrm *chrm);
SPNG_API int spng_get_chrm_int(spng_ctx *ctx, struct spng_chrm_int *chrm_int);
SPNG_API int spng_get_gama(spng_ctx *ctx, double *gamma);
SPNG_API int spng_get_gama_int(spng_ctx *ctx, uint32_t *gama_int);
SPNG_API int spng_get_iccp(spng_ctx *ctx, struct spng_iccp *iccp);
SPNG_API int spng_get_sbit(spng_ctx *ctx, struct spng_sbit *sbit);
SPNG_API int spng_get_srgb(spng_ctx *ctx, uint8_t *rendering_intent);
SPNG_API int spng_get_text(spng_ctx *ctx, struct spng_text *text, uint32_t *n_text);
SPNG_API int spng_get_bkgd(spng_ctx *ctx, struct spng_bkgd *bkgd);
SPNG_API int spng_get_hist(spng_ctx *ctx, struct spng_hist *hist);
SPNG_API int spng_get_phys(spng_ctx *ctx, struct spng_phys *phys);
SPNG_API int spng_get_splt(spng_ctx *ctx, struct spng_splt *splt, uint32_t *n_splt);
SPNG_API int spng_get_time(spng_ctx *ctx, struct spng_time *time);
SPNG_API int spng_get_unknown_chunks(spng_ctx *ctx, struct spng_unknown_chunk *chunks, uint32_t *n_chunks);
/* Official extensions */
SPNG_API int spng_get_offs(spng_ctx *ctx, struct spng_offs *offs);
SPNG_API int spng_get_exif(spng_ctx *ctx, struct spng_exif *exif);
SPNG_API int spng_set_ihdr(spng_ctx *ctx, struct spng_ihdr *ihdr);
SPNG_API int spng_set_plte(spng_ctx *ctx, struct spng_plte *plte);
SPNG_API int spng_set_trns(spng_ctx *ctx, struct spng_trns *trns);
SPNG_API int spng_set_chrm(spng_ctx *ctx, struct spng_chrm *chrm);
SPNG_API int spng_set_chrm_int(spng_ctx *ctx, struct spng_chrm_int *chrm_int);
SPNG_API int spng_set_gama(spng_ctx *ctx, double gamma);
SPNG_API int spng_set_gama_int(spng_ctx *ctx, uint32_t gamma);
SPNG_API int spng_set_iccp(spng_ctx *ctx, struct spng_iccp *iccp);
SPNG_API int spng_set_sbit(spng_ctx *ctx, struct spng_sbit *sbit);
SPNG_API int spng_set_srgb(spng_ctx *ctx, uint8_t rendering_intent);
SPNG_API int spng_set_text(spng_ctx *ctx, struct spng_text *text, uint32_t n_text);
SPNG_API int spng_set_bkgd(spng_ctx *ctx, struct spng_bkgd *bkgd);
SPNG_API int spng_set_hist(spng_ctx *ctx, struct spng_hist *hist);
SPNG_API int spng_set_phys(spng_ctx *ctx, struct spng_phys *phys);
SPNG_API int spng_set_splt(spng_ctx *ctx, struct spng_splt *splt, uint32_t n_splt);
SPNG_API int spng_set_time(spng_ctx *ctx, struct spng_time *time);
SPNG_API int spng_set_unknown_chunks(spng_ctx *ctx, struct spng_unknown_chunk *chunks, uint32_t n_chunks);
/* Official extensions */
SPNG_API int spng_set_offs(spng_ctx *ctx, struct spng_offs *offs);
SPNG_API int spng_set_exif(spng_ctx *ctx, struct spng_exif *exif);
SPNG_API const char *spng_strerror(int err);
SPNG_API const char *spng_version_string(void);
#ifdef __cplusplus
}
#endif
#endif /* SPNG_H */

View File

@ -1,7 +0,0 @@
add_library(lodepng
lodepng/lodepng.cpp
lodepng/lodepng.h
)
create_target_directory_groups(lodepng)
target_include_directories(lodepng INTERFACE lodepng)

69
externals/minizip/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,69 @@
project(minizip C)
add_library(minizip STATIC
mz.h
mz_compat.c
mz_compat.h
mz_crypt.c
mz_crypt.h
mz_os.c
mz_os.h
mz_strm.c
mz_strm.h
mz_strm_buf.c
mz_strm_buf.h
mz_strm_mem.c
mz_strm_mem.h
mz_strm_os.h
mz_strm_split.c
mz_strm_split.h
mz_strm_zlib.c
mz_strm_zlib.h
mz_zip.c
mz_zip.h
mz_zip_rw.c
mz_zip_rw.h
unzip.h
zip.h
)
if (UNIX)
target_sources(minizip PRIVATE
mz_os_posix.c
mz_strm_os_posix.c
)
endif()
if (WIN32)
target_sources(minizip PRIVATE
mz_os_win32.c
mz_strm_os_win32.c
)
endif()
target_include_directories(minizip PUBLIC .)
target_compile_definitions(minizip PRIVATE HAVE_ZLIB ZLIB_COMPAT MZ_ZIP_NO_CRYPTO MZ_ZIP_NO_ENCRYPTION)
if (UNIX)
target_compile_definitions(minizip PRIVATE _POSIX_C_SOURCE=200112L)
target_compile_definitions(minizip PRIVATE __USE_LARGEFILE64 _LARGEFILE64_SOURCE)
endif()
check_include_file(stdint.h HAVE_STDINT_H)
if (HAVE_STDINT_H)
target_compile_definitions(minizip PRIVATE HAVE_STDINT_H)
endif()
check_include_file(inttypes.h HAVE_INTTYPES_H)
if (HAVE_INTTYPES_H)
target_compile_definitions(minizip PRIVATE HAVE_INTTYPES_H)
endif()
check_function_exists(fseeko HAVE_FSEEKO)
if (NOT HAVE_FSEEKO)
target_compile_definitions(minizip PRIVATE NO_FSEEKO)
endif()
target_link_libraries(minizip PUBLIC ZLIB::ZLIB)
add_library(minizip-ng ALIAS minizip)

1015
externals/minizip/CMakeLists.txt.original vendored Normal file

File diff suppressed because it is too large Load Diff

17
externals/minizip/LICENSE vendored Normal file
View File

@ -0,0 +1,17 @@
Condition of use and distribution are the same as zlib:
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgement in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

3
externals/minizip/README vendored Normal file
View File

@ -0,0 +1,3 @@
minizip-ng, Version 3.0.4 (2021-11-29)
https://github.com/zlib-ng/minizip-ng
Revision: 95987e98b4862c055b8cf91d6e7ce5f9153ddc24

13
externals/minizip/exports.props vendored Normal file
View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<ItemDefinitionGroup>
<ClCompile>
<AdditionalIncludeDirectories>$(ExternalsDir)minizip;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ProjectReference Include="$(ExternalsDir)minizip\minizip.vcxproj">
<Project>{23114507-079a-4418-9707-cfa81a03ca99}</Project>
</ProjectReference>
</ItemGroup>
</Project>

182
externals/minizip/minigzip.c vendored Normal file
View File

@ -0,0 +1,182 @@
/* minigzip.c
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include "mz_strm.h"
#include "mz_strm_os.h"
#include "mz_strm_zlib.h"
#include <stdio.h> /* printf */
/***************************************************************************/
#define MZ_GZIP_COMPRESS (1)
#define MZ_GZIP_DECOMPRESS (2)
int32_t minigzip_banner(void);
int32_t minigzip_help(void);
/***************************************************************************/
int32_t minigzip_banner(void) {
printf("Minigzip %s - https://github.com/zlib-ng/minizip-ng\n", MZ_VERSION);
printf("---------------------------------------------------\n");
return MZ_OK;
}
int32_t minigzip_help(void) {
printf("Usage: minigzip [-x] [-d] [-0 to -9] [files]\n\n" \
" -x Extract file\n" \
" -d Destination directory\n" \
" -0 Store only\n" \
" -1 Compress faster\n" \
" -9 Compress better\n\n");
return MZ_OK;
}
/***************************************************************************/
int32_t minigzip_copy(const char *path, const char *destination, int16_t operation, int16_t level) {
void *target_stream = NULL;
void *source_stream = NULL;
void *zlib_stream = NULL;
const char *filename = NULL;
char target_path[1024];
int32_t err = 0;
memset(target_path, 0, sizeof(target_path));
if (destination != NULL) {
if (mz_os_file_exists(destination) != MZ_OK)
mz_dir_make(destination);
}
if (operation == MZ_GZIP_COMPRESS) {
mz_path_combine(target_path, path, sizeof(target_path));
strncat(target_path, ".gz", sizeof(target_path) - strlen(target_path) - 1);
printf("Compressing to %s\n", target_path);
} else if (operation == MZ_GZIP_DECOMPRESS) {
if (destination != NULL)
mz_path_combine(target_path, destination, sizeof(target_path));
if (mz_path_get_filename(path, &filename) != MZ_OK)
filename = path;
mz_path_combine(target_path, filename, sizeof(target_path));
mz_path_remove_extension(target_path);
printf("Decompressing to %s\n", target_path);
}
mz_stream_zlib_create(&zlib_stream);
mz_stream_zlib_set_prop_int64(zlib_stream, MZ_STREAM_PROP_COMPRESS_WINDOW, 15 + 16);
mz_stream_os_create(&source_stream);
err = mz_stream_os_open(source_stream, path, MZ_OPEN_MODE_READ);
if (err == MZ_OK) {
mz_stream_os_create(&target_stream);
err = mz_stream_os_open(target_stream, target_path, MZ_OPEN_MODE_CREATE | MZ_OPEN_MODE_WRITE);
if (err == MZ_OK) {
if (operation == MZ_GZIP_COMPRESS) {
mz_stream_zlib_set_prop_int64(zlib_stream, MZ_STREAM_PROP_COMPRESS_LEVEL, level);
mz_stream_zlib_open(zlib_stream, target_path, MZ_OPEN_MODE_WRITE);
mz_stream_set_base(zlib_stream, target_stream);
err = mz_stream_copy_to_end(zlib_stream, source_stream);
} else if (operation == MZ_GZIP_DECOMPRESS) {
mz_stream_zlib_open(zlib_stream, path, MZ_OPEN_MODE_READ);
mz_stream_set_base(zlib_stream, source_stream);
err = mz_stream_copy_to_end(target_stream, zlib_stream);
}
if (err != MZ_OK)
printf("Error %d in zlib stream (%d)\n", err, mz_stream_zlib_error(zlib_stream));
else
printf("Operation completed successfully\n");
mz_stream_zlib_close(zlib_stream);
} else {
printf("Error %d opening target path %s\n", err, target_path);
}
mz_stream_os_close(target_stream);
mz_stream_os_delete(&target_stream);
} else {
printf("Error %d opening source path %s\n", err, path);
}
mz_stream_os_close(source_stream);
mz_stream_os_delete(&source_stream);
mz_stream_zlib_delete(&zlib_stream);
return err;
}
/***************************************************************************/
#if !defined(MZ_ZIP_NO_MAIN)
int main(int argc, const char *argv[]) {
int16_t operation_level = MZ_COMPRESS_LEVEL_DEFAULT;
int32_t path_arg = 0;
int32_t err = 0;
int32_t i = 0;
uint8_t operation = MZ_GZIP_COMPRESS;
const char *path = NULL;
const char *destination = NULL;
minigzip_banner();
if (argc == 1) {
minigzip_help();
return 0;
}
/* Parse command line options */
for (i = 1; i < argc; i += 1) {
printf("%s ", argv[i]);
if (argv[i][0] == '-') {
char c = argv[i][1];
if ((c == 'x') || (c == 'X'))
operation = MZ_GZIP_DECOMPRESS;
else if ((c >= '0') && (c <= '9'))
operation_level = (c - '0');
else if (((c == 'd') || (c == 'D')) && (i + 1 < argc)) {
destination = argv[i + 1];
printf("%s ", argv[i + 1]);
i += 1;
} else {
err = MZ_SUPPORT_ERROR;
}
} else if (path_arg == 0) {
path_arg = i;
break;
}
}
printf("\n");
if (err == MZ_SUPPORT_ERROR) {
printf("Feature not supported\n");
return err;
}
if (path_arg == 0) {
minigzip_help();
return 0;
}
path = argv[path_arg];
err = minigzip_copy(path, destination, operation, operation_level);
return err;
}
#endif

671
externals/minizip/minizip.c vendored Normal file
View File

@ -0,0 +1,671 @@
/* minizip.c
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 1998-2010 Gilles Vollant
https://www.winimage.com/zLibDll/minizip.html
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include "mz_strm.h"
#include "mz_strm_buf.h"
#include "mz_strm_split.h"
#include "mz_zip.h"
#include "mz_zip_rw.h"
#include <stdio.h> /* printf */
/***************************************************************************/
typedef struct minizip_opt_s {
uint8_t include_path;
int16_t compress_level;
uint8_t compress_method;
uint8_t overwrite;
uint8_t append;
int64_t disk_size;
uint8_t follow_links;
uint8_t store_links;
uint8_t zip_cd;
int32_t encoding;
uint8_t verbose;
uint8_t aes;
const char *cert_path;
const char *cert_pwd;
} minizip_opt;
/***************************************************************************/
int32_t minizip_banner(void);
int32_t minizip_help(void);
int32_t minizip_list(const char *path);
int32_t minizip_add_entry_cb(void *handle, void *userdata, mz_zip_file *file_info);
int32_t minizip_add_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position);
int32_t minizip_add_overwrite_cb(void *handle, void *userdata, const char *path);
int32_t minizip_add(const char *path, const char *password, minizip_opt *options, int32_t arg_count, const char **args);
int32_t minizip_extract_entry_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path);
int32_t minizip_extract_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position);
int32_t minizip_extract_overwrite_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path);
int32_t minizip_extract(const char *path, const char *pattern, const char *destination, const char *password, minizip_opt *options);
int32_t minizip_erase(const char *src_path, const char *target_path, int32_t arg_count, const char **args);
/***************************************************************************/
int32_t minizip_banner(void) {
printf("minizip-ng %s - https://github.com/zlib-ng/minizip-ng\n", MZ_VERSION);
printf("---------------------------------------------------\n");
return MZ_OK;
}
int32_t minizip_help(void) {
printf("Usage: minizip [-x][-d dir|-l|-e][-o][-f][-y][-c cp][-a][-0 to -9][-b|-m|-t][-k 512][-p pwd][-s] file.zip [files]\n\n" \
" -x Extract files\n" \
" -l List files\n" \
" -d Destination directory\n" \
" -e Erase files\n" \
" -o Overwrite existing files\n" \
" -c File names use cp437 encoding (or specified codepage)\n" \
" -a Append to existing zip file\n" \
" -i Include full path of files\n" \
" -f Follow symbolic links\n" \
" -y Store symbolic links\n" \
" -v Verbose info\n" \
" -0 Store only\n" \
" -1 Compress faster\n" \
" -9 Compress better\n" \
" -k Disk size in KB\n" \
" -z Zip central directory\n" \
" -p Encryption password\n" \
" -s AES encryption\n" \
" -h PKCS12 certificate path\n" \
" -w PKCS12 certificate password\n" \
" -b BZIP2 compression\n" \
" -m LZMA compression\n" \
" -n XZ compression\n" \
" -t ZSTD compression\n\n");
return MZ_OK;
}
/***************************************************************************/
int32_t minizip_list(const char *path) {
mz_zip_file *file_info = NULL;
uint32_t ratio = 0;
int32_t err = MZ_OK;
struct tm tmu_date;
const char *method = NULL;
char crypt = ' ';
void *reader = NULL;
mz_zip_reader_create(&reader);
err = mz_zip_reader_open_file(reader, path);
if (err != MZ_OK) {
printf("Error %" PRId32 " opening archive %s\n", err, path);
mz_zip_reader_delete(&reader);
return err;
}
err = mz_zip_reader_goto_first_entry(reader);
if (err != MZ_OK && err != MZ_END_OF_LIST) {
printf("Error %" PRId32 " going to first entry in archive\n", err);
mz_zip_reader_delete(&reader);
return err;
}
printf(" Packed Unpacked Ratio Method Attribs Date Time CRC-32 Name\n");
printf(" ------ -------- ----- ------ ------- ---- ---- ------ ----\n");
/* Enumerate all entries in the archive */
do {
err = mz_zip_reader_entry_get_info(reader, &file_info);
if (err != MZ_OK) {
printf("Error %" PRId32 " getting entry info in archive\n", err);
break;
}
ratio = 0;
if (file_info->uncompressed_size > 0)
ratio = (uint32_t)((file_info->compressed_size * 100) / file_info->uncompressed_size);
/* Display a '*' if the file is encrypted */
if (file_info->flag & MZ_ZIP_FLAG_ENCRYPTED)
crypt = '*';
else
crypt = ' ';
method = mz_zip_get_compression_method_string(file_info->compression_method);
mz_zip_time_t_to_tm(file_info->modified_date, &tmu_date);
/* Print entry information */
printf("%12" PRId64 " %12" PRId64 " %3" PRIu32 "%% %6s%c %8" PRIx32 " %2.2" PRIu32 \
"-%2.2" PRIu32 "-%2.2" PRIu32 " %2.2" PRIu32 ":%2.2" PRIu32 " %8.8" PRIx32 " %s\n",
file_info->compressed_size, file_info->uncompressed_size, ratio,
method, crypt, file_info->external_fa,
(uint32_t)tmu_date.tm_mon + 1, (uint32_t)tmu_date.tm_mday,
(uint32_t)tmu_date.tm_year % 100,
(uint32_t)tmu_date.tm_hour, (uint32_t)tmu_date.tm_min,
file_info->crc, file_info->filename);
err = mz_zip_reader_goto_next_entry(reader);
if (err != MZ_OK && err != MZ_END_OF_LIST) {
printf("Error %" PRId32 " going to next entry in archive\n", err);
break;
}
} while (err == MZ_OK);
mz_zip_reader_delete(&reader);
if (err == MZ_END_OF_LIST)
return MZ_OK;
return err;
}
/***************************************************************************/
int32_t minizip_add_entry_cb(void *handle, void *userdata, mz_zip_file *file_info) {
MZ_UNUSED(handle);
MZ_UNUSED(userdata);
/* Print the current file we are trying to compress */
printf("Adding %s\n", file_info->filename);
return MZ_OK;
}
int32_t minizip_add_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position) {
minizip_opt *options = (minizip_opt *)userdata;
double progress = 0;
uint8_t raw = 0;
MZ_UNUSED(userdata);
mz_zip_writer_get_raw(handle, &raw);
if (raw && file_info->compressed_size > 0)
progress = ((double)position / file_info->compressed_size) * 100;
else if (!raw && file_info->uncompressed_size > 0)
progress = ((double)position / file_info->uncompressed_size) * 100;
/* Print the progress of the current compress operation */
if (options->verbose)
printf("%s - %" PRId64 " / %" PRId64 " (%.02f%%)\n", file_info->filename, position,
file_info->uncompressed_size, progress);
return MZ_OK;
}
int32_t minizip_add_overwrite_cb(void *handle, void *userdata, const char *path) {
minizip_opt *options = (minizip_opt *)userdata;
MZ_UNUSED(handle);
if (options->overwrite == 0) {
/* If ask the user what to do because append and overwrite args not set */
char rep = 0;
do {
char answer[128];
printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ", path);
if (scanf("%1s", answer) != 1)
exit(EXIT_FAILURE);
rep = answer[0];
if ((rep >= 'a') && (rep <= 'z'))
rep -= 0x20;
} while ((rep != 'Y') && (rep != 'N') && (rep != 'A'));
if (rep == 'A') {
return MZ_EXIST_ERROR;
} else if (rep == 'N') {
return MZ_INTERNAL_ERROR;
}
}
return MZ_OK;
}
int32_t minizip_add(const char *path, const char *password, minizip_opt *options, int32_t arg_count, const char **args) {
void *writer = NULL;
int32_t err = MZ_OK;
int32_t err_close = MZ_OK;
int32_t i = 0;
const char *filename_in_zip = NULL;
printf("Archive %s\n", path);
/* Create zip writer */
mz_zip_writer_create(&writer);
mz_zip_writer_set_password(writer, password);
mz_zip_writer_set_aes(writer, options->aes);
mz_zip_writer_set_compress_method(writer, options->compress_method);
mz_zip_writer_set_compress_level(writer, options->compress_level);
mz_zip_writer_set_follow_links(writer, options->follow_links);
mz_zip_writer_set_store_links(writer, options->store_links);
mz_zip_writer_set_overwrite_cb(writer, options, minizip_add_overwrite_cb);
mz_zip_writer_set_progress_cb(writer, options, minizip_add_progress_cb);
mz_zip_writer_set_entry_cb(writer, options, minizip_add_entry_cb);
mz_zip_writer_set_zip_cd(writer, options->zip_cd);
if (options->cert_path != NULL)
mz_zip_writer_set_certificate(writer, options->cert_path, options->cert_pwd);
err = mz_zip_writer_open_file(writer, path, options->disk_size, options->append);
if (err == MZ_OK) {
for (i = 0; i < arg_count; i += 1) {
filename_in_zip = args[i];
/* Add file system path to archive */
err = mz_zip_writer_add_path(writer, filename_in_zip, NULL, options->include_path, 1);
if (err != MZ_OK)
printf("Error %" PRId32 " adding path to archive %s\n", err, filename_in_zip);
}
} else {
printf("Error %" PRId32 " opening archive for writing\n", err);
}
err_close = mz_zip_writer_close(writer);
if (err_close != MZ_OK) {
printf("Error %" PRId32 " closing archive for writing %s\n", err_close, path);
err = err_close;
}
mz_zip_writer_delete(&writer);
return err;
}
/***************************************************************************/
int32_t minizip_extract_entry_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path) {
MZ_UNUSED(handle);
MZ_UNUSED(userdata);
MZ_UNUSED(path);
/* Print the current entry extracting */
printf("Extracting %s\n", file_info->filename);
return MZ_OK;
}
int32_t minizip_extract_progress_cb(void *handle, void *userdata, mz_zip_file *file_info, int64_t position) {
minizip_opt *options = (minizip_opt *)userdata;
double progress = 0;
uint8_t raw = 0;
MZ_UNUSED(userdata);
mz_zip_reader_get_raw(handle, &raw);
if (raw && file_info->compressed_size > 0)
progress = ((double)position / file_info->compressed_size) * 100;
else if (!raw && file_info->uncompressed_size > 0)
progress = ((double)position / file_info->uncompressed_size) * 100;
/* Print the progress of the current extraction */
if (options->verbose)
printf("%s - %" PRId64 " / %" PRId64 " (%.02f%%)\n", file_info->filename, position,
file_info->uncompressed_size, progress);
return MZ_OK;
}
int32_t minizip_extract_overwrite_cb(void *handle, void *userdata, mz_zip_file *file_info, const char *path) {
minizip_opt *options = (minizip_opt *)userdata;
MZ_UNUSED(handle);
MZ_UNUSED(file_info);
/* Verify if we want to overwrite current entry on disk */
if (options->overwrite == 0) {
char rep = 0;
do {
char answer[128];
printf("The file %s exists. Overwrite ? [y]es, [n]o, [A]ll: ", path);
if (scanf("%1s", answer) != 1)
exit(EXIT_FAILURE);
rep = answer[0];
if ((rep >= 'a') && (rep <= 'z'))
rep -= 0x20;
} while ((rep != 'Y') && (rep != 'N') && (rep != 'A'));
if (rep == 'N')
return MZ_EXIST_ERROR;
if (rep == 'A')
options->overwrite = 1;
}
return MZ_OK;
}
int32_t minizip_extract(const char *path, const char *pattern, const char *destination, const char *password, minizip_opt *options) {
void *reader = NULL;
int32_t err = MZ_OK;
int32_t err_close = MZ_OK;
printf("Archive %s\n", path);
/* Create zip reader */
mz_zip_reader_create(&reader);
mz_zip_reader_set_pattern(reader, pattern, 1);
mz_zip_reader_set_password(reader, password);
mz_zip_reader_set_encoding(reader, options->encoding);
mz_zip_reader_set_entry_cb(reader, options, minizip_extract_entry_cb);
mz_zip_reader_set_progress_cb(reader, options, minizip_extract_progress_cb);
mz_zip_reader_set_overwrite_cb(reader, options, minizip_extract_overwrite_cb);
err = mz_zip_reader_open_file(reader, path);
if (err != MZ_OK) {
printf("Error %" PRId32 " opening archive %s\n", err, path);
} else {
/* Save all entries in archive to destination directory */
err = mz_zip_reader_save_all(reader, destination);
if (err == MZ_END_OF_LIST) {
if (pattern != NULL) {
printf("Files matching %s not found in archive\n", pattern);
} else {
printf("No files in archive\n");
err = MZ_OK;
}
} else if (err != MZ_OK) {
printf("Error %" PRId32 " saving entries to disk %s\n", err, path);
}
}
err_close = mz_zip_reader_close(reader);
if (err_close != MZ_OK) {
printf("Error %" PRId32 " closing archive for reading\n", err_close);
err = err_close;
}
mz_zip_reader_delete(&reader);
return err;
}
/***************************************************************************/
int32_t minizip_erase(const char *src_path, const char *target_path, int32_t arg_count, const char **args) {
mz_zip_file *file_info = NULL;
const char *filename_in_zip = NULL;
const char *target_path_ptr = target_path;
void *reader = NULL;
void *writer = NULL;
int32_t skip = 0;
int32_t err = MZ_OK;
int32_t i = 0;
uint8_t zip_cd = 0;
char bak_path[256];
char tmp_path[256];
if (target_path == NULL) {
/* Construct temporary zip name */
strncpy(tmp_path, src_path, sizeof(tmp_path) - 1);
tmp_path[sizeof(tmp_path) - 1] = 0;
strncat(tmp_path, ".tmp.zip", sizeof(tmp_path) - strlen(tmp_path) - 1);
target_path_ptr = tmp_path;
}
mz_zip_reader_create(&reader);
mz_zip_writer_create(&writer);
/* Open original archive we want to erase an entry in */
err = mz_zip_reader_open_file(reader, src_path);
if (err != MZ_OK) {
printf("Error %" PRId32 " opening archive for reading %s\n", err, src_path);
mz_zip_reader_delete(&reader);
return err;
}
/* Open temporary archive */
err = mz_zip_writer_open_file(writer, target_path_ptr, 0, 0);
if (err != MZ_OK) {
printf("Error %" PRId32 " opening archive for writing %s\n", err, target_path_ptr);
mz_zip_reader_delete(&reader);
mz_zip_writer_delete(&writer);
return err;
}
err = mz_zip_reader_goto_first_entry(reader);
if (err != MZ_OK && err != MZ_END_OF_LIST)
printf("Error %" PRId32 " going to first entry in archive\n", err);
while (err == MZ_OK) {
err = mz_zip_reader_entry_get_info(reader, &file_info);
if (err != MZ_OK) {
printf("Error %" PRId32 " getting info from archive\n", err);
break;
}
/* Copy all entries from original archive to temporary archive
except the ones we don't want */
for (i = 0, skip = 0; i < arg_count; i += 1) {
filename_in_zip = args[i];
if (mz_path_compare_wc(file_info->filename, filename_in_zip, 1) == MZ_OK)
skip = 1;
}
if (skip) {
printf("Skipping %s\n", file_info->filename);
} else {
printf("Copying %s\n", file_info->filename);
err = mz_zip_writer_copy_from_reader(writer, reader);
}
if (err != MZ_OK) {
printf("Error %" PRId32 " copying entry into new zip\n", err);
break;
}
err = mz_zip_reader_goto_next_entry(reader);
if (err != MZ_OK && err != MZ_END_OF_LIST)
printf("Error %" PRId32 " going to next entry in archive\n", err);
}
mz_zip_reader_get_zip_cd(reader, &zip_cd);
mz_zip_writer_set_zip_cd(writer, zip_cd);
mz_zip_reader_close(reader);
mz_zip_reader_delete(&reader);
mz_zip_writer_close(writer);
mz_zip_writer_delete(&writer);
if (err == MZ_END_OF_LIST) {
if (target_path == NULL) {
/* Swap original archive with temporary archive, backup old archive if possible */
strncpy(bak_path, src_path, sizeof(bak_path) - 1);
bak_path[sizeof(bak_path) - 1] = 0;
strncat(bak_path, ".bak", sizeof(bak_path) - strlen(bak_path) - 1);
if (mz_os_file_exists(bak_path) == MZ_OK)
mz_os_unlink(bak_path);
if (mz_os_rename(src_path, bak_path) != MZ_OK)
printf("Error backing up archive before replacing %s\n", bak_path);
if (mz_os_rename(tmp_path, src_path) != MZ_OK)
printf("Error replacing archive with temp %s\n", tmp_path);
}
return MZ_OK;
}
return err;
}
/***************************************************************************/
#if !defined(MZ_ZIP_NO_MAIN)
int main(int argc, const char *argv[]) {
minizip_opt options;
int32_t path_arg = 0;
int32_t err = 0;
int32_t i = 0;
uint8_t do_list = 0;
uint8_t do_extract = 0;
uint8_t do_erase = 0;
const char *path = NULL;
const char *password = NULL;
const char *destination = NULL;
const char *filename_to_extract = NULL;
minizip_banner();
if (argc == 1) {
minizip_help();
return 0;
}
memset(&options, 0, sizeof(options));
options.compress_method = MZ_COMPRESS_METHOD_DEFLATE;
options.compress_level = MZ_COMPRESS_LEVEL_DEFAULT;
/* Parse command line options */
for (i = 1; i < argc; i += 1) {
printf("%s ", argv[i]);
if (argv[i][0] == '-') {
char c = argv[i][1];
if ((c == 'l') || (c == 'L'))
do_list = 1;
else if ((c == 'x') || (c == 'X'))
do_extract = 1;
else if ((c == 'e') || (c == 'E'))
do_erase = 1;
else if ((c == 'a') || (c == 'A'))
options.append = 1;
else if ((c == 'o') || (c == 'O'))
options.overwrite = 1;
else if ((c == 'f') || (c == 'F'))
options.follow_links = 1;
else if ((c == 'y') || (c == 'Y'))
options.store_links = 1;
else if ((c == 'i') || (c == 'I'))
options.include_path = 1;
else if ((c == 'z') || (c == 'Z'))
options.zip_cd = 1;
else if ((c == 'v') || (c == 'V'))
options.verbose = 1;
else if ((c >= '0') && (c <= '9')) {
options.compress_level = (c - '0');
if (options.compress_level == 0)
options.compress_method = MZ_COMPRESS_METHOD_STORE;
} else if ((c == 'b') || (c == 'B'))
#ifdef HAVE_BZIP2
options.compress_method = MZ_COMPRESS_METHOD_BZIP2;
#else
err = MZ_SUPPORT_ERROR;
#endif
else if ((c == 'm') || (c == 'M'))
#ifdef HAVE_LZMA
options.compress_method = MZ_COMPRESS_METHOD_LZMA;
#else
err = MZ_SUPPORT_ERROR;
#endif
else if ((c == 'n') || (c == 'N'))
#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP)
options.compress_method = MZ_COMPRESS_METHOD_XZ;
#else
err = MZ_SUPPORT_ERROR;
#endif
else if ((c == 't') || (c == 'T'))
#ifdef HAVE_ZSTD
options.compress_method = MZ_COMPRESS_METHOD_ZSTD;
#else
err = MZ_SUPPORT_ERROR;
#endif
else if ((c == 's') || (c == 'S'))
#ifdef HAVE_WZAES
options.aes = 1;
#else
err = MZ_SUPPORT_ERROR;
#endif
else if (((c == 'h') || (c == 'H')) && (i + 1 < argc)) {
#ifdef MZ_ZIP_SIGNING
options.cert_path = argv[i + 1];
printf("%s ", argv[i + 1]);
#else
err = MZ_SUPPORT_ERROR;
#endif
i += 1;
} else if (((c == 'w') || (c == 'W')) && (i + 1 < argc)) {
#ifdef MZ_ZIP_SIGNING
options.cert_pwd = argv[i + 1];
printf("%s ", argv[i + 1]);
#else
err = MZ_SUPPORT_ERROR;
#endif
i += 1;
} else if (((c == 'c') || (c == 'C')) && (i + 1 < argc)) {
options.encoding = (int32_t)atoi(argv[i + 1]);
i += 1;
} else if (((c == 'k') || (c == 'K')) && (i + 1 < argc)) {
options.disk_size = (int64_t)atoi(argv[i + 1]) * 1024;
printf("%s ", argv[i + 1]);
i += 1;
} else if (((c == 'd') || (c == 'D')) && (i + 1 < argc)) {
destination = argv[i + 1];
printf("%s ", argv[i + 1]);
i += 1;
} else if (((c == 'p') || (c == 'P')) && (i + 1 < argc)) {
#ifndef MZ_ZIP_NO_ENCRYPTION
password = argv[i + 1];
printf("*** ");
#else
err = MZ_SUPPORT_ERROR;
#endif
i += 1;
}
} else if (path_arg == 0)
path_arg = i;
}
printf("\n");
if (err == MZ_SUPPORT_ERROR) {
printf("Feature not supported\n");
return err;
}
if (path_arg == 0) {
minizip_help();
return 0;
}
path = argv[path_arg];
if (do_list) {
/* List archive contents */
err = minizip_list(path);
} else if (do_extract) {
if (argc > path_arg + 1)
filename_to_extract = argv[path_arg + 1];
/* Extract archive */
err = minizip_extract(path, filename_to_extract, destination, password, &options);
} else if (do_erase) {
/* Erase file in archive */
err = minizip_erase(path, NULL, argc - (path_arg + 1), &argv[path_arg + 1]);
} else {
/* Add files to archive */
err = minizip_add(path, password, &options, argc - (path_arg + 1), &argv[path_arg + 1]);
}
return err;
}
#endif

14
externals/minizip/minizip.pc.cmakein vendored Normal file
View File

@ -0,0 +1,14 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=@CMAKE_INSTALL_PREFIX@
libdir=@CMAKE_INSTALL_FULL_LIBDIR@
sharedlibdir=@CMAKE_INSTALL_FULL_LIBDIR@
includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
Name: @PROJECT_NAME@
Description: Minizip zip file manipulation library
Version: @VERSION@
Requires: zlib
Libs: -L${libdir} -L${sharedlibdir} -l@PROJECT_NAME@
Libs.private:@PC_PRIVATE_LIBS@
Cflags: -I${includedir}

64
externals/minizip/minizip.vcxproj vendored Normal file
View File

@ -0,0 +1,64 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<Import Project="..\..\Source\VSProps\Base.Macros.props" />
<Import Project="$(VSPropsDir)Base.Targets.props" />
<PropertyGroup Label="Globals">
<ProjectGuid>{23114507-079A-4418-9707-CFA81A03CA99}</ProjectGuid>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<Import Project="$(VSPropsDir)Configuration.StaticLibrary.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings" />
<ImportGroup Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="$(VSPropsDir)Base.props" />
<Import Project="$(VSPropsDir)ClDisableAllWarnings.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<PreprocessorDefinitions>HAVE_ZLIB;ZLIB_COMPAT;MZ_ZIP_NO_CRYPTO;MZ_ZIP_NO_ENCRYPTION;HAVE_STDINT_H;HAVE_INTTYPES_H;NO_FSEEKO;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="mz_compat.c" />
<ClCompile Include="mz_crypt.c" />
<ClCompile Include="mz_os.c" />
<ClCompile Include="mz_os_win32.c" />
<ClCompile Include="mz_strm.c" />
<ClCompile Include="mz_strm_buf.c" />
<ClCompile Include="mz_strm_mem.c" />
<ClCompile Include="mz_strm_os_win32.c" />
<ClCompile Include="mz_strm_split.c" />
<ClCompile Include="mz_strm_zlib.c" />
<ClCompile Include="mz_zip.c" />
<ClCompile Include="mz_zip_rw.c" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="mz.h" />
<ClInclude Include="mz_compat.h" />
<ClInclude Include="mz_crypt.h" />
<ClInclude Include="mz_os.h" />
<ClInclude Include="mz_strm.h" />
<ClInclude Include="mz_strm_buf.h" />
<ClInclude Include="mz_strm_mem.h" />
<ClInclude Include="mz_strm_os.h" />
<ClInclude Include="mz_strm_split.h" />
<ClInclude Include="mz_strm_zlib.h" />
<ClInclude Include="mz_zip.h" />
<ClInclude Include="mz_zip_rw.h" />
<ClInclude Include="unzip.h" />
<ClInclude Include="zip.h" />
</ItemGroup>
<ItemGroup>
<None Include="LICENSE" />
<None Include="README" />
</ItemGroup>
<Import Project="$(ExternalsDir)zlib-ng\exports.props" />
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

274
externals/minizip/mz.h vendored Normal file
View File

@ -0,0 +1,274 @@
/* mz.h -- Errors codes, zip flags and magic
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_H
#define MZ_H
/***************************************************************************/
/* MZ_VERSION */
#define MZ_VERSION ("3.0.4")
#define MZ_VERSION_BUILD (030004)
/* MZ_ERROR */
#define MZ_OK (0) /* zlib */
#define MZ_STREAM_ERROR (-1) /* zlib */
#define MZ_DATA_ERROR (-3) /* zlib */
#define MZ_MEM_ERROR (-4) /* zlib */
#define MZ_BUF_ERROR (-5) /* zlib */
#define MZ_VERSION_ERROR (-6) /* zlib */
#define MZ_END_OF_LIST (-100)
#define MZ_END_OF_STREAM (-101)
#define MZ_PARAM_ERROR (-102)
#define MZ_FORMAT_ERROR (-103)
#define MZ_INTERNAL_ERROR (-104)
#define MZ_CRC_ERROR (-105)
#define MZ_CRYPT_ERROR (-106)
#define MZ_EXIST_ERROR (-107)
#define MZ_PASSWORD_ERROR (-108)
#define MZ_SUPPORT_ERROR (-109)
#define MZ_HASH_ERROR (-110)
#define MZ_OPEN_ERROR (-111)
#define MZ_CLOSE_ERROR (-112)
#define MZ_SEEK_ERROR (-113)
#define MZ_TELL_ERROR (-114)
#define MZ_READ_ERROR (-115)
#define MZ_WRITE_ERROR (-116)
#define MZ_SIGN_ERROR (-117)
#define MZ_SYMLINK_ERROR (-118)
/* MZ_OPEN */
#define MZ_OPEN_MODE_READ (0x01)
#define MZ_OPEN_MODE_WRITE (0x02)
#define MZ_OPEN_MODE_READWRITE (MZ_OPEN_MODE_READ | MZ_OPEN_MODE_WRITE)
#define MZ_OPEN_MODE_APPEND (0x04)
#define MZ_OPEN_MODE_CREATE (0x08)
#define MZ_OPEN_MODE_EXISTING (0x10)
/* MZ_SEEK */
#define MZ_SEEK_SET (0)
#define MZ_SEEK_CUR (1)
#define MZ_SEEK_END (2)
/* MZ_COMPRESS */
#define MZ_COMPRESS_METHOD_STORE (0)
#define MZ_COMPRESS_METHOD_DEFLATE (8)
#define MZ_COMPRESS_METHOD_BZIP2 (12)
#define MZ_COMPRESS_METHOD_LZMA (14)
#define MZ_COMPRESS_METHOD_ZSTD (93)
#define MZ_COMPRESS_METHOD_XZ (95)
#define MZ_COMPRESS_METHOD_AES (99)
#define MZ_COMPRESS_LEVEL_DEFAULT (-1)
#define MZ_COMPRESS_LEVEL_FAST (2)
#define MZ_COMPRESS_LEVEL_NORMAL (6)
#define MZ_COMPRESS_LEVEL_BEST (9)
/* MZ_ZIP_FLAG */
#define MZ_ZIP_FLAG_ENCRYPTED (1 << 0)
#define MZ_ZIP_FLAG_LZMA_EOS_MARKER (1 << 1)
#define MZ_ZIP_FLAG_DEFLATE_MAX (1 << 1)
#define MZ_ZIP_FLAG_DEFLATE_NORMAL (0)
#define MZ_ZIP_FLAG_DEFLATE_FAST (1 << 2)
#define MZ_ZIP_FLAG_DEFLATE_SUPER_FAST (MZ_ZIP_FLAG_DEFLATE_FAST | \
MZ_ZIP_FLAG_DEFLATE_MAX)
#define MZ_ZIP_FLAG_DATA_DESCRIPTOR (1 << 3)
#define MZ_ZIP_FLAG_UTF8 (1 << 11)
#define MZ_ZIP_FLAG_MASK_LOCAL_INFO (1 << 13)
/* MZ_ZIP_EXTENSION */
#define MZ_ZIP_EXTENSION_ZIP64 (0x0001)
#define MZ_ZIP_EXTENSION_NTFS (0x000a)
#define MZ_ZIP_EXTENSION_AES (0x9901)
#define MZ_ZIP_EXTENSION_UNIX1 (0x000d)
#define MZ_ZIP_EXTENSION_SIGN (0x10c5)
#define MZ_ZIP_EXTENSION_HASH (0x1a51)
#define MZ_ZIP_EXTENSION_CDCD (0xcdcd)
/* MZ_ZIP64 */
#define MZ_ZIP64_AUTO (0)
#define MZ_ZIP64_FORCE (1)
#define MZ_ZIP64_DISABLE (2)
/* MZ_HOST_SYSTEM */
#define MZ_HOST_SYSTEM(VERSION_MADEBY) ((uint8_t)(VERSION_MADEBY >> 8))
#define MZ_HOST_SYSTEM_MSDOS (0)
#define MZ_HOST_SYSTEM_UNIX (3)
#define MZ_HOST_SYSTEM_WINDOWS_NTFS (10)
#define MZ_HOST_SYSTEM_RISCOS (13)
#define MZ_HOST_SYSTEM_OSX_DARWIN (19)
/* MZ_PKCRYPT */
#define MZ_PKCRYPT_HEADER_SIZE (12)
/* MZ_AES */
#define MZ_AES_VERSION (1)
#define MZ_AES_ENCRYPTION_MODE_128 (0x01)
#define MZ_AES_ENCRYPTION_MODE_192 (0x02)
#define MZ_AES_ENCRYPTION_MODE_256 (0x03)
#define MZ_AES_KEY_LENGTH(MODE) (8 * (MODE & 3) + 8)
#define MZ_AES_KEY_LENGTH_MAX (32)
#define MZ_AES_BLOCK_SIZE (16)
#define MZ_AES_HEADER_SIZE(MODE) ((4 * (MODE & 3) + 4) + 2)
#define MZ_AES_FOOTER_SIZE (10)
/* MZ_HASH */
#define MZ_HASH_MD5 (10)
#define MZ_HASH_MD5_SIZE (16)
#define MZ_HASH_SHA1 (20)
#define MZ_HASH_SHA1_SIZE (20)
#define MZ_HASH_SHA256 (23)
#define MZ_HASH_SHA256_SIZE (32)
#define MZ_HASH_MAX_SIZE (256)
/* MZ_ENCODING */
#define MZ_ENCODING_CODEPAGE_437 (437)
#define MZ_ENCODING_CODEPAGE_932 (932)
#define MZ_ENCODING_CODEPAGE_936 (936)
#define MZ_ENCODING_CODEPAGE_950 (950)
#define MZ_ENCODING_UTF8 (65001)
/* MZ_UTILITY */
#define MZ_UNUSED(SYMBOL) ((void)SYMBOL)
#ifndef MZ_CUSTOM_ALLOC
#define MZ_ALLOC(SIZE) (malloc((SIZE)))
#endif
#ifndef MZ_CUSTOM_FREE
#define MZ_FREE(PTR) (free(PTR))
#endif
#if defined(_WIN32) && defined(MZ_EXPORTS)
#define MZ_EXPORT __declspec(dllexport)
#else
#define MZ_EXPORT
#endif
/***************************************************************************/
#include <stdlib.h> /* size_t, NULL, malloc */
#include <time.h> /* time_t, time() */
#include <string.h> /* memset, strncpy, strlen */
#include <limits.h>
#if defined(HAVE_STDINT_H)
# include <stdint.h>
#elif defined(__has_include)
# if __has_include(<stdint.h>)
# include <stdint.h>
# endif
#endif
#ifndef INT8_MAX
typedef signed char int8_t;
#endif
#ifndef INT16_MAX
typedef short int16_t;
#endif
#ifndef INT32_MAX
typedef int int32_t;
#endif
#ifndef INT64_MAX
typedef long long int64_t;
#endif
#ifndef UINT8_MAX
typedef unsigned char uint8_t;
#endif
#ifndef UINT16_MAX
typedef unsigned short uint16_t;
#endif
#ifndef UINT32_MAX
typedef unsigned int uint32_t;
#endif
#ifndef UINT64_MAX
typedef unsigned long long uint64_t;
#endif
#if defined(HAVE_INTTYPES_H)
# include <inttypes.h>
#elif defined(__has_include)
# if __has_include(<inttypes.h>)
# include <inttypes.h>
# endif
#endif
#ifndef PRId8
# define PRId8 "hhd"
#endif
#ifndef PRIu8
# define PRIu8 "hhu"
#endif
#ifndef PRIx8
# define PRIx8 "hhx"
#endif
#ifndef PRId16
# define PRId16 "hd"
#endif
#ifndef PRIu16
# define PRIu16 "hu"
#endif
#ifndef PRIx16
# define PRIx16 "hx"
#endif
#ifndef PRId32
# define PRId32 "d"
#endif
#ifndef PRIu32
# define PRIu32 "u"
#endif
#ifndef PRIx32
# define PRIx32 "x"
#endif
#if ULONG_MAX == 0xfffffffful
# ifndef PRId64
# define PRId64 "ld"
# endif
# ifndef PRIu64
# define PRIu64 "lu"
# endif
# ifndef PRIx64
# define PRIx64 "lx"
# endif
#else
# ifndef PRId64
# define PRId64 "lld"
# endif
# ifndef PRIu64
# define PRIu64 "llu"
# endif
# ifndef PRIx64
# define PRIx64 "llx"
# endif
#endif
#ifndef INT16_MAX
# define INT16_MAX 32767
#endif
#ifndef INT32_MAX
# define INT32_MAX 2147483647L
#endif
#ifndef INT64_MAX
# define INT64_MAX 9223372036854775807LL
#endif
#ifndef UINT16_MAX
# define UINT16_MAX 65535U
#endif
#ifndef UINT32_MAX
# define UINT32_MAX 4294967295UL
#endif
#ifndef UINT64_MAX
# define UINT64_MAX 18446744073709551615ULL
#endif
/***************************************************************************/
#endif

1303
externals/minizip/mz_compat.c vendored Normal file

File diff suppressed because it is too large Load Diff

396
externals/minizip/mz_compat.h vendored Normal file
View File

@ -0,0 +1,396 @@
/* mz_compat.h -- Backwards compatible interface for older versions
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 1998-2010 Gilles Vollant
https://www.winimage.com/zLibDll/minizip.html
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_COMPAT_H
#define MZ_COMPAT_H
#include "mz.h"
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
#if defined(HAVE_ZLIB) && defined(MAX_MEM_LEVEL)
#ifndef DEF_MEM_LEVEL
# if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
# else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
# endif
#endif
#endif
#ifndef MAX_WBITS
#define MAX_WBITS (15)
#endif
#ifndef DEF_MEM_LEVEL
#define DEF_MEM_LEVEL (8)
#endif
#ifndef ZEXPORT
# define ZEXPORT MZ_EXPORT
#endif
/***************************************************************************/
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagzipFile__ { int unused; } zip_file__;
typedef zip_file__ *zipFile;
#else
typedef void *zipFile;
#endif
/***************************************************************************/
typedef uint64_t ZPOS64_T;
#ifndef ZCALLBACK
#define ZCALLBACK
#endif
typedef void* (ZCALLBACK *open_file_func) (void *opaque, const char *filename, int mode);
typedef void* (ZCALLBACK *open64_file_func) (void *opaque, const void *filename, int mode);
typedef unsigned long (ZCALLBACK *read_file_func) (void *opaque, void *stream, void* buf, unsigned long size);
typedef unsigned long (ZCALLBACK *write_file_func) (void *opaque, void *stream, const void* buf,
unsigned long size);
typedef int (ZCALLBACK *close_file_func) (void *opaque, void *stream);
typedef int (ZCALLBACK *testerror_file_func)(void *opaque, void *stream);
typedef long (ZCALLBACK *tell_file_func) (void *opaque, void *stream);
typedef ZPOS64_T (ZCALLBACK *tell64_file_func) (void *opaque, void *stream);
typedef long (ZCALLBACK *seek_file_func) (void *opaque, void *stream, unsigned long offset, int origin);
typedef long (ZCALLBACK *seek64_file_func) (void *opaque, void *stream, ZPOS64_T offset, int origin);
typedef struct zlib_filefunc_def_s
{
open_file_func zopen_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell_file_func ztell_file;
seek_file_func zseek_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
void* opaque;
} zlib_filefunc_def;
typedef struct zlib_filefunc64_def_s
{
open64_file_func zopen64_file;
read_file_func zread_file;
write_file_func zwrite_file;
tell64_file_func ztell64_file;
seek64_file_func zseek64_file;
close_file_func zclose_file;
testerror_file_func zerror_file;
void* opaque;
} zlib_filefunc64_def;
/***************************************************************************/
#define ZLIB_FILEFUNC_SEEK_SET (0)
#define ZLIB_FILEFUNC_SEEK_CUR (1)
#define ZLIB_FILEFUNC_SEEK_END (2)
#define ZLIB_FILEFUNC_MODE_READ (1)
#define ZLIB_FILEFUNC_MODE_WRITE (2)
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
#define ZLIB_FILEFUNC_MODE_EXISTING (4)
#define ZLIB_FILEFUNC_MODE_CREATE (8)
/***************************************************************************/
ZEXPORT void fill_fopen_filefunc(zlib_filefunc_def *pzlib_filefunc_def);
ZEXPORT void fill_fopen64_filefunc(zlib_filefunc64_def *pzlib_filefunc_def);
ZEXPORT void fill_win32_filefunc(zlib_filefunc_def *pzlib_filefunc_def);
ZEXPORT void fill_win32_filefunc64(zlib_filefunc64_def *pzlib_filefunc_def);
ZEXPORT void fill_win32_filefunc64A(zlib_filefunc64_def *pzlib_filefunc_def);
ZEXPORT void fill_memory_filefunc(zlib_filefunc_def *pzlib_filefunc_def);
/***************************************************************************/
#if MZ_COMPAT_VERSION <= 110
#define mz_dos_date dosDate
#else
#define mz_dos_date dos_date
#endif
typedef struct tm tm_unz;
typedef struct tm tm_zip;
typedef struct {
uint32_t mz_dos_date;
struct tm tmz_date;
uint16_t internal_fa; /* internal file attributes 2 bytes */
uint32_t external_fa; /* external file attributes 4 bytes */
} zip_fileinfo;
typedef const char *zipcharpc;
/***************************************************************************/
#define ZIP_OK (0)
#define ZIP_EOF (0)
#define ZIP_ERRNO (-1)
#define ZIP_PARAMERROR (-102)
#define ZIP_BADZIPFILE (-103)
#define ZIP_INTERNALERROR (-104)
#ifndef Z_DEFLATED
#define Z_DEFLATED (8)
#endif
#define Z_BZIP2ED (12)
#define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_CREATEAFTER (1)
#define APPEND_STATUS_ADDINZIP (2)
/***************************************************************************/
/* Writing a zip file */
ZEXPORT zipFile zipOpen(const char *path, int append);
ZEXPORT zipFile zipOpen64(const void *path, int append);
ZEXPORT zipFile zipOpen2(const char *path, int append, const char **globalcomment,
zlib_filefunc_def *pzlib_filefunc_def);
ZEXPORT zipFile zipOpen2_64(const void *path, int append, const char **globalcomment,
zlib_filefunc64_def *pzlib_filefunc_def);
ZEXPORT zipFile zipOpen_MZ(void *stream, int append, const char **globalcomment);
ZEXPORT void* zipGetHandle_MZ(zipFile);
ZEXPORT void* zipGetStream_MZ(zipFile file);
ZEXPORT int zipOpenNewFileInZip(zipFile file, const char *filename, const zip_fileinfo *zipfi,
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
uint16_t size_extrafield_global, const char *comment, int compression_method, int level);
ZEXPORT int zipOpenNewFileInZip_64(zipFile file, const char *filename, const zip_fileinfo *zipfi,
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
uint16_t size_extrafield_global, const char *comment, int compression_method, int level,
int zip64);
ZEXPORT int zipOpenNewFileInZip2(zipFile file, const char *filename, const zip_fileinfo *zipfi,
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
uint16_t size_extrafield_global, const char *comment, int compression_method, int level,
int raw);
ZEXPORT int zipOpenNewFileInZip2_64(zipFile file, const char *filename, const zip_fileinfo *zipfi,
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
uint16_t size_extrafield_global, const char *comment, int compression_method, int level,
int raw, int zip64);
ZEXPORT int zipOpenNewFileInZip3(zipFile file, const char *filename, const zip_fileinfo *zipfi,
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
uint16_t size_extrafield_global, const char *comment, int compression_method, int level,
int raw, int windowBits, int memLevel, int strategy, const char *password,
unsigned long crc_for_crypting);
ZEXPORT int zipOpenNewFileInZip3_64(zipFile file, const char *filename, const zip_fileinfo *zipfi,
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
uint16_t size_extrafield_global, const char *comment, int compression_method, int level,
int raw, int windowBits, int memLevel, int strategy, const char *password,
uint32_t crc_for_crypting, int zip64);
ZEXPORT int zipOpenNewFileInZip4(zipFile file, const char *filename, const zip_fileinfo *zipfi,
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
uint16_t size_extrafield_global, const char *comment, int compression_method, int level,
int raw, int windowBits, int memLevel, int strategy, const char *password,
unsigned long crc_for_crypting, unsigned long version_madeby, unsigned long flag_base);
ZEXPORT int zipOpenNewFileInZip4_64(zipFile file, const char *filename, const zip_fileinfo *zipfi,
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
uint16_t size_extrafield_global, const char *comment, int compression_method, int level,
int raw, int windowBits, int memLevel, int strategy, const char *password,
unsigned long crc_for_crypting, unsigned long version_madeby, unsigned long flag_base, int zip64);
ZEXPORT int zipOpenNewFileInZip5(zipFile file, const char *filename, const zip_fileinfo *zipfi,
const void *extrafield_local, uint16_t size_extrafield_local, const void *extrafield_global,
uint16_t size_extrafield_global, const char *comment, int compression_method, int level,
int raw, int windowBits, int memLevel, int strategy, const char *password,
unsigned long crc_for_crypting, unsigned long version_madeby, unsigned long flag_base, int zip64);
ZEXPORT int zipWriteInFileInZip(zipFile file, const void *buf, uint32_t len);
ZEXPORT int zipCloseFileInZipRaw(zipFile file, unsigned long uncompressed_size, unsigned long crc32);
ZEXPORT int zipCloseFileInZipRaw64(zipFile file, uint64_t uncompressed_size, unsigned long crc32);
ZEXPORT int zipCloseFileInZip(zipFile file);
ZEXPORT int zipCloseFileInZip64(zipFile file);
ZEXPORT int zipClose(zipFile file, const char *global_comment);
ZEXPORT int zipClose_64(zipFile file, const char *global_comment);
ZEXPORT int zipClose2_64(zipFile file, const char *global_comment, uint16_t version_madeby);
int zipClose_MZ(zipFile file, const char *global_comment);
int zipClose2_MZ(zipFile file, const char *global_comment, uint16_t version_madeby);
/***************************************************************************/
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */
typedef struct TagunzFile__ { int unused; } unz_file__;
typedef unz_file__ *unzFile;
#else
typedef void *unzFile;
#endif
/***************************************************************************/
#define UNZ_OK (0)
#define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_ERRNO (-1)
#define UNZ_EOF (0)
#define UNZ_PARAMERROR (-102)
#define UNZ_BADZIPFILE (-103)
#define UNZ_INTERNALERROR (-104)
#define UNZ_CRCERROR (-105)
#define UNZ_BADPASSWORD (-106)
/***************************************************************************/
typedef struct unz_global_info64_s {
uint64_t number_entry; /* total number of entries in the central dir on this disk */
uint32_t number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */
uint16_t size_comment; /* size of the global comment of the zipfile */
} unz_global_info64;
typedef struct unz_global_info_s {
uint32_t number_entry; /* total number of entries in the central dir on this disk */
uint32_t number_disk_with_CD; /* number the the disk with central dir, used for spanning ZIP */
uint16_t size_comment; /* size of the global comment of the zipfile */
} unz_global_info;
typedef struct unz_file_info64_s {
uint16_t version; /* version made by 2 bytes */
uint16_t version_needed; /* version needed to extract 2 bytes */
uint16_t flag; /* general purpose bit flag 2 bytes */
uint16_t compression_method; /* compression method 2 bytes */
uint32_t mz_dos_date; /* last mod file date in Dos fmt 4 bytes */
struct tm tmu_date;
uint32_t crc; /* crc-32 4 bytes */
uint64_t compressed_size; /* compressed size 8 bytes */
uint64_t uncompressed_size; /* uncompressed size 8 bytes */
uint16_t size_filename; /* filename length 2 bytes */
uint16_t size_file_extra; /* extra field length 2 bytes */
uint16_t size_file_comment; /* file comment length 2 bytes */
uint32_t disk_num_start; /* disk number start 4 bytes */
uint16_t internal_fa; /* internal file attributes 2 bytes */
uint32_t external_fa; /* external file attributes 4 bytes */
uint64_t disk_offset;
uint16_t size_file_extra_internal;
} unz_file_info64;
typedef struct unz_file_info_s {
uint16_t version; /* version made by 2 bytes */
uint16_t version_needed; /* version needed to extract 2 bytes */
uint16_t flag; /* general purpose bit flag 2 bytes */
uint16_t compression_method; /* compression method 2 bytes */
uint32_t mz_dos_date; /* last mod file date in Dos fmt 4 bytes */
struct tm tmu_date;
uint32_t crc; /* crc-32 4 bytes */
uint32_t compressed_size; /* compressed size 4 bytes */
uint32_t uncompressed_size; /* uncompressed size 4 bytes */
uint16_t size_filename; /* filename length 2 bytes */
uint16_t size_file_extra; /* extra field length 2 bytes */
uint16_t size_file_comment; /* file comment length 2 bytes */
uint16_t disk_num_start; /* disk number start 2 bytes */
uint16_t internal_fa; /* internal file attributes 2 bytes */
uint32_t external_fa; /* external file attributes 4 bytes */
uint64_t disk_offset;
} unz_file_info;
/***************************************************************************/
typedef int (*unzFileNameComparer)(unzFile file, const char *filename1, const char *filename2);
typedef int (*unzIteratorFunction)(unzFile file);
typedef int (*unzIteratorFunction2)(unzFile file, unz_file_info64 *pfile_info, char *filename,
uint16_t filename_size, void *extrafield, uint16_t extrafield_size, char *comment,
uint16_t comment_size);
/***************************************************************************/
/* Reading a zip file */
ZEXPORT unzFile unzOpen(const char *path);
ZEXPORT unzFile unzOpen64(const void *path);
ZEXPORT unzFile unzOpen2(const char *path, zlib_filefunc_def *pzlib_filefunc_def);
ZEXPORT unzFile unzOpen2_64(const void *path, zlib_filefunc64_def *pzlib_filefunc_def);
unzFile unzOpen_MZ(void *stream);
ZEXPORT int unzClose(unzFile file);
ZEXPORT int unzClose_MZ(unzFile file);
ZEXPORT void* unzGetHandle_MZ(unzFile file);
ZEXPORT void* unzGetStream_MZ(zipFile file);
ZEXPORT int unzGetGlobalInfo(unzFile file, unz_global_info* pglobal_info32);
ZEXPORT int unzGetGlobalInfo64(unzFile file, unz_global_info64 *pglobal_info);
ZEXPORT int unzGetGlobalComment(unzFile file, char *comment, unsigned long comment_size);
ZEXPORT int unzOpenCurrentFile(unzFile file);
ZEXPORT int unzOpenCurrentFilePassword(unzFile file, const char *password);
ZEXPORT int unzOpenCurrentFile2(unzFile file, int *method, int *level, int raw);
ZEXPORT int unzOpenCurrentFile3(unzFile file, int *method, int *level, int raw, const char *password);
ZEXPORT int unzReadCurrentFile(unzFile file, void *buf, uint32_t len);
ZEXPORT int unzCloseCurrentFile(unzFile file);
ZEXPORT int unzGetCurrentFileInfo(unzFile file, unz_file_info *pfile_info, char *filename,
unsigned long filename_size, void *extrafield, unsigned long extrafield_size, char *comment,
unsigned long comment_size);
ZEXPORT int unzGetCurrentFileInfo64(unzFile file, unz_file_info64 * pfile_info, char *filename,
unsigned long filename_size, void *extrafield, unsigned long extrafield_size, char *comment,
unsigned long comment_size);
ZEXPORT int unzGoToFirstFile(unzFile file);
ZEXPORT int unzGoToNextFile(unzFile file);
ZEXPORT int unzLocateFile(unzFile file, const char *filename, unzFileNameComparer filename_compare_func);
ZEXPORT int unzGetLocalExtrafield(unzFile file, void *buf, unsigned int len);
/***************************************************************************/
/* Raw access to zip file */
typedef struct unz_file_pos_s {
uint32_t pos_in_zip_directory; /* offset in zip file directory */
uint32_t num_of_file; /* # of file */
} unz_file_pos;
ZEXPORT int unzGetFilePos(unzFile file, unz_file_pos *file_pos);
ZEXPORT int unzGoToFilePos(unzFile file, unz_file_pos *file_pos);
typedef struct unz64_file_pos_s {
int64_t pos_in_zip_directory; /* offset in zip file directory */
uint64_t num_of_file; /* # of file */
} unz64_file_pos;
ZEXPORT int unzGetFilePos64(unzFile file, unz64_file_pos *file_pos);
ZEXPORT int unzGoToFilePos64(unzFile file, const unz64_file_pos *file_pos);
ZEXPORT int64_t unzGetOffset64(unzFile file);
ZEXPORT unsigned long
unzGetOffset(unzFile file);
ZEXPORT int unzSetOffset64(unzFile file, int64_t pos);
ZEXPORT int unzSetOffset(unzFile file, unsigned long pos);
ZEXPORT int32_t unztell(unzFile file);
ZEXPORT int32_t unzTell(unzFile file);
ZEXPORT uint64_t unztell64(unzFile file);
ZEXPORT uint64_t unzTell64(unzFile file);
ZEXPORT int unzSeek(unzFile file, int32_t offset, int origin);
ZEXPORT int unzSeek64(unzFile file, int64_t offset, int origin);
ZEXPORT int unzEndOfFile(unzFile file);
ZEXPORT int unzeof(unzFile file);
ZEXPORT void* unzGetStream(unzFile file);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

196
externals/minizip/mz_crypt.c vendored Normal file
View File

@ -0,0 +1,196 @@
/* mz_crypt.c -- Crypto/hash functions
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include "mz_crypt.h"
#if defined(HAVE_ZLIB)
# include "zlib.h"
# if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
# include "zlib-ng.h"
# endif
#elif defined(HAVE_LZMA)
# include "lzma.h"
#endif
/***************************************************************************/
/* Define z_crc_t in zlib 1.2.5 and less or if using zlib-ng */
#if defined(HAVE_ZLIB) && defined(ZLIBNG_VERNUM)
# if defined(ZLIB_COMPAT)
# define ZLIB_PREFIX(x) x
# else
# define ZLIB_PREFIX(x) zng_ ## x
# endif
typedef uint32_t z_crc_t;
#elif defined(HAVE_ZLIB)
# define ZLIB_PREFIX(x) x
# if (ZLIB_VERNUM < 0x1270)
typedef unsigned long z_crc_t;
# endif
#endif
/***************************************************************************/
#if defined(MZ_ZIP_NO_CRYPTO)
int32_t mz_crypt_rand(uint8_t *buf, int32_t size) {
return mz_os_rand(buf, size);
}
#endif
uint32_t mz_crypt_crc32_update(uint32_t value, const uint8_t *buf, int32_t size) {
#if defined(HAVE_ZLIB)
return (uint32_t)ZLIB_PREFIX(crc32)((z_crc_t)value, buf, (uInt)size);
#elif defined(HAVE_LZMA)
return (uint32_t)lzma_crc32(buf, (size_t)size, (uint32_t)value);
#else
static uint32_t crc32_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
value = ~value;
while (size > 0) {
value = (value >> 8) ^ crc32_table[(value ^ *buf) & 0xFF];
buf += 1;
size -= 1;
}
return ~value;
#endif
}
#if defined(HAVE_WZAES)
int32_t mz_crypt_pbkdf2(uint8_t *password, int32_t password_length, uint8_t *salt,
int32_t salt_length, int32_t iteration_count, uint8_t *key, int32_t key_length) {
void *hmac1 = NULL;
void *hmac2 = NULL;
void *hmac3 = NULL;
int32_t err = MZ_OK;
uint16_t i = 0;
uint16_t j = 0;
uint16_t k = 0;
uint16_t block_count = 0;
uint8_t uu[MZ_HASH_SHA1_SIZE];
uint8_t ux[MZ_HASH_SHA1_SIZE];
if (password == NULL || salt == NULL || key == NULL)
return MZ_PARAM_ERROR;
memset(key, 0, key_length);
mz_crypt_hmac_create(&hmac1);
mz_crypt_hmac_create(&hmac2);
mz_crypt_hmac_create(&hmac3);
mz_crypt_hmac_set_algorithm(hmac1, MZ_HASH_SHA1);
mz_crypt_hmac_set_algorithm(hmac2, MZ_HASH_SHA1);
mz_crypt_hmac_set_algorithm(hmac3, MZ_HASH_SHA1);
err = mz_crypt_hmac_init(hmac1, password, password_length);
if (err == MZ_OK)
err = mz_crypt_hmac_init(hmac2, password, password_length);
if (err == MZ_OK)
err = mz_crypt_hmac_update(hmac2, salt, salt_length);
block_count = 1 + ((uint16_t)key_length - 1) / MZ_HASH_SHA1_SIZE;
for (i = 0; (err == MZ_OK) && (i < block_count); i += 1) {
memset(ux, 0, sizeof(ux));
err = mz_crypt_hmac_copy(hmac2, hmac3);
if (err != MZ_OK)
break;
uu[0] = (uint8_t)((i + 1) >> 24);
uu[1] = (uint8_t)((i + 1) >> 16);
uu[2] = (uint8_t)((i + 1) >> 8);
uu[3] = (uint8_t)(i + 1);
for (j = 0, k = 4; j < iteration_count; j += 1) {
err = mz_crypt_hmac_update(hmac3, uu, k);
if (err == MZ_OK)
err = mz_crypt_hmac_end(hmac3, uu, sizeof(uu));
if (err != MZ_OK)
break;
for(k = 0; k < MZ_HASH_SHA1_SIZE; k += 1)
ux[k] ^= uu[k];
err = mz_crypt_hmac_copy(hmac1, hmac3);
if (err != MZ_OK)
break;
}
if (err != MZ_OK)
break;
j = 0;
k = i * MZ_HASH_SHA1_SIZE;
while (j < MZ_HASH_SHA1_SIZE && k < key_length)
key[k++] = ux[j++];
}
/* hmac3 uses the same provider as hmac2, so it must be deleted
before the context is destroyed. */
mz_crypt_hmac_delete(&hmac3);
mz_crypt_hmac_delete(&hmac1);
mz_crypt_hmac_delete(&hmac2);
return err;
}
#endif
/***************************************************************************/

65
externals/minizip/mz_crypt.h vendored Normal file
View File

@ -0,0 +1,65 @@
/* mz_crypt.h -- Crypto/hash functions
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_CRYPT_H
#define MZ_CRYPT_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
uint32_t mz_crypt_crc32_update(uint32_t value, const uint8_t *buf, int32_t size);
int32_t mz_crypt_pbkdf2(uint8_t *password, int32_t password_length, uint8_t *salt,
int32_t salt_length, int32_t iteration_count, uint8_t *key, int32_t key_length);
/***************************************************************************/
int32_t mz_crypt_rand(uint8_t *buf, int32_t size);
void mz_crypt_sha_reset(void *handle);
int32_t mz_crypt_sha_begin(void *handle);
int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size);
int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size);
void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm);
void* mz_crypt_sha_create(void **handle);
void mz_crypt_sha_delete(void **handle);
void mz_crypt_aes_reset(void *handle);
int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size);
int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size);
int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length);
int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length);
void mz_crypt_aes_set_mode(void *handle, int32_t mode);
void* mz_crypt_aes_create(void **handle);
void mz_crypt_aes_delete(void **handle);
void mz_crypt_hmac_reset(void *handle);
int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length);
int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size);
int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size);
int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle);
void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm);
void* mz_crypt_hmac_create(void **handle);
void mz_crypt_hmac_delete(void **handle);
int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size,
const char *cert_pwd, uint8_t **signature, int32_t *signature_size);
int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

487
externals/minizip/mz_crypt_apple.c vendored Normal file
View File

@ -0,0 +1,487 @@
/* mz_crypt_apple.c -- Crypto/hash functions for Apple
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include <CoreFoundation/CoreFoundation.h>
#include <CommonCrypto/CommonCryptor.h>
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonHMAC.h>
#include <Security/Security.h>
#include <Security/SecPolicy.h>
/***************************************************************************/
int32_t mz_crypt_rand(uint8_t *buf, int32_t size) {
if (SecRandomCopyBytes(kSecRandomDefault, size, buf) != errSecSuccess)
return 0;
return size;
}
/***************************************************************************/
typedef struct mz_crypt_sha_s {
CC_SHA1_CTX ctx1;
CC_SHA256_CTX ctx256;
int32_t error;
int32_t initialized;
uint16_t algorithm;
} mz_crypt_sha;
/***************************************************************************/
void mz_crypt_sha_reset(void *handle) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
sha->error = 0;
sha->initialized = 0;
}
int32_t mz_crypt_sha_begin(void *handle) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
if (sha == NULL)
return MZ_PARAM_ERROR;
mz_crypt_sha_reset(handle);
if (sha->algorithm == MZ_HASH_SHA1)
sha->error = CC_SHA1_Init(&sha->ctx1);
else if (sha->algorithm == MZ_HASH_SHA256)
sha->error = CC_SHA256_Init(&sha->ctx256);
else
return MZ_PARAM_ERROR;
if (!sha->error)
return MZ_HASH_ERROR;
sha->initialized = 1;
return MZ_OK;
}
int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
if (sha == NULL || buf == NULL || !sha->initialized)
return MZ_PARAM_ERROR;
if (sha->algorithm == MZ_HASH_SHA1)
sha->error = CC_SHA1_Update(&sha->ctx1, buf, size);
else
sha->error = CC_SHA256_Update(&sha->ctx256, buf, size);
if (!sha->error)
return MZ_HASH_ERROR;
return size;
}
int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
if (sha == NULL || digest == NULL || !sha->initialized)
return MZ_PARAM_ERROR;
if (sha->algorithm == MZ_HASH_SHA1) {
if (digest_size < MZ_HASH_SHA1_SIZE)
return MZ_BUF_ERROR;
sha->error = CC_SHA1_Final(digest, &sha->ctx1);
} else {
if (digest_size < MZ_HASH_SHA256_SIZE)
return MZ_BUF_ERROR;
sha->error = CC_SHA256_Final(digest, &sha->ctx256);
}
if (!sha->error)
return MZ_HASH_ERROR;
return MZ_OK;
}
void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
sha->algorithm = algorithm;
}
void *mz_crypt_sha_create(void **handle) {
mz_crypt_sha *sha = NULL;
sha = (mz_crypt_sha *)MZ_ALLOC(sizeof(mz_crypt_sha));
if (sha != NULL) {
memset(sha, 0, sizeof(mz_crypt_sha));
sha->algorithm = MZ_HASH_SHA256;
}
if (handle != NULL)
*handle = sha;
return sha;
}
void mz_crypt_sha_delete(void **handle) {
mz_crypt_sha *sha = NULL;
if (handle == NULL)
return;
sha = (mz_crypt_sha *)*handle;
if (sha != NULL) {
mz_crypt_sha_reset(*handle);
MZ_FREE(sha);
}
*handle = NULL;
}
/***************************************************************************/
typedef struct mz_crypt_aes_s {
CCCryptorRef crypt;
int32_t mode;
int32_t error;
} mz_crypt_aes;
/***************************************************************************/
void mz_crypt_aes_reset(void *handle) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
if (aes->crypt != NULL)
CCCryptorRelease(aes->crypt);
aes->crypt = NULL;
}
int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
size_t data_moved = 0;
if (aes == NULL || buf == NULL)
return MZ_PARAM_ERROR;
if (size != MZ_AES_BLOCK_SIZE)
return MZ_PARAM_ERROR;
aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved);
if (aes->error != kCCSuccess)
return MZ_HASH_ERROR;
return size;
}
int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
size_t data_moved = 0;
if (aes == NULL || buf == NULL)
return MZ_PARAM_ERROR;
if (size != MZ_AES_BLOCK_SIZE)
return MZ_PARAM_ERROR;
aes->error = CCCryptorUpdate(aes->crypt, buf, size, buf, size, &data_moved);
if (aes->error != kCCSuccess)
return MZ_HASH_ERROR;
return size;
}
int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
if (aes == NULL || key == NULL || key_length == 0)
return MZ_PARAM_ERROR;
mz_crypt_aes_reset(handle);
aes->error = CCCryptorCreate(kCCEncrypt, kCCAlgorithmAES, kCCOptionECBMode,
key, key_length, NULL, &aes->crypt);
if (aes->error != kCCSuccess)
return MZ_HASH_ERROR;
return MZ_OK;
}
int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
if (aes == NULL || key == NULL || key_length == 0)
return MZ_PARAM_ERROR;
mz_crypt_aes_reset(handle);
aes->error = CCCryptorCreate(kCCDecrypt, kCCAlgorithmAES, kCCOptionECBMode,
key, key_length, NULL, &aes->crypt);
if (aes->error != kCCSuccess)
return MZ_HASH_ERROR;
return MZ_OK;
}
void mz_crypt_aes_set_mode(void *handle, int32_t mode) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
aes->mode = mode;
}
void *mz_crypt_aes_create(void **handle) {
mz_crypt_aes *aes = NULL;
aes = (mz_crypt_aes *)MZ_ALLOC(sizeof(mz_crypt_aes));
if (aes != NULL)
memset(aes, 0, sizeof(mz_crypt_aes));
if (handle != NULL)
*handle = aes;
return aes;
}
void mz_crypt_aes_delete(void **handle) {
mz_crypt_aes *aes = NULL;
if (handle == NULL)
return;
aes = (mz_crypt_aes *)*handle;
if (aes != NULL) {
mz_crypt_aes_reset(*handle);
MZ_FREE(aes);
}
*handle = NULL;
}
/***************************************************************************/
typedef struct mz_crypt_hmac_s {
CCHmacContext ctx;
int32_t initialized;
int32_t error;
uint16_t algorithm;
} mz_crypt_hmac;
/***************************************************************************/
static void mz_crypt_hmac_free(void *handle) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
memset(&hmac->ctx, 0, sizeof(hmac->ctx));
}
void mz_crypt_hmac_reset(void *handle) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
mz_crypt_hmac_free(handle);
hmac->error = 0;
}
int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
CCHmacAlgorithm algorithm = 0;
if (hmac == NULL || key == NULL)
return MZ_PARAM_ERROR;
mz_crypt_hmac_reset(handle);
if (hmac->algorithm == MZ_HASH_SHA1)
algorithm = kCCHmacAlgSHA1;
else if (hmac->algorithm == MZ_HASH_SHA256)
algorithm = kCCHmacAlgSHA256;
else
return MZ_PARAM_ERROR;
CCHmacInit(&hmac->ctx, algorithm, key, key_length);
return MZ_OK;
}
int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
if (hmac == NULL || buf == NULL)
return MZ_PARAM_ERROR;
CCHmacUpdate(&hmac->ctx, buf, size);
return MZ_OK;
}
int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
if (hmac == NULL || digest == NULL)
return MZ_PARAM_ERROR;
if (hmac->algorithm == MZ_HASH_SHA1) {
if (digest_size < MZ_HASH_SHA1_SIZE)
return MZ_BUF_ERROR;
CCHmacFinal(&hmac->ctx, digest);
} else {
if (digest_size < MZ_HASH_SHA256_SIZE)
return MZ_BUF_ERROR;
CCHmacFinal(&hmac->ctx, digest);
}
return MZ_OK;
}
void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
hmac->algorithm = algorithm;
}
int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle) {
mz_crypt_hmac *source = (mz_crypt_hmac *)src_handle;
mz_crypt_hmac *target = (mz_crypt_hmac *)target_handle;
if (source == NULL || target == NULL)
return MZ_PARAM_ERROR;
memcpy(&target->ctx, &source->ctx, sizeof(CCHmacContext));
return MZ_OK;
}
void *mz_crypt_hmac_create(void **handle) {
mz_crypt_hmac *hmac = NULL;
hmac = (mz_crypt_hmac *)MZ_ALLOC(sizeof(mz_crypt_hmac));
if (hmac != NULL) {
memset(hmac, 0, sizeof(mz_crypt_hmac));
hmac->algorithm = MZ_HASH_SHA256;
}
if (handle != NULL)
*handle = hmac;
return hmac;
}
void mz_crypt_hmac_delete(void **handle) {
mz_crypt_hmac *hmac = NULL;
if (handle == NULL)
return;
hmac = (mz_crypt_hmac *)*handle;
if (hmac != NULL) {
mz_crypt_hmac_free(*handle);
MZ_FREE(hmac);
}
*handle = NULL;
}
/***************************************************************************/
#if defined(MZ_ZIP_SIGNING)
int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size,
const char *cert_pwd, uint8_t **signature, int32_t *signature_size) {
CFStringRef password_ref = NULL;
CFDictionaryRef options_dict = NULL;
CFDictionaryRef identity_trust = NULL;
CFDataRef signature_out = NULL;
CFDataRef pkcs12_data = NULL;
CFArrayRef items = 0;
SecIdentityRef identity = NULL;
SecTrustRef trust = NULL;
OSStatus status = noErr;
const void *options_key[2] = { kSecImportExportPassphrase, kSecReturnRef };
const void *options_values[2] = { 0, kCFBooleanTrue };
int32_t err = MZ_SIGN_ERROR;
if (message == NULL || cert_data == NULL || signature == NULL || signature_size == NULL)
return MZ_PARAM_ERROR;
*signature = NULL;
*signature_size = 0;
password_ref = CFStringCreateWithCString(0, cert_pwd, kCFStringEncodingUTF8);
options_values[0] = password_ref;
options_dict = CFDictionaryCreate(0, options_key, options_values, 2, 0, 0);
if (options_dict)
pkcs12_data = CFDataCreate(0, cert_data, cert_data_size);
if (pkcs12_data)
status = SecPKCS12Import(pkcs12_data, options_dict, &items);
if (status == noErr)
identity_trust = CFArrayGetValueAtIndex(items, 0);
if (identity_trust)
identity = (SecIdentityRef)CFDictionaryGetValue(identity_trust, kSecImportItemIdentity);
if (identity)
trust = (SecTrustRef)CFDictionaryGetValue(identity_trust, kSecImportItemTrust);
if (trust) {
status = CMSEncodeContent(identity, NULL, NULL, FALSE, 0, message, message_size, &signature_out);
if (status == errSecSuccess) {
*signature_size = CFDataGetLength(signature_out);
*signature = (uint8_t *)MZ_ALLOC(*signature_size);
memcpy(*signature, CFDataGetBytePtr(signature_out), *signature_size);
err = MZ_OK;
}
}
if (signature_out)
CFRelease(signature_out);
if (items)
CFRelease(items);
if (pkcs12_data)
CFRelease(pkcs12_data);
if (options_dict)
CFRelease(options_dict);
if (password_ref)
CFRelease(password_ref);
return err;
}
int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size) {
CMSDecoderRef decoder = NULL;
CMSSignerStatus signer_status = 0;
CFDataRef message_out = NULL;
SecPolicyRef trust_policy = NULL;
OSStatus status = noErr;
OSStatus verify_status = noErr;
size_t signer_count = 0;
size_t i = 0;
int32_t err = MZ_SIGN_ERROR;
if (message == NULL || signature == NULL)
return MZ_PARAM_ERROR;
status = CMSDecoderCreate(&decoder);
if (status == errSecSuccess)
status = CMSDecoderUpdateMessage(decoder, signature, signature_size);
if (status == errSecSuccess)
status = CMSDecoderFinalizeMessage(decoder);
if (status == errSecSuccess)
trust_policy = SecPolicyCreateBasicX509();
if (status == errSecSuccess && trust_policy) {
CMSDecoderGetNumSigners(decoder, &signer_count);
if (signer_count > 0)
err = MZ_OK;
for (i = 0; i < signer_count; i += 1) {
status = CMSDecoderCopySignerStatus(decoder, i, trust_policy, TRUE, &signer_status, NULL, &verify_status);
if (status != errSecSuccess || verify_status != 0 || signer_status != kCMSSignerValid) {
err = MZ_SIGN_ERROR;
break;
}
}
}
if (err == MZ_OK) {
status = CMSDecoderCopyContent(decoder, &message_out);
if ((status != errSecSuccess) ||
(CFDataGetLength(message_out) != message_size) ||
(memcmp(message, CFDataGetBytePtr(message_out), message_size) != 0))
err = MZ_SIGN_ERROR;
}
if (trust_policy)
CFRelease(trust_policy);
if (decoder)
CFRelease(decoder);
return err;
}
#endif

638
externals/minizip/mz_crypt_openssl.c vendored Normal file
View File

@ -0,0 +1,638 @@
/* mz_crypt_openssl.c -- Crypto/hash functions for OpenSSL
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include <openssl/err.h>
#include <openssl/engine.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include <openssl/aes.h>
#include <openssl/crypto.h>
#include <openssl/evp.h>
#include <openssl/hmac.h>
#if defined(MZ_ZIP_SIGNING)
/* Note: https://www.imperialviolet.org/2015/10/17/boringssl.html says that
BoringSSL does not support CMS. "#include <etc/cms.h>" will fail. See
https://bugs.chromium.org/p/boringssl/issues/detail?id=421
*/
#include <openssl/cms.h>
#include <openssl/pkcs12.h>
#include <openssl/x509.h>
#endif
/***************************************************************************/
static void mz_crypt_init(void) {
static int32_t openssl_initialized = 0;
if (openssl_initialized == 0) {
OpenSSL_add_all_algorithms();
ERR_load_BIO_strings();
ERR_load_crypto_strings();
ENGINE_load_builtin_engines();
ENGINE_register_all_complete();
openssl_initialized = 1;
}
}
int32_t mz_crypt_rand(uint8_t *buf, int32_t size) {
int32_t result = 0;
result = RAND_bytes(buf, size);
if (!result)
return MZ_CRYPT_ERROR;
return size;
}
/***************************************************************************/
typedef struct mz_crypt_sha_s {
SHA256_CTX ctx256;
SHA_CTX ctx1;
int32_t initialized;
int32_t error;
uint16_t algorithm;
} mz_crypt_sha;
/***************************************************************************/
void mz_crypt_sha_reset(void *handle) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
sha->error = 0;
sha->initialized = 0;
mz_crypt_init();
}
int32_t mz_crypt_sha_begin(void *handle) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
int32_t result = 0;
if (sha == NULL)
return MZ_PARAM_ERROR;
mz_crypt_sha_reset(handle);
if (sha->algorithm == MZ_HASH_SHA1)
result = SHA1_Init(&sha->ctx1);
else
result = SHA256_Init(&sha->ctx256);
if (!result) {
sha->error = ERR_get_error();
return MZ_HASH_ERROR;
}
sha->initialized = 1;
return MZ_OK;
}
int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
int32_t result = 0;
if (sha == NULL || buf == NULL || !sha->initialized)
return MZ_PARAM_ERROR;
if (sha->algorithm == MZ_HASH_SHA1)
result = SHA1_Update(&sha->ctx1, buf, size);
else
result = SHA256_Update(&sha->ctx256, buf, size);
if (!result) {
sha->error = ERR_get_error();
return MZ_HASH_ERROR;
}
return size;
}
int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
int32_t result = 0;
if (sha == NULL || digest == NULL || !sha->initialized)
return MZ_PARAM_ERROR;
if (sha->algorithm == MZ_HASH_SHA1) {
if (digest_size < MZ_HASH_SHA1_SIZE)
return MZ_BUF_ERROR;
result = SHA1_Final(digest, &sha->ctx1);
} else {
if (digest_size < MZ_HASH_SHA256_SIZE)
return MZ_BUF_ERROR;
result = SHA256_Final(digest, &sha->ctx256);
}
if (!result) {
sha->error = ERR_get_error();
return MZ_HASH_ERROR;
}
return MZ_OK;
}
void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
sha->algorithm = algorithm;
}
void *mz_crypt_sha_create(void **handle) {
mz_crypt_sha *sha = NULL;
sha = (mz_crypt_sha *)MZ_ALLOC(sizeof(mz_crypt_sha));
if (sha != NULL) {
memset(sha, 0, sizeof(mz_crypt_sha));
sha->algorithm = MZ_HASH_SHA256;
}
if (handle != NULL)
*handle = sha;
return sha;
}
void mz_crypt_sha_delete(void **handle) {
mz_crypt_sha *sha = NULL;
if (handle == NULL)
return;
sha = (mz_crypt_sha *)*handle;
if (sha != NULL) {
mz_crypt_sha_reset(*handle);
MZ_FREE(sha);
}
*handle = NULL;
}
/***************************************************************************/
typedef struct mz_crypt_aes_s {
AES_KEY key;
int32_t mode;
int32_t error;
uint8_t *key_copy;
int32_t key_length;
} mz_crypt_aes;
/***************************************************************************/
void mz_crypt_aes_reset(void *handle) {
MZ_UNUSED(handle);
mz_crypt_init();
}
int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
if (aes == NULL || buf == NULL)
return MZ_PARAM_ERROR;
if (size != MZ_AES_BLOCK_SIZE)
return MZ_PARAM_ERROR;
AES_encrypt(buf, buf, &aes->key);
/* Equivalent to AES_ecb_encrypt with AES_ENCRYPT */
return size;
}
int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
if (aes == NULL || buf == NULL)
return MZ_PARAM_ERROR;
if (size != MZ_AES_BLOCK_SIZE)
return MZ_PARAM_ERROR;
AES_decrypt(buf, buf, &aes->key);
/* Equivalent to AES_ecb_encrypt with AES_DECRYPT */
return size;
}
int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
int32_t result = 0;
int32_t key_bits = 0;
if (aes == NULL || key == NULL)
return MZ_PARAM_ERROR;
mz_crypt_aes_reset(handle);
key_bits = key_length * 8;
result = AES_set_encrypt_key(key, key_bits, &aes->key);
if (result) {
aes->error = ERR_get_error();
return MZ_HASH_ERROR;
}
return MZ_OK;
}
int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
int32_t result = 0;
int32_t key_bits = 0;
if (aes == NULL || key == NULL)
return MZ_PARAM_ERROR;
mz_crypt_aes_reset(handle);
key_bits = key_length * 8;
result = AES_set_decrypt_key(key, key_bits, &aes->key);
if (result) {
aes->error = ERR_get_error();
return MZ_HASH_ERROR;
}
return MZ_OK;
}
void mz_crypt_aes_set_mode(void *handle, int32_t mode) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
aes->mode = mode;
}
void *mz_crypt_aes_create(void **handle) {
mz_crypt_aes *aes = NULL;
aes = (mz_crypt_aes *)MZ_ALLOC(sizeof(mz_crypt_aes));
if (aes != NULL)
memset(aes, 0, sizeof(mz_crypt_aes));
if (handle != NULL)
*handle = aes;
return aes;
}
void mz_crypt_aes_delete(void **handle) {
mz_crypt_aes *aes = NULL;
if (handle == NULL)
return;
aes = (mz_crypt_aes *)*handle;
if (aes != NULL)
MZ_FREE(aes);
*handle = NULL;
}
/***************************************************************************/
typedef struct mz_crypt_hmac_s {
HMAC_CTX *ctx;
int32_t initialized;
int32_t error;
uint16_t algorithm;
} mz_crypt_hmac;
/***************************************************************************/
#if (OPENSSL_VERSION_NUMBER < 0x10100000L) || (defined(LIBRESSL_VERSION_NUMBER) && (LIBRESSL_VERSION_NUMBER < 0x2070000fL))
static HMAC_CTX *HMAC_CTX_new(void) {
HMAC_CTX *ctx = OPENSSL_malloc(sizeof(HMAC_CTX));
if (ctx != NULL)
HMAC_CTX_init(ctx);
return ctx;
}
static void HMAC_CTX_free(HMAC_CTX *ctx) {
if (ctx != NULL) {
HMAC_CTX_cleanup(ctx);
OPENSSL_free(ctx);
}
}
#endif
/***************************************************************************/
void mz_crypt_hmac_reset(void *handle) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
HMAC_CTX_free(hmac->ctx);
hmac->ctx = NULL;
hmac->error = 0;
mz_crypt_init();
}
int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
int32_t result = 0;
const EVP_MD *evp_md = NULL;
if (hmac == NULL || key == NULL)
return MZ_PARAM_ERROR;
mz_crypt_hmac_reset(handle);
hmac->ctx = HMAC_CTX_new();
if (hmac->algorithm == MZ_HASH_SHA1)
evp_md = EVP_sha1();
else
evp_md = EVP_sha256();
result = HMAC_Init_ex(hmac->ctx, key, key_length, evp_md, NULL);
if (!result) {
hmac->error = ERR_get_error();
return MZ_HASH_ERROR;
}
return MZ_OK;
}
int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
int32_t result = 0;
if (hmac == NULL || buf == NULL)
return MZ_PARAM_ERROR;
result = HMAC_Update(hmac->ctx, buf, size);
if (!result) {
hmac->error = ERR_get_error();
return MZ_HASH_ERROR;
}
return MZ_OK;
}
int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
int32_t result = 0;
if (hmac == NULL || digest == NULL)
return MZ_PARAM_ERROR;
if (hmac->algorithm == MZ_HASH_SHA1) {
if (digest_size < MZ_HASH_SHA1_SIZE)
return MZ_BUF_ERROR;
result = HMAC_Final(hmac->ctx, digest, (uint32_t *)&digest_size);
} else {
if (digest_size < MZ_HASH_SHA256_SIZE)
return MZ_BUF_ERROR;
result = HMAC_Final(hmac->ctx, digest, (uint32_t *)&digest_size);
}
if (!result) {
hmac->error = ERR_get_error();
return MZ_HASH_ERROR;
}
return MZ_OK;
}
void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
hmac->algorithm = algorithm;
}
int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle) {
mz_crypt_hmac *source = (mz_crypt_hmac *)src_handle;
mz_crypt_hmac *target = (mz_crypt_hmac *)target_handle;
int32_t result = 0;
if (source == NULL || target == NULL)
return MZ_PARAM_ERROR;
mz_crypt_hmac_reset(target_handle);
if (target->ctx == NULL)
target->ctx = HMAC_CTX_new();
result = HMAC_CTX_copy(target->ctx, source->ctx);
if (!result) {
target->error = ERR_get_error();
return MZ_HASH_ERROR;
}
return MZ_OK;
}
void *mz_crypt_hmac_create(void **handle) {
mz_crypt_hmac *hmac = NULL;
hmac = (mz_crypt_hmac *)MZ_ALLOC(sizeof(mz_crypt_hmac));
if (hmac != NULL) {
memset(hmac, 0, sizeof(mz_crypt_hmac));
hmac->algorithm = MZ_HASH_SHA256;
}
if (handle != NULL)
*handle = hmac;
return hmac;
}
void mz_crypt_hmac_delete(void **handle) {
mz_crypt_hmac *hmac = NULL;
if (handle == NULL)
return;
hmac = (mz_crypt_hmac *)*handle;
if (hmac != NULL) {
mz_crypt_hmac_reset(*handle);
MZ_FREE(hmac);
}
*handle = NULL;
}
/***************************************************************************/
#if defined(MZ_ZIP_SIGNING)
int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size,
const char *cert_pwd, uint8_t **signature, int32_t *signature_size) {
PKCS12 *p12 = NULL;
EVP_PKEY *evp_pkey = NULL;
BUF_MEM *buf_mem = NULL;
BIO *cert_bio = NULL;
BIO *message_bio = NULL;
BIO *signature_bio = NULL;
CMS_ContentInfo *cms = NULL;
CMS_SignerInfo *signer_info = NULL;
STACK_OF(X509) *ca_stack = NULL;
X509 *cert = NULL;
int32_t result = 0;
int32_t err = MZ_OK;
if (message == NULL || cert_data == NULL || signature == NULL || signature_size == NULL)
return MZ_PARAM_ERROR;
mz_crypt_init();
*signature = NULL;
*signature_size = 0;
cert_bio = BIO_new_mem_buf(cert_data, cert_data_size);
if (d2i_PKCS12_bio(cert_bio, &p12) == NULL)
err = MZ_SIGN_ERROR;
if (err == MZ_OK)
result = PKCS12_parse(p12, cert_pwd, &evp_pkey, &cert, &ca_stack);
if (result) {
cms = CMS_sign(NULL, NULL, ca_stack, NULL, CMS_BINARY | CMS_PARTIAL);
if (cms)
signer_info = CMS_add1_signer(cms, cert, evp_pkey, EVP_sha256(), 0);
if (signer_info == NULL) {
err = MZ_SIGN_ERROR;
} else {
message_bio = BIO_new_mem_buf(message, message_size);
signature_bio = BIO_new(BIO_s_mem());
result = CMS_final(cms, message_bio, NULL, CMS_BINARY);
if (result)
result = i2d_CMS_bio(signature_bio, cms);
if (result) {
BIO_flush(signature_bio);
BIO_get_mem_ptr(signature_bio, &buf_mem);
*signature_size = buf_mem->length;
*signature = MZ_ALLOC(buf_mem->length);
memcpy(*signature, buf_mem->data, buf_mem->length);
}
#if 0
BIO *yy = BIO_new_file("xyz", "wb");
BIO_write(yy, *signature, *signature_size);
BIO_flush(yy);
BIO_free(yy);
#endif
}
}
if (!result)
err = MZ_SIGN_ERROR;
if (cms)
CMS_ContentInfo_free(cms);
if (signature_bio)
BIO_free(signature_bio);
if (cert_bio)
BIO_free(cert_bio);
if (message_bio)
BIO_free(message_bio);
if (p12)
PKCS12_free(p12);
if (err != MZ_OK && *signature != NULL) {
MZ_FREE(*signature);
*signature = NULL;
*signature_size = 0;
}
return err;
}
int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size) {
CMS_ContentInfo *cms = NULL;
STACK_OF(X509) *signers = NULL;
STACK_OF(X509) *intercerts = NULL;
X509_STORE *cert_store = NULL;
X509_LOOKUP *lookup = NULL;
X509_STORE_CTX *store_ctx = NULL;
BIO *message_bio = NULL;
BIO *signature_bio = NULL;
BUF_MEM *buf_mem = NULL;
int32_t signer_count = 0;
int32_t result = 0;
int32_t i = 0;
int32_t err = MZ_SIGN_ERROR;
if (message == NULL || message_size == 0 || signature == NULL || signature_size == 0)
return MZ_PARAM_ERROR;
mz_crypt_init();
cert_store = X509_STORE_new();
X509_STORE_load_locations(cert_store, "cacert.pem", NULL);
X509_STORE_set_default_paths(cert_store);
#if 0
BIO *yy = BIO_new_file("xyz", "wb");
BIO_write(yy, signature, signature_size);
BIO_flush(yy);
BIO_free(yy);
#endif
lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_file());
if (lookup != NULL)
X509_LOOKUP_load_file(lookup, "cacert.pem", X509_FILETYPE_PEM);
lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_hash_dir());
if (lookup != NULL)
X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
signature_bio = BIO_new_mem_buf(signature, signature_size);
message_bio = BIO_new(BIO_s_mem());
cms = d2i_CMS_bio(signature_bio, NULL);
if (cms) {
result = CMS_verify(cms, NULL, cert_store, NULL, message_bio, CMS_NO_SIGNER_CERT_VERIFY | CMS_BINARY);
if (result)
signers = CMS_get0_signers(cms);
if (signers)
intercerts = CMS_get1_certs(cms);
if (intercerts) {
/* Verify signer certificates */
signer_count = sk_X509_num(signers);
if (signer_count > 0)
err = MZ_OK;
for (i = 0; i < signer_count; i++) {
store_ctx = X509_STORE_CTX_new();
X509_STORE_CTX_init(store_ctx, cert_store, sk_X509_value(signers, i), intercerts);
result = X509_verify_cert(store_ctx);
if (store_ctx)
X509_STORE_CTX_free(store_ctx);
if (!result) {
err = MZ_SIGN_ERROR;
break;
}
}
}
BIO_get_mem_ptr(message_bio, &buf_mem);
if (err == MZ_OK) {
/* Verify the message */
if (((int32_t)buf_mem->length != message_size) ||
(memcmp(buf_mem->data, message, message_size) != 0))
err = MZ_SIGN_ERROR;
}
}
#if 0
if (!result)
printf(ERR_error_string(ERR_get_error(), NULL));
#endif
if (cms)
CMS_ContentInfo_free(cms);
if (message_bio)
BIO_free(message_bio);
if (signature_bio)
BIO_free(signature_bio);
if (cert_store)
X509_STORE_free(cert_store);
return err;
}
#endif

739
externals/minizip/mz_crypt_win32.c vendored Normal file
View File

@ -0,0 +1,739 @@
/* mz_crypt_win32.c -- Crypto/hash functions for Windows
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include "mz_crypt.h"
#include <windows.h>
#include <wincrypt.h>
/***************************************************************************/
int32_t mz_crypt_rand(uint8_t *buf, int32_t size) {
HCRYPTPROV provider;
int32_t result = 0;
result = CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
if (result) {
result = CryptGenRandom(provider, size, buf);
CryptReleaseContext(provider, 0);
if (result)
return size;
}
return mz_os_rand(buf, size);
}
/***************************************************************************/
typedef struct mz_crypt_sha_s {
HCRYPTPROV provider;
HCRYPTHASH hash;
int32_t error;
uint16_t algorithm;
} mz_crypt_sha;
/***************************************************************************/
void mz_crypt_sha_reset(void *handle) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
if (sha->hash)
CryptDestroyHash(sha->hash);
sha->hash = 0;
if (sha->provider)
CryptReleaseContext(sha->provider, 0);
sha->provider = 0;
sha->error = 0;
}
int32_t mz_crypt_sha_begin(void *handle) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
ALG_ID alg_id = 0;
int32_t result = 0;
int32_t err = MZ_OK;
if (sha == NULL)
return MZ_PARAM_ERROR;
if (sha->algorithm == MZ_HASH_SHA1)
alg_id = CALG_SHA1;
else
alg_id = CALG_SHA_256;
result = CryptAcquireContext(&sha->provider, NULL, NULL, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
if (!result) {
sha->error = GetLastError();
err = MZ_CRYPT_ERROR;
}
if (result) {
result = CryptCreateHash(sha->provider, alg_id, 0, 0, &sha->hash);
if (!result) {
sha->error = GetLastError();
err = MZ_HASH_ERROR;
}
}
return err;
}
int32_t mz_crypt_sha_update(void *handle, const void *buf, int32_t size) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
int32_t result = 0;
if (sha == NULL || buf == NULL || sha->hash == 0)
return MZ_PARAM_ERROR;
result = CryptHashData(sha->hash, buf, size, 0);
if (!result) {
sha->error = GetLastError();
return MZ_HASH_ERROR;
}
return size;
}
int32_t mz_crypt_sha_end(void *handle, uint8_t *digest, int32_t digest_size) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
int32_t result = 0;
int32_t expected_size = 0;
if (sha == NULL || digest == NULL || sha->hash == 0)
return MZ_PARAM_ERROR;
result = CryptGetHashParam(sha->hash, HP_HASHVAL, NULL, (DWORD *)&expected_size, 0);
if (expected_size > digest_size)
return MZ_BUF_ERROR;
if (!result)
return MZ_HASH_ERROR;
result = CryptGetHashParam(sha->hash, HP_HASHVAL, digest, (DWORD *)&digest_size, 0);
if (!result) {
sha->error = GetLastError();
return MZ_HASH_ERROR;
}
return MZ_OK;
}
void mz_crypt_sha_set_algorithm(void *handle, uint16_t algorithm) {
mz_crypt_sha *sha = (mz_crypt_sha *)handle;
sha->algorithm = algorithm;
}
void *mz_crypt_sha_create(void **handle) {
mz_crypt_sha *sha = NULL;
sha = (mz_crypt_sha *)MZ_ALLOC(sizeof(mz_crypt_sha));
if (sha != NULL) {
memset(sha, 0, sizeof(mz_crypt_sha));
sha->algorithm = MZ_HASH_SHA256;
}
if (handle != NULL)
*handle = sha;
return sha;
}
void mz_crypt_sha_delete(void **handle) {
mz_crypt_sha *sha = NULL;
if (handle == NULL)
return;
sha = (mz_crypt_sha *)*handle;
if (sha != NULL) {
mz_crypt_sha_reset(*handle);
MZ_FREE(sha);
}
*handle = NULL;
}
/***************************************************************************/
typedef struct mz_crypt_aes_s {
HCRYPTPROV provider;
HCRYPTKEY key;
int32_t mode;
int32_t error;
} mz_crypt_aes;
/***************************************************************************/
static void mz_crypt_aes_free(void *handle) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
if (aes->key)
CryptDestroyKey(aes->key);
aes->key = 0;
if (aes->provider)
CryptReleaseContext(aes->provider, 0);
aes->provider = 0;
}
void mz_crypt_aes_reset(void *handle) {
mz_crypt_aes_free(handle);
}
int32_t mz_crypt_aes_encrypt(void *handle, uint8_t *buf, int32_t size) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
int32_t result = 0;
if (aes == NULL || buf == NULL)
return MZ_PARAM_ERROR;
if (size != MZ_AES_BLOCK_SIZE)
return MZ_PARAM_ERROR;
result = CryptEncrypt(aes->key, 0, 0, 0, buf, (DWORD *)&size, size);
if (!result) {
aes->error = GetLastError();
return MZ_CRYPT_ERROR;
}
return size;
}
int32_t mz_crypt_aes_decrypt(void *handle, uint8_t *buf, int32_t size) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
int32_t result = 0;
if (aes == NULL || buf == NULL)
return MZ_PARAM_ERROR;
if (size != MZ_AES_BLOCK_SIZE)
return MZ_PARAM_ERROR;
result = CryptDecrypt(aes->key, 0, 0, 0, buf, (DWORD *)&size);
if (!result) {
aes->error = GetLastError();
return MZ_CRYPT_ERROR;
}
return size;
}
static int32_t mz_crypt_aes_set_key(void *handle, const void *key, int32_t key_length) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
HCRYPTHASH hash = 0;
ALG_ID alg_id = 0;
typedef struct key_blob_header_s {
BLOBHEADER hdr;
uint32_t key_length;
} key_blob_header_s;
key_blob_header_s *key_blob_s = NULL;
uint32_t mode = CRYPT_MODE_ECB;
uint8_t *key_blob = NULL;
int32_t key_blob_size = 0;
int32_t result = 0;
int32_t err = MZ_OK;
if (aes == NULL || key == NULL)
return MZ_PARAM_ERROR;
mz_crypt_aes_reset(handle);
if (key_length == MZ_AES_KEY_LENGTH(MZ_AES_ENCRYPTION_MODE_128))
alg_id = CALG_AES_128;
else if (key_length == MZ_AES_KEY_LENGTH(MZ_AES_ENCRYPTION_MODE_192))
alg_id = CALG_AES_192;
else if (key_length == MZ_AES_KEY_LENGTH(MZ_AES_ENCRYPTION_MODE_256))
alg_id = CALG_AES_256;
else
return MZ_PARAM_ERROR;
result = CryptAcquireContext(&aes->provider, NULL, MS_ENH_RSA_AES_PROV, PROV_RSA_AES, CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
if (result) {
key_blob_size = sizeof(key_blob_header_s) + key_length;
key_blob = (uint8_t *)MZ_ALLOC(key_blob_size);
if (key_blob) {
key_blob_s = (key_blob_header_s *)key_blob;
key_blob_s->hdr.bType = PLAINTEXTKEYBLOB;
key_blob_s->hdr.bVersion = CUR_BLOB_VERSION;
key_blob_s->hdr.aiKeyAlg = alg_id;
key_blob_s->hdr.reserved = 0;
key_blob_s->key_length = key_length;
memcpy(key_blob + sizeof(key_blob_header_s), key, key_length);
result = CryptImportKey(aes->provider, key_blob, key_blob_size, 0, 0, &aes->key);
SecureZeroMemory(key_blob, key_blob_size);
MZ_FREE(key_blob);
} else {
err = MZ_MEM_ERROR;
}
}
if (result && err == MZ_OK)
result = CryptSetKeyParam(aes->key, KP_MODE, (const uint8_t *)&mode, 0);
if (!result && err == MZ_OK) {
aes->error = GetLastError();
err = MZ_CRYPT_ERROR;
}
if (hash)
CryptDestroyHash(hash);
return err;
}
int32_t mz_crypt_aes_set_encrypt_key(void *handle, const void *key, int32_t key_length) {
return mz_crypt_aes_set_key(handle, key, key_length);
}
int32_t mz_crypt_aes_set_decrypt_key(void *handle, const void *key, int32_t key_length) {
return mz_crypt_aes_set_key(handle, key, key_length);
}
void mz_crypt_aes_set_mode(void *handle, int32_t mode) {
mz_crypt_aes *aes = (mz_crypt_aes *)handle;
aes->mode = mode;
}
void *mz_crypt_aes_create(void **handle) {
mz_crypt_aes *aes = NULL;
aes = (mz_crypt_aes *)MZ_ALLOC(sizeof(mz_crypt_aes));
if (aes != NULL)
memset(aes, 0, sizeof(mz_crypt_aes));
if (handle != NULL)
*handle = aes;
return aes;
}
void mz_crypt_aes_delete(void **handle) {
mz_crypt_aes *aes = NULL;
if (handle == NULL)
return;
aes = (mz_crypt_aes *)*handle;
if (aes != NULL) {
mz_crypt_aes_free(*handle);
MZ_FREE(aes);
}
*handle = NULL;
}
/***************************************************************************/
typedef struct mz_crypt_hmac_s {
HCRYPTPROV provider;
HCRYPTHASH hash;
HCRYPTKEY key;
HMAC_INFO info;
int32_t mode;
int32_t error;
uint16_t algorithm;
} mz_crypt_hmac;
/***************************************************************************/
static void mz_crypt_hmac_free(void *handle) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
if (hmac->key)
CryptDestroyKey(hmac->key);
hmac->key = 0;
if (hmac->hash)
CryptDestroyHash(hmac->hash);
hmac->hash = 0;
if (hmac->provider)
CryptReleaseContext(hmac->provider, 0);
hmac->provider = 0;
memset(&hmac->info, 0, sizeof(hmac->info));
}
void mz_crypt_hmac_reset(void *handle) {
mz_crypt_hmac_free(handle);
}
int32_t mz_crypt_hmac_init(void *handle, const void *key, int32_t key_length) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
ALG_ID alg_id = 0;
typedef struct key_blob_header_s {
BLOBHEADER hdr;
uint32_t key_length;
} key_blob_header_s;
key_blob_header_s *key_blob_s = NULL;
uint8_t *key_blob = NULL;
int32_t key_blob_size = 0;
int32_t result = 0;
int32_t err = MZ_OK;
if (hmac == NULL || key == NULL)
return MZ_PARAM_ERROR;
mz_crypt_hmac_reset(handle);
if (hmac->algorithm == MZ_HASH_SHA1)
alg_id = CALG_SHA1;
else
alg_id = CALG_SHA_256;
hmac->info.HashAlgid = alg_id;
result = CryptAcquireContext(&hmac->provider, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT);
if (!result) {
hmac->error = GetLastError();
err = MZ_CRYPT_ERROR;
} else {
/* Zero-pad odd key lengths */
if (key_length % 2 == 1)
key_length += 1;
key_blob_size = sizeof(key_blob_header_s) + key_length;
key_blob = (uint8_t *)MZ_ALLOC(key_blob_size);
}
if (key_blob) {
memset(key_blob, 0, key_blob_size);
key_blob_s = (key_blob_header_s *)key_blob;
key_blob_s->hdr.bType = PLAINTEXTKEYBLOB;
key_blob_s->hdr.bVersion = CUR_BLOB_VERSION;
key_blob_s->hdr.aiKeyAlg = CALG_RC2;
key_blob_s->hdr.reserved = 0;
key_blob_s->key_length = key_length;
memcpy(key_blob + sizeof(key_blob_header_s), key, key_length);
result = CryptImportKey(hmac->provider, key_blob, key_blob_size, 0, CRYPT_IPSEC_HMAC_KEY, &hmac->key);
if (result)
result = CryptCreateHash(hmac->provider, CALG_HMAC, hmac->key, 0, &hmac->hash);
if (result)
result = CryptSetHashParam(hmac->hash, HP_HMAC_INFO, (uint8_t *)&hmac->info, 0);
SecureZeroMemory(key_blob, key_blob_size);
MZ_FREE(key_blob);
} else if (err == MZ_OK) {
err = MZ_MEM_ERROR;
}
if (!result) {
hmac->error = GetLastError();
err = MZ_CRYPT_ERROR;
}
if (err != MZ_OK)
mz_crypt_hmac_free(handle);
return err;
}
int32_t mz_crypt_hmac_update(void *handle, const void *buf, int32_t size) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
int32_t result = 0;
if (hmac == NULL || buf == NULL || hmac->hash == 0)
return MZ_PARAM_ERROR;
result = CryptHashData(hmac->hash, buf, size, 0);
if (!result) {
hmac->error = GetLastError();
return MZ_HASH_ERROR;
}
return MZ_OK;
}
int32_t mz_crypt_hmac_end(void *handle, uint8_t *digest, int32_t digest_size) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
int32_t result = 0;
int32_t expected_size = 0;
if (hmac == NULL || digest == NULL || hmac->hash == 0)
return MZ_PARAM_ERROR;
result = CryptGetHashParam(hmac->hash, HP_HASHVAL, NULL, (DWORD *)&expected_size, 0);
if (expected_size > digest_size)
return MZ_BUF_ERROR;
if (!result)
return MZ_HASH_ERROR;
result = CryptGetHashParam(hmac->hash, HP_HASHVAL, digest, (DWORD *)&digest_size, 0);
if (!result) {
hmac->error = GetLastError();
return MZ_HASH_ERROR;
}
return MZ_OK;
}
void mz_crypt_hmac_set_algorithm(void *handle, uint16_t algorithm) {
mz_crypt_hmac *hmac = (mz_crypt_hmac *)handle;
hmac->algorithm = algorithm;
}
int32_t mz_crypt_hmac_copy(void *src_handle, void *target_handle) {
mz_crypt_hmac *source = (mz_crypt_hmac *)src_handle;
mz_crypt_hmac *target = (mz_crypt_hmac *)target_handle;
int32_t result = 0;
int32_t err = MZ_OK;
if (target->hash) {
CryptDestroyHash(target->hash);
target->hash = 0;
}
result = CryptDuplicateHash(source->hash, NULL, 0, &target->hash);
if (!result) {
target->error = GetLastError();
err = MZ_HASH_ERROR;
}
return err;
}
void *mz_crypt_hmac_create(void **handle) {
mz_crypt_hmac *hmac = NULL;
hmac = (mz_crypt_hmac *)MZ_ALLOC(sizeof(mz_crypt_hmac));
if (hmac != NULL) {
memset(hmac, 0, sizeof(mz_crypt_hmac));
hmac->algorithm = MZ_HASH_SHA256;
}
if (handle != NULL)
*handle = hmac;
return hmac;
}
void mz_crypt_hmac_delete(void **handle) {
mz_crypt_hmac *hmac = NULL;
if (handle == NULL)
return;
hmac = (mz_crypt_hmac *)*handle;
if (hmac != NULL) {
mz_crypt_hmac_free(*handle);
MZ_FREE(hmac);
}
*handle = NULL;
}
/***************************************************************************/
#if defined(MZ_ZIP_SIGNING)
int32_t mz_crypt_sign(uint8_t *message, int32_t message_size, uint8_t *cert_data, int32_t cert_data_size,
const char *cert_pwd, uint8_t **signature, int32_t *signature_size) {
CRYPT_SIGN_MESSAGE_PARA sign_params;
CRYPT_DATA_BLOB cert_data_blob;
PCCERT_CONTEXT cert_context = NULL;
HCERTSTORE cert_store = 0;
wchar_t *password_wide = NULL;
int32_t result = 0;
int32_t err = MZ_OK;
uint32_t messages_sizes[1];
uint8_t *messages[1];
if (message == NULL || cert_data == NULL || signature == NULL || signature_size == NULL)
return MZ_PARAM_ERROR;
*signature = NULL;
*signature_size = 0;
cert_data_blob.pbData = cert_data;
cert_data_blob.cbData = cert_data_size;
password_wide = mz_os_unicode_string_create(cert_pwd, MZ_ENCODING_UTF8);
if (password_wide) {
cert_store = PFXImportCertStore(&cert_data_blob, password_wide, 0);
mz_os_unicode_string_delete(&password_wide);
}
if (cert_store == NULL)
cert_store = PFXImportCertStore(&cert_data_blob, L"", 0);
if (cert_store == NULL)
cert_store = PFXImportCertStore(&cert_data_blob, NULL, 0);
if (cert_store == NULL)
return MZ_PARAM_ERROR;
if (err == MZ_OK) {
cert_context = CertFindCertificateInStore(cert_store,
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_HAS_PRIVATE_KEY, NULL, NULL);
if (cert_context == NULL)
err = MZ_PARAM_ERROR;
}
if (err == MZ_OK) {
memset(&sign_params, 0, sizeof(sign_params));
sign_params.cbSize = sizeof(sign_params);
sign_params.dwMsgEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
sign_params.pSigningCert = cert_context;
sign_params.HashAlgorithm.pszObjId = szOID_NIST_sha256;
sign_params.cMsgCert = 1;
sign_params.rgpMsgCert = &cert_context;
messages[0] = message;
messages_sizes[0] = message_size;
#if 0 /* Timestamp support */
CRYPT_ATTR_BLOB crypt_blob;
CRYPT_TIMESTAMP_CONTEXT *ts_context = NULL;
CRYPT_ATTRIBUTE unauth_attribs[1];
wchar_t *timestamp_url_wide = NULL;
const char *timestamp_url = NULL;
if (timestamp_url != NULL)
timestamp_url_wide = mz_os_unicode_string_create(timestamp_url);
if (timestamp_url_wide != NULL) {
result = CryptRetrieveTimeStamp(timestamp_url_wide,
TIMESTAMP_NO_AUTH_RETRIEVAL | TIMESTAMP_VERIFY_CONTEXT_SIGNATURE, 0, szOID_NIST_sha256,
NULL, message, message_size, &ts_context, NULL, NULL);
mz_os_unicode_string_delete(&timestamp_url_wide);
if ((result) && (ts_context != NULL)) {
crypt_blob.cbData = ts_context->cbEncoded;
crypt_blob.pbData = ts_context->pbEncoded;
unauth_attribs[0].pszObjId = "1.2.840.113549.1.9.16.2.14"; //id-smime-aa-timeStampToken
unauth_attribs[0].cValue = 1;
unauth_attribs[0].rgValue = &crypt_blob;
sign_params.rgUnauthAttr = &unauth_attribs[0];
sign_params.cUnauthAttr = 1;
}
}
if (ts_context != NULL)
CryptMemFree(ts_context);
if (result)
#endif
result = CryptSignMessage(&sign_params, FALSE, 1, (const BYTE **)messages, (DWORD *)messages_sizes,
NULL, (DWORD *)signature_size);
if (result && *signature_size > 0)
*signature = (uint8_t *)MZ_ALLOC(*signature_size);
if (result && *signature != NULL)
result = CryptSignMessage(&sign_params, FALSE, 1, (const BYTE **)messages, (DWORD *)messages_sizes,
*signature, (DWORD *)signature_size);
if (!result)
err = MZ_SIGN_ERROR;
}
if (cert_context != NULL)
CertFreeCertificateContext(cert_context);
if (cert_store != NULL)
CertCloseStore(cert_store, 0);
return err;
}
int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size) {
CRYPT_VERIFY_MESSAGE_PARA verify_params;
CERT_CONTEXT *signer_cert = NULL;
CERT_CHAIN_PARA chain_para;
CERT_CHAIN_CONTEXT *chain_context = NULL;
CERT_CHAIN_POLICY_PARA chain_policy;
CERT_CHAIN_POLICY_STATUS chain_policy_status;
HCRYPTMSG crypt_msg = 0;
int32_t result = 0;
int32_t err = MZ_SIGN_ERROR;
uint8_t *decoded = NULL;
int32_t decoded_size = 0;
memset(&verify_params, 0, sizeof(verify_params));
verify_params.cbSize = sizeof(verify_params);
verify_params.dwMsgAndCertEncodingType = PKCS_7_ASN_ENCODING | X509_ASN_ENCODING;
result = CryptVerifyMessageSignature(&verify_params, 0, signature, signature_size,
NULL, (DWORD *)&decoded_size, NULL);
if (result && decoded_size > 0)
decoded = (uint8_t *)MZ_ALLOC(decoded_size);
if (result && decoded != NULL)
result = CryptVerifyMessageSignature(&verify_params, 0, signature, signature_size,
decoded, (DWORD *)&decoded_size, (const CERT_CONTEXT **)&signer_cert);
/* Get and validate certificate chain */
memset(&chain_para, 0, sizeof(chain_para));
if (result && signer_cert != NULL)
result = CertGetCertificateChain(NULL, signer_cert, NULL, NULL, &chain_para,
CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, NULL, (const CERT_CHAIN_CONTEXT **)&chain_context);
memset(&chain_policy, 0, sizeof(chain_policy));
chain_policy.cbSize = sizeof(CERT_CHAIN_POLICY_PARA);
memset(&chain_policy_status, 0, sizeof(chain_policy_status));
chain_policy_status.cbSize = sizeof(CERT_CHAIN_POLICY_STATUS);
if (result && chain_context != NULL)
result = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_BASE, chain_context,
&chain_policy, &chain_policy_status);
if (chain_policy_status.dwError != S_OK)
result = 0;
#if 0
crypt_msg = CryptMsgOpenToDecode(PKCS_7_ASN_ENCODING | X509_ASN_ENCODING, 0, 0, 0, NULL, NULL);
if (crypt_msg != NULL) {
/* Timestamp support */
PCRYPT_ATTRIBUTES unauth_attribs = NULL;
HCRYPTMSG ts_msg = 0;
uint8_t *ts_content = NULL;
int32_t ts_content_size = 0;
uint8_t *ts_signature = NULL;
int32_t ts_signature_size = 0;
result = CryptMsgUpdate(crypt_msg, signature, signature_size, 1);
if (result)
CryptMsgGetParam(crypt_msg, CMSG_SIGNER_UNAUTH_ATTR_PARAM, 0, NULL, &ts_signature_size);
if ((result) && (ts_signature_size > 0))
ts_signature = (uint8_t *)MZ_ALLOC(ts_signature_size);
if ((result) && (ts_signature != NULL)) {
result = CryptMsgGetParam(crypt_msg, CMSG_SIGNER_UNAUTH_ATTR_PARAM, 0, ts_signature,
&ts_signature_size);
if (result)
{
unauth_attribs = (PCRYPT_ATTRIBUTES)ts_signature;
if ((unauth_attribs->cAttr > 0) && (unauth_attribs->rgAttr[0].cValue > 0))
{
ts_content = unauth_attribs->rgAttr[0].rgValue->pbData;
ts_content_size = unauth_attribs->rgAttr[0].rgValue->cbData;
}
}
if ((result) && (ts_content != NULL))
result = CryptVerifyTimeStampSignature(ts_content, ts_content_size, decoded,
decoded_size, 0, &crypt_context, NULL, NULL);
if (result)
err = MZ_OK;
}
if (ts_signature != NULL)
MZ_FREE(ts_signature);
if (crypt_context != NULL)
CryptMemFree(crypt_context);
} else {
result = 0;
}
#endif
if ((result) && (decoded != NULL) && (decoded_size == message_size)) {
/* Verify cms message with our stored message */
if (memcmp(decoded, message, message_size) == 0)
err = MZ_OK;
}
if (chain_context != NULL)
CertFreeCertificateChain(chain_context);
if (signer_cert != NULL)
CertFreeCertificateContext(signer_cert);
if (crypt_msg != NULL)
CryptMsgClose(crypt_msg);
if (decoded != NULL)
MZ_FREE(decoded);
return err;
}
#endif

354
externals/minizip/mz_os.c vendored Normal file
View File

@ -0,0 +1,354 @@
/* mz_os.c -- System functions
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 1998-2010 Gilles Vollant
https://www.winimage.com/zLibDll/minizip.html
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_crypt.h"
#include "mz_os.h"
#include "mz_strm.h"
#include "mz_strm_os.h"
#include <ctype.h> /* tolower */
/***************************************************************************/
int32_t mz_path_combine(char *path, const char *join, int32_t max_path) {
int32_t path_len = 0;
if (path == NULL || join == NULL || max_path == 0)
return MZ_PARAM_ERROR;
path_len = (int32_t)strlen(path);
if (path_len == 0) {
strncpy(path, join, max_path - 1);
path[max_path - 1] = 0;
} else {
mz_path_append_slash(path, max_path, MZ_PATH_SLASH_PLATFORM);
strncat(path, join, max_path - path_len);
}
return MZ_OK;
}
int32_t mz_path_append_slash(char *path, int32_t max_path, char slash) {
int32_t path_len = (int32_t)strlen(path);
if ((path_len + 2) >= max_path)
return MZ_BUF_ERROR;
if (path[path_len - 1] != '\\' && path[path_len - 1] != '/') {
path[path_len] = slash;
path[path_len + 1] = 0;
}
return MZ_OK;
}
int32_t mz_path_remove_slash(char *path) {
int32_t path_len = (int32_t)strlen(path);
while (path_len > 0) {
if (path[path_len - 1] == '\\' || path[path_len - 1] == '/')
path[path_len - 1] = 0;
else
break;
path_len -= 1;
}
return MZ_OK;
}
int32_t mz_path_has_slash(const char *path) {
int32_t path_len = (int32_t)strlen(path);
if (path[path_len - 1] != '\\' && path[path_len - 1] != '/')
return MZ_EXIST_ERROR;
return MZ_OK;
}
int32_t mz_path_convert_slashes(char *path, char slash) {
int32_t i = 0;
for (i = 0; i < (int32_t)strlen(path); i += 1) {
if (path[i] == '\\' || path[i] == '/')
path[i] = slash;
}
return MZ_OK;
}
int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case) {
while (*path != 0) {
switch (*wildcard) {
case '*':
if (*(wildcard + 1) == 0)
return MZ_OK;
while (*path != 0) {
if (mz_path_compare_wc(path, (wildcard + 1), ignore_case) == MZ_OK)
return MZ_OK;
path += 1;
}
return MZ_EXIST_ERROR;
default:
/* Ignore differences in path slashes on platforms */
if ((*path == '\\' && *wildcard == '/') || (*path == '/' && *wildcard == '\\'))
break;
if (ignore_case) {
if (tolower(*path) != tolower(*wildcard))
return MZ_EXIST_ERROR;
} else {
if (*path != *wildcard)
return MZ_EXIST_ERROR;
}
break;
}
path += 1;
wildcard += 1;
}
if ((*wildcard != 0) && (*wildcard != '*'))
return MZ_EXIST_ERROR;
return MZ_OK;
}
int32_t mz_path_resolve(const char *path, char *output, int32_t max_output) {
const char *source = path;
const char *check = output;
char *target = output;
if (max_output <= 0)
return MZ_PARAM_ERROR;
while (*source != 0 && max_output > 1) {
check = source;
if ((*check == '\\') || (*check == '/'))
check += 1;
if ((source == path) || (target == output) || (check != source)) {
/* Skip double paths */
if ((*check == '\\') || (*check == '/')) {
source += 1;
continue;
}
if (*check == '.') {
check += 1;
/* Remove . if at end of string and not at the beginning */
if ((*check == 0) && (source != path && target != output)) {
/* Copy last slash */
*target = *source;
target += 1;
max_output -= 1;
source += (check - source);
continue;
}
/* Remove . if not at end of string */
else if ((*check == '\\') || (*check == '/')) {
source += (check - source);
/* Skip slash if at beginning of string */
if (target == output && *source != 0)
source += 1;
continue;
}
/* Go to parent directory .. */
else if (*check == '.') {
check += 1;
if ((*check == 0) || (*check == '\\' || *check == '/')) {
source += (check - source);
/* Search backwards for previous slash */
if (target != output) {
target -= 1;
do {
if ((*target == '\\') || (*target == '/'))
break;
target -= 1;
max_output += 1;
} while (target > output);
}
if ((target == output) && (*source != 0))
source += 1;
if ((*target == '\\' || *target == '/') && (*source == 0))
target += 1;
*target = 0;
continue;
}
}
}
}
*target = *source;
source += 1;
target += 1;
max_output -= 1;
}
*target = 0;
if (*path == 0)
return MZ_INTERNAL_ERROR;
return MZ_OK;
}
int32_t mz_path_remove_filename(char *path) {
char *path_ptr = NULL;
if (path == NULL)
return MZ_PARAM_ERROR;
path_ptr = path + strlen(path) - 1;
while (path_ptr > path) {
if ((*path_ptr == '/') || (*path_ptr == '\\')) {
*path_ptr = 0;
break;
}
path_ptr -= 1;
}
if (path_ptr == path)
*path_ptr = 0;
return MZ_OK;
}
int32_t mz_path_remove_extension(char *path) {
char *path_ptr = NULL;
if (path == NULL)
return MZ_PARAM_ERROR;
path_ptr = path + strlen(path) - 1;
while (path_ptr > path) {
if ((*path_ptr == '/') || (*path_ptr == '\\'))
break;
if (*path_ptr == '.') {
*path_ptr = 0;
break;
}
path_ptr -= 1;
}
if (path_ptr == path)
*path_ptr = 0;
return MZ_OK;
}
int32_t mz_path_get_filename(const char *path, const char **filename) {
const char *match = NULL;
if (path == NULL || filename == NULL)
return MZ_PARAM_ERROR;
*filename = NULL;
for (match = path; *match != 0; match += 1) {
if ((*match == '\\') || (*match == '/'))
*filename = match + 1;
}
if (*filename == NULL)
return MZ_EXIST_ERROR;
return MZ_OK;
}
int32_t mz_dir_make(const char *path) {
int32_t err = MZ_OK;
int16_t len = 0;
char *current_dir = NULL;
char *match = NULL;
char hold = 0;
len = (int16_t)strlen(path);
if (len <= 0)
return 0;
current_dir = (char *)MZ_ALLOC((uint16_t)len + 1);
if (current_dir == NULL)
return MZ_MEM_ERROR;
strcpy(current_dir, path);
mz_path_remove_slash(current_dir);
err = mz_os_make_dir(current_dir);
if (err != MZ_OK) {
match = current_dir + 1;
while (1) {
while (*match != 0 && *match != '\\' && *match != '/')
match += 1;
hold = *match;
*match = 0;
err = mz_os_make_dir(current_dir);
if (err != MZ_OK)
break;
if (hold == 0)
break;
*match = hold;
match += 1;
}
}
MZ_FREE(current_dir);
return err;
}
int32_t mz_file_get_crc(const char *path, uint32_t *result_crc) {
void *stream = NULL;
uint32_t crc32 = 0;
int32_t read = 0;
int32_t err = MZ_OK;
uint8_t buf[16384];
mz_stream_os_create(&stream);
err = mz_stream_os_open(stream, path, MZ_OPEN_MODE_READ);
if (err == MZ_OK) {
do {
read = mz_stream_os_read(stream, buf, sizeof(buf));
if (read < 0) {
err = read;
break;
}
crc32 = mz_crypt_crc32_update(crc32, buf, read);
} while ((err == MZ_OK) && (read > 0));
mz_stream_os_close(stream);
}
*result_crc = crc32;
mz_stream_os_delete(&stream);
return err;
}
/***************************************************************************/

175
externals/minizip/mz_os.h vendored Normal file
View File

@ -0,0 +1,175 @@
/* mz_os.h -- System functions
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_OS_H
#define MZ_OS_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
#if defined(__APPLE__)
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_OSX_DARWIN)
#elif defined(__riscos__)
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_RISCOS)
#elif defined(_WIN32)
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_WINDOWS_NTFS)
#else
# define MZ_VERSION_MADEBY_HOST_SYSTEM (MZ_HOST_SYSTEM_UNIX)
#endif
#if defined(HAVE_LZMA) || defined(HAVE_LIBCOMP)
# define MZ_VERSION_MADEBY_ZIP_VERSION (63)
#elif defined(HAVE_WZAES)
# define MZ_VERSION_MADEBY_ZIP_VERSION (51)
#elif defined(HAVE_BZIP2)
# define MZ_VERSION_MADEBY_ZIP_VERSION (46)
#else
# define MZ_VERSION_MADEBY_ZIP_VERSION (45)
#endif
#define MZ_VERSION_MADEBY ((MZ_VERSION_MADEBY_HOST_SYSTEM << 8) | \
(MZ_VERSION_MADEBY_ZIP_VERSION))
#define MZ_PATH_SLASH_UNIX ('/')
#if defined(_WIN32)
# define MZ_PATH_SLASH_PLATFORM ('\\')
#else
# define MZ_PATH_SLASH_PLATFORM (MZ_PATH_SLASH_UNIX)
#endif
/***************************************************************************/
#if defined(_WIN32)
struct dirent {
char d_name[256];
};
typedef void* DIR;
#else
#include <dirent.h>
#endif
/***************************************************************************/
/* Shared functions */
int32_t mz_path_combine(char *path, const char *join, int32_t max_path);
/* Combines two paths */
int32_t mz_path_append_slash(char *path, int32_t max_path, char slash);
/* Appends a path slash on to the end of the path */
int32_t mz_path_remove_slash(char *path);
/* Removes a path slash from the end of the path */
int32_t mz_path_has_slash(const char *path);
/* Returns whether or not the path ends with slash */
int32_t mz_path_convert_slashes(char *path, char slash);
/* Converts the slashes in a path */
int32_t mz_path_compare_wc(const char *path, const char *wildcard, uint8_t ignore_case);
/* Compare two paths with wildcard */
int32_t mz_path_resolve(const char *path, char *target, int32_t max_target);
/* Resolves path */
int32_t mz_path_remove_filename(char *path);
/* Remove the filename from a path */
int32_t mz_path_remove_extension(char *path);
/* Remove the extension from a path */
int32_t mz_path_get_filename(const char *path, const char **filename);
/* Get the filename from a path */
int32_t mz_dir_make(const char *path);
/* Creates a directory recursively */
int32_t mz_file_get_crc(const char *path, uint32_t *result_crc);
/* Gets the crc32 hash of a file */
/***************************************************************************/
/* Platform specific functions */
wchar_t *mz_os_unicode_string_create(const char *string, int32_t encoding);
/* Create unicode string from a utf8 string */
void mz_os_unicode_string_delete(wchar_t **string);
/* Delete a unicode string that was created */
uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding);
/* Create a utf8 string from a string with another encoding */
void mz_os_utf8_string_delete(uint8_t **string);
/* Delete a utf8 string that was created */
int32_t mz_os_rand(uint8_t *buf, int32_t size);
/* Random number generator (not cryptographically secure) */
int32_t mz_os_rename(const char *source_path, const char *target_path);
/* Rename a file */
int32_t mz_os_unlink(const char *path);
/* Delete an existing file */
int32_t mz_os_file_exists(const char *path);
/* Check to see if a file exists */
int64_t mz_os_get_file_size(const char *path);
/* Gets the length of a file */
int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date);
/* Gets a file's modified, access, and creation dates if supported */
int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date);
/* Sets a file's modified, access, and creation dates if supported */
int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes);
/* Gets a file's attributes */
int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes);
/* Sets a file's attributes */
int32_t mz_os_make_dir(const char *path);
/* Recursively creates a directory */
DIR* mz_os_open_dir(const char *path);
/* Opens a directory for listing */
struct
dirent* mz_os_read_dir(DIR *dir);
/* Reads a directory listing entry */
int32_t mz_os_close_dir(DIR *dir);
/* Closes a directory that has been opened for listing */
int32_t mz_os_is_dir(const char *path);
/* Checks to see if path is a directory */
int32_t mz_os_is_symlink(const char *path);
/* Checks to see if path is a symbolic link */
int32_t mz_os_make_symlink(const char *path, const char *target_path);
/* Creates a symbolic link pointing to a target */
int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path);
/* Gets the target path for a symbolic link */
uint64_t mz_os_ms_time(void);
/* Gets the time in milliseconds */
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

367
externals/minizip/mz_os_posix.c vendored Normal file
View File

@ -0,0 +1,367 @@
/* mz_os_posix.c -- System functions for posix
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_os.h"
#include <stdio.h> /* rename */
#include <errno.h>
#if defined(HAVE_ICONV)
#include <iconv.h>
#endif
#include <sys/types.h>
#include <sys/stat.h>
#ifndef _WIN32
# include <utime.h>
# include <unistd.h>
#endif
#if defined(__APPLE__)
# include <mach/clock.h>
# include <mach/mach.h>
#endif
#if defined(HAVE_GETRANDOM)
# include <sys/random.h>
#endif
#if defined(HAVE_LIBBSD)
# include <sys/types.h>
# ifndef __u_char_defined
typedef unsigned char u_char;
# endif
# include <bsd/stdlib.h> /* arc4random_buf */
#endif
/***************************************************************************/
#if defined(HAVE_ICONV)
uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding) {
iconv_t cd;
const char *from_encoding = NULL;
size_t result = 0;
size_t string_length = 0;
size_t string_utf8_size = 0;
uint8_t *string_utf8 = NULL;
uint8_t *string_utf8_ptr = NULL;
if (string == NULL)
return NULL;
if (encoding == MZ_ENCODING_CODEPAGE_437)
from_encoding = "CP437";
else if (encoding == MZ_ENCODING_CODEPAGE_932)
from_encoding = "CP932";
else if (encoding == MZ_ENCODING_CODEPAGE_936)
from_encoding = "CP936";
else if (encoding == MZ_ENCODING_CODEPAGE_950)
from_encoding = "CP950";
else if (encoding == MZ_ENCODING_UTF8)
from_encoding = "UTF-8";
else
return NULL;
cd = iconv_open("UTF-8", from_encoding);
if (cd == (iconv_t)-1)
return NULL;
string_length = strlen(string);
string_utf8_size = string_length * 2;
string_utf8 = (uint8_t *)MZ_ALLOC((int32_t)(string_utf8_size + 1));
string_utf8_ptr = string_utf8;
if (string_utf8) {
memset(string_utf8, 0, string_utf8_size + 1);
result = iconv(cd, (char **)&string, &string_length,
(char **)&string_utf8_ptr, &string_utf8_size);
}
iconv_close(cd);
if (result == (size_t)-1) {
MZ_FREE(string_utf8);
string_utf8 = NULL;
}
return string_utf8;
}
#else
uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding) {
size_t string_length = 0;
uint8_t *string_copy = NULL;
string_length = strlen(string);
string_copy = (uint8_t *)MZ_ALLOC((int32_t)(string_length + 1));
strncpy((char *)string_copy, string, string_length);
string_copy[string_length] = 0;
return string_copy;
}
#endif
void mz_os_utf8_string_delete(uint8_t **string) {
if (string != NULL) {
MZ_FREE(*string);
*string = NULL;
}
}
/***************************************************************************/
#if defined(HAVE_ARC4RANDOM_BUF)
int32_t mz_os_rand(uint8_t *buf, int32_t size) {
if (size < 0)
return 0;
arc4random_buf(buf, (uint32_t)size);
return size;
}
#elif defined(HAVE_ARC4RANDOM)
int32_t mz_os_rand(uint8_t *buf, int32_t size) {
int32_t left = size;
for (; left > 2; left -= 3, buf += 3) {
uint32_t val = arc4random();
buf[0] = (val) & 0xFF;
buf[1] = (val >> 8) & 0xFF;
buf[2] = (val >> 16) & 0xFF;
}
for (; left > 0; left--, buf++) {
*buf = arc4random() & 0xFF;
}
return size - left;
}
#elif defined(HAVE_GETRANDOM)
int32_t mz_os_rand(uint8_t *buf, int32_t size) {
int32_t left = size;
int32_t written = 0;
while (left > 0) {
written = getrandom(buf, left, 0);
if (written < 0)
return MZ_INTERNAL_ERROR;
buf += written;
left -= written;
}
return size - left;
}
#else
int32_t mz_os_rand(uint8_t *buf, int32_t size) {
static unsigned calls = 0;
int32_t i = 0;
/* Ensure different random header each time */
if (++calls == 1) {
#define PI_SEED 3141592654UL
srand((unsigned)(time(NULL) ^ PI_SEED));
}
while (i < size)
buf[i++] = (rand() >> 7) & 0xff;
return size;
}
#endif
int32_t mz_os_rename(const char *source_path, const char *target_path) {
if (rename(source_path, target_path) == -1)
return MZ_EXIST_ERROR;
return MZ_OK;
}
int32_t mz_os_unlink(const char *path) {
if (unlink(path) == -1)
return MZ_EXIST_ERROR;
return MZ_OK;
}
int32_t mz_os_file_exists(const char *path) {
struct stat path_stat;
memset(&path_stat, 0, sizeof(path_stat));
if (stat(path, &path_stat) == 0)
return MZ_OK;
return MZ_EXIST_ERROR;
}
int64_t mz_os_get_file_size(const char *path) {
struct stat path_stat;
memset(&path_stat, 0, sizeof(path_stat));
if (stat(path, &path_stat) == 0) {
/* Stat returns size taken up by directory entry, so return 0 */
if (S_ISDIR(path_stat.st_mode))
return 0;
return path_stat.st_size;
}
return 0;
}
int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date) {
struct stat path_stat;
char *name = NULL;
size_t len = 0;
int32_t err = MZ_INTERNAL_ERROR;
memset(&path_stat, 0, sizeof(path_stat));
if (strcmp(path, "-") != 0) {
/* Not all systems allow stat'ing a file with / appended */
len = strlen(path);
name = (char *)malloc(len + 1);
strncpy(name, path, len + 1);
mz_path_remove_slash(name);
if (stat(name, &path_stat) == 0) {
if (modified_date != NULL)
*modified_date = path_stat.st_mtime;
if (accessed_date != NULL)
*accessed_date = path_stat.st_atime;
/* Creation date not supported */
if (creation_date != NULL)
*creation_date = 0;
err = MZ_OK;
}
free(name);
}
return err;
}
int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date) {
struct utimbuf ut;
ut.actime = accessed_date;
ut.modtime = modified_date;
/* Creation date not supported */
MZ_UNUSED(creation_date);
if (utime(path, &ut) != 0)
return MZ_INTERNAL_ERROR;
return MZ_OK;
}
int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes) {
struct stat path_stat;
int32_t err = MZ_OK;
memset(&path_stat, 0, sizeof(path_stat));
if (lstat(path, &path_stat) == -1)
err = MZ_INTERNAL_ERROR;
*attributes = path_stat.st_mode;
return err;
}
int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes) {
int32_t err = MZ_OK;
if (chmod(path, (mode_t)attributes) == -1)
err = MZ_INTERNAL_ERROR;
return err;
}
int32_t mz_os_make_dir(const char *path) {
int32_t err = 0;
err = mkdir(path, 0755);
if (err != 0 && errno != EEXIST)
return MZ_INTERNAL_ERROR;
return MZ_OK;
}
DIR* mz_os_open_dir(const char *path) {
return opendir(path);
}
struct dirent* mz_os_read_dir(DIR *dir) {
if (dir == NULL)
return NULL;
return readdir(dir);
}
int32_t mz_os_close_dir(DIR *dir) {
if (dir == NULL)
return MZ_PARAM_ERROR;
if (closedir(dir) == -1)
return MZ_INTERNAL_ERROR;
return MZ_OK;
}
int32_t mz_os_is_dir(const char *path) {
struct stat path_stat;
memset(&path_stat, 0, sizeof(path_stat));
stat(path, &path_stat);
if (S_ISDIR(path_stat.st_mode))
return MZ_OK;
return MZ_EXIST_ERROR;
}
int32_t mz_os_is_symlink(const char *path) {
struct stat path_stat;
memset(&path_stat, 0, sizeof(path_stat));
lstat(path, &path_stat);
if (S_ISLNK(path_stat.st_mode))
return MZ_OK;
return MZ_EXIST_ERROR;
}
int32_t mz_os_make_symlink(const char *path, const char *target_path) {
if (symlink(target_path, path) != 0)
return MZ_INTERNAL_ERROR;
return MZ_OK;
}
int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path) {
size_t length = 0;
length = (size_t)readlink(path, target_path, max_target_path - 1);
if (length == (size_t)-1)
return MZ_EXIST_ERROR;
target_path[length] = 0;
return MZ_OK;
}
uint64_t mz_os_ms_time(void) {
struct timespec ts;
#if defined(__APPLE__)
clock_serv_t cclock;
mach_timespec_t mts;
host_get_clock_service(mach_host_self(), CALENDAR_CLOCK, &cclock);
clock_get_time(cclock, &mts);
mach_port_deallocate(mach_task_self(), cclock);
ts.tv_sec = mts.tv_sec;
ts.tv_nsec = mts.tv_nsec;
#else
clock_gettime(CLOCK_MONOTONIC, &ts);
#endif
return ((uint64_t)ts.tv_sec * 1000) + ((uint64_t)ts.tv_nsec / 1000000);
}

659
externals/minizip/mz_os_win32.c vendored Normal file
View File

@ -0,0 +1,659 @@
/* mz_os_win32.c -- System functions for Windows
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include "mz_strm_os.h"
#include <windows.h>
#include <winioctl.h>
/***************************************************************************/
#if defined(WINAPI_FAMILY_PARTITION) && (!(defined(MZ_WINRT_API)))
# if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# define MZ_WINRT_API 1
# endif
#endif
#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
# define SYMBOLIC_LINK_FLAG_DIRECTORY 0x1
#endif
/***************************************************************************/
typedef struct DIR_int_s {
void *find_handle;
WIN32_FIND_DATAW find_data;
struct dirent entry;
uint8_t end;
} DIR_int;
/***************************************************************************/
wchar_t *mz_os_unicode_string_create(const char *string, int32_t encoding) {
wchar_t *string_wide = NULL;
uint32_t string_wide_size = 0;
string_wide_size = MultiByteToWideChar(encoding, 0, string, -1, NULL, 0);
if (string_wide_size == 0)
return NULL;
string_wide = (wchar_t *)MZ_ALLOC((string_wide_size + 1) * sizeof(wchar_t));
if (string_wide == NULL)
return NULL;
memset(string_wide, 0, sizeof(wchar_t) * (string_wide_size + 1));
MultiByteToWideChar(encoding, 0, string, -1, string_wide, string_wide_size);
return string_wide;
}
void mz_os_unicode_string_delete(wchar_t **string) {
if (string != NULL) {
MZ_FREE(*string);
*string = NULL;
}
}
uint8_t *mz_os_utf8_string_create(const char *string, int32_t encoding) {
wchar_t *string_wide = NULL;
uint8_t *string_utf8 = NULL;
uint32_t string_utf8_size = 0;
string_wide = mz_os_unicode_string_create(string, encoding);
if (string_wide) {
string_utf8_size = WideCharToMultiByte(CP_UTF8, 0, string_wide, -1, NULL, 0, NULL, NULL);
string_utf8 = (uint8_t *)MZ_ALLOC((string_utf8_size + 1) * sizeof(wchar_t));
if (string_utf8) {
memset(string_utf8, 0, string_utf8_size + 1);
WideCharToMultiByte(CP_UTF8, 0, string_wide, -1, (char *)string_utf8, string_utf8_size, NULL, NULL);
}
mz_os_unicode_string_delete(&string_wide);
}
return string_utf8;
}
uint8_t *mz_os_utf8_string_create_from_unicode(const wchar_t *string, int32_t encoding) {
uint8_t *string_utf8 = NULL;
uint32_t string_utf8_size = 0;
MZ_UNUSED(encoding);
string_utf8_size = WideCharToMultiByte(CP_UTF8, 0, string, -1, NULL, 0, NULL, NULL);
string_utf8 = (uint8_t *)MZ_ALLOC((string_utf8_size + 1) * sizeof(wchar_t));
if (string_utf8) {
memset(string_utf8, 0, string_utf8_size + 1);
WideCharToMultiByte(CP_UTF8, 0, string, -1, (char *)string_utf8, string_utf8_size, NULL, NULL);
}
return string_utf8;
}
void mz_os_utf8_string_delete(uint8_t **string) {
if (string != NULL) {
MZ_FREE(*string);
*string = NULL;
}
}
/***************************************************************************/
int32_t mz_os_rand(uint8_t *buf, int32_t size) {
unsigned __int64 pentium_tsc[1];
int32_t len = 0;
for (len = 0; len < (int)size; len += 1) {
if (len % 8 == 0)
QueryPerformanceCounter((LARGE_INTEGER *)pentium_tsc);
buf[len] = ((unsigned char*)pentium_tsc)[len % 8];
}
return len;
}
int32_t mz_os_rename(const char *source_path, const char *target_path) {
wchar_t *source_path_wide = NULL;
wchar_t *target_path_wide = NULL;
int32_t result = 0;
int32_t err = MZ_OK;
if (source_path == NULL || target_path == NULL)
return MZ_PARAM_ERROR;
source_path_wide = mz_os_unicode_string_create(source_path, MZ_ENCODING_UTF8);
if (source_path_wide == NULL) {
err = MZ_PARAM_ERROR;
} else {
target_path_wide = mz_os_unicode_string_create(target_path, MZ_ENCODING_UTF8);
if (target_path_wide == NULL)
err = MZ_PARAM_ERROR;
}
if (err == MZ_OK) {
#ifdef MZ_WINRT_API
result = MoveFileExW(source_path_wide, target_path_wide, MOVEFILE_WRITE_THROUGH);
#else
result = MoveFileW(source_path_wide, target_path_wide);
#endif
if (result == 0)
err = MZ_EXIST_ERROR;
}
if (target_path_wide)
mz_os_unicode_string_delete(&target_path_wide);
if (source_path_wide)
mz_os_unicode_string_delete(&source_path_wide);
return err;
}
int32_t mz_os_unlink(const char *path) {
wchar_t *path_wide = NULL;
int32_t result = 0;
if (path == NULL)
return MZ_PARAM_ERROR;
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
if (mz_os_is_dir(path) == MZ_OK)
result = RemoveDirectoryW(path_wide);
else
result = DeleteFileW(path_wide);
mz_os_unicode_string_delete(&path_wide);
if (result == 0)
return MZ_EXIST_ERROR;
return MZ_OK;
}
int32_t mz_os_file_exists(const char *path) {
wchar_t *path_wide = NULL;
DWORD attribs = 0;
if (path == NULL)
return MZ_PARAM_ERROR;
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
attribs = GetFileAttributesW(path_wide);
mz_os_unicode_string_delete(&path_wide);
if (attribs == 0xFFFFFFFF)
return MZ_EXIST_ERROR;
return MZ_OK;
}
int64_t mz_os_get_file_size(const char *path) {
HANDLE handle = NULL;
LARGE_INTEGER large_size;
wchar_t *path_wide = NULL;
if (path == NULL)
return MZ_PARAM_ERROR;
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
#ifdef MZ_WINRT_API
handle = CreateFile2(path_wide, GENERIC_READ, 0, OPEN_EXISTING, NULL);
#else
handle = CreateFileW(path_wide, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
#endif
mz_os_unicode_string_delete(&path_wide);
large_size.QuadPart = 0;
if (handle != INVALID_HANDLE_VALUE) {
GetFileSizeEx(handle, &large_size);
CloseHandle(handle);
}
return large_size.QuadPart;
}
static void mz_os_file_to_unix_time(FILETIME file_time, time_t *unix_time) {
uint64_t quad_file_time = 0;
quad_file_time = file_time.dwLowDateTime;
quad_file_time |= ((uint64_t)file_time.dwHighDateTime << 32);
*unix_time = (time_t)((quad_file_time - 116444736000000000LL) / 10000000);
}
static void mz_os_unix_to_file_time(time_t unix_time, FILETIME *file_time) {
uint64_t quad_file_time = 0;
quad_file_time = ((uint64_t)unix_time * 10000000) + 116444736000000000LL;
file_time->dwHighDateTime = (quad_file_time >> 32);
file_time->dwLowDateTime = (uint32_t)(quad_file_time);
}
int32_t mz_os_get_file_date(const char *path, time_t *modified_date, time_t *accessed_date, time_t *creation_date) {
WIN32_FIND_DATAW ff32;
HANDLE handle = NULL;
wchar_t *path_wide = NULL;
int32_t err = MZ_INTERNAL_ERROR;
if (path == NULL)
return MZ_PARAM_ERROR;
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
handle = FindFirstFileW(path_wide, &ff32);
MZ_FREE(path_wide);
if (handle != INVALID_HANDLE_VALUE) {
if (modified_date != NULL)
mz_os_file_to_unix_time(ff32.ftLastWriteTime, modified_date);
if (accessed_date != NULL)
mz_os_file_to_unix_time(ff32.ftLastAccessTime, accessed_date);
if (creation_date != NULL)
mz_os_file_to_unix_time(ff32.ftCreationTime, creation_date);
FindClose(handle);
err = MZ_OK;
}
return err;
}
int32_t mz_os_set_file_date(const char *path, time_t modified_date, time_t accessed_date, time_t creation_date) {
HANDLE handle = NULL;
FILETIME ftm_creation, ftm_accessed, ftm_modified;
wchar_t *path_wide = NULL;
int32_t err = MZ_OK;
if (path == NULL)
return MZ_PARAM_ERROR;
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
#ifdef MZ_WINRT_API
handle = CreateFile2(path_wide, GENERIC_READ | GENERIC_WRITE, 0, OPEN_EXISTING, NULL);
#else
handle = CreateFileW(path_wide, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
#endif
mz_os_unicode_string_delete(&path_wide);
if (handle != INVALID_HANDLE_VALUE) {
GetFileTime(handle, &ftm_creation, &ftm_accessed, &ftm_modified);
if (modified_date != 0)
mz_os_unix_to_file_time(modified_date, &ftm_modified);
if (accessed_date != 0)
mz_os_unix_to_file_time(accessed_date, &ftm_accessed);
if (creation_date != 0)
mz_os_unix_to_file_time(creation_date, &ftm_creation);
if (SetFileTime(handle, &ftm_creation, &ftm_accessed, &ftm_modified) == 0)
err = MZ_INTERNAL_ERROR;
CloseHandle(handle);
}
return err;
}
int32_t mz_os_get_file_attribs(const char *path, uint32_t *attributes) {
wchar_t *path_wide = NULL;
int32_t err = MZ_OK;
if (path == NULL || attributes == NULL)
return MZ_PARAM_ERROR;
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
*attributes = GetFileAttributesW(path_wide);
mz_os_unicode_string_delete(&path_wide);
if (*attributes == INVALID_FILE_ATTRIBUTES)
err = MZ_INTERNAL_ERROR;
return err;
}
int32_t mz_os_set_file_attribs(const char *path, uint32_t attributes) {
wchar_t *path_wide = NULL;
int32_t err = MZ_OK;
if (path == NULL)
return MZ_PARAM_ERROR;
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
if (SetFileAttributesW(path_wide, attributes) == 0)
err = MZ_INTERNAL_ERROR;
mz_os_unicode_string_delete(&path_wide);
return err;
}
int32_t mz_os_make_dir(const char *path) {
wchar_t *path_wide = NULL;
int32_t err = MZ_OK;
if (path == NULL)
return MZ_PARAM_ERROR;
/* Don't try to create a drive letter */
if ((path[0] != 0) && (strlen(path) <= 3) && (path[1] == ':'))
return mz_os_is_dir(path);
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
if (CreateDirectoryW(path_wide, NULL) == 0) {
if (GetLastError() != ERROR_ALREADY_EXISTS)
err = MZ_INTERNAL_ERROR;
}
mz_os_unicode_string_delete(&path_wide);
return err;
}
DIR *mz_os_open_dir(const char *path) {
WIN32_FIND_DATAW find_data;
DIR_int *dir_int = NULL;
wchar_t *path_wide = NULL;
char fixed_path[320];
void *handle = NULL;
if (path == NULL)
return NULL;
strncpy(fixed_path, path, sizeof(fixed_path) - 1);
fixed_path[sizeof(fixed_path) - 1] = 0;
mz_path_append_slash(fixed_path, sizeof(fixed_path), MZ_PATH_SLASH_PLATFORM);
mz_path_combine(fixed_path, "*", sizeof(fixed_path));
path_wide = mz_os_unicode_string_create(fixed_path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return NULL;
handle = FindFirstFileW(path_wide, &find_data);
mz_os_unicode_string_delete(&path_wide);
if (handle == INVALID_HANDLE_VALUE)
return NULL;
dir_int = (DIR_int *)MZ_ALLOC(sizeof(DIR_int));
if (dir_int == NULL)
return NULL;
dir_int->find_handle = handle;
dir_int->end = 0;
memcpy(&dir_int->find_data, &find_data, sizeof(dir_int->find_data));
return (DIR *)dir_int;
}
struct dirent* mz_os_read_dir(DIR *dir) {
DIR_int *dir_int;
if (dir == NULL)
return NULL;
dir_int = (DIR_int *)dir;
if (dir_int->end)
return NULL;
WideCharToMultiByte(CP_UTF8, 0, dir_int->find_data.cFileName, -1,
dir_int->entry.d_name, sizeof(dir_int->entry.d_name), NULL, NULL);
if (FindNextFileW(dir_int->find_handle, &dir_int->find_data) == 0) {
if (GetLastError() != ERROR_NO_MORE_FILES)
return NULL;
dir_int->end = 1;
}
return &dir_int->entry;
}
int32_t mz_os_close_dir(DIR *dir) {
DIR_int *dir_int;
if (dir == NULL)
return MZ_PARAM_ERROR;
dir_int = (DIR_int *)dir;
if (dir_int->find_handle != INVALID_HANDLE_VALUE)
FindClose(dir_int->find_handle);
MZ_FREE(dir_int);
return MZ_OK;
}
int32_t mz_os_is_dir(const char *path) {
wchar_t *path_wide = NULL;
uint32_t attribs = 0;
if (path == NULL)
return MZ_PARAM_ERROR;
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
attribs = GetFileAttributesW(path_wide);
mz_os_unicode_string_delete(&path_wide);
if (attribs != 0xFFFFFFFF) {
if (attribs & FILE_ATTRIBUTE_DIRECTORY)
return MZ_OK;
}
return MZ_EXIST_ERROR;
}
int32_t mz_os_is_symlink(const char *path) {
wchar_t *path_wide = NULL;
uint32_t attribs = 0;
if (path == NULL)
return MZ_PARAM_ERROR;
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
attribs = GetFileAttributesW(path_wide);
mz_os_unicode_string_delete(&path_wide);
if (attribs != 0xFFFFFFFF) {
if (attribs & FILE_ATTRIBUTE_REPARSE_POINT)
return MZ_OK;
}
return MZ_EXIST_ERROR;
}
int32_t mz_os_make_symlink(const char *path, const char *target_path) {
typedef BOOLEAN (WINAPI *LPCREATESYMBOLICLINKW)(LPCWSTR, LPCWSTR, DWORD);
LPCREATESYMBOLICLINKW create_symbolic_link_w = NULL;
HMODULE kernel32_mod = NULL;
wchar_t *path_wide = NULL;
wchar_t *target_path_wide = NULL;
int32_t err = MZ_OK;
int32_t flags = 0;
if (path == NULL)
return MZ_PARAM_ERROR;
#ifdef MZ_WINRT_API
MEMORY_BASIC_INFORMATION mbi;
memset(&mbi, 0, sizeof(mbi));
VirtualQuery(VirtualQuery, &mbi, sizeof(mbi));
kernel32_mod = (HMODULE)mbi.AllocationBase;
#else
kernel32_mod = GetModuleHandleW(L"kernel32.dll");
#endif
if (kernel32_mod == NULL)
return MZ_SUPPORT_ERROR;
create_symbolic_link_w = (LPCREATESYMBOLICLINKW)GetProcAddress(kernel32_mod, "CreateSymbolicLinkW");
if (create_symbolic_link_w == NULL) {
return MZ_SUPPORT_ERROR;
}
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL) {
return MZ_PARAM_ERROR;
}
target_path_wide = mz_os_unicode_string_create(target_path, MZ_ENCODING_UTF8);
if (target_path_wide != NULL) {
if (mz_path_has_slash(target_path) == MZ_OK)
flags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
if (create_symbolic_link_w(path_wide, target_path_wide, flags) == FALSE)
err = MZ_SYMLINK_ERROR;
mz_os_unicode_string_delete(&target_path_wide);
} else {
err = MZ_PARAM_ERROR;
}
mz_os_unicode_string_delete(&path_wide);
return err;
}
int32_t mz_os_read_symlink(const char *path, char *target_path, int32_t max_target_path) {
typedef struct _REPARSE_DATA_BUFFER {
ULONG ReparseTag;
USHORT ReparseDataLength;
USHORT Reserved;
union {
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
ULONG Flags;
WCHAR PathBuffer[1];
} SymbolicLinkReparseBuffer;
struct {
USHORT SubstituteNameOffset;
USHORT SubstituteNameLength;
USHORT PrintNameOffset;
USHORT PrintNameLength;
WCHAR PathBuffer[1];
} MountPointReparseBuffer;
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
};
} REPARSE_DATA_BUFFER;
REPARSE_DATA_BUFFER *reparse_data = NULL;
DWORD length = 0;
HANDLE handle = NULL;
wchar_t *path_wide = NULL;
wchar_t *target_path_wide = NULL;
uint8_t buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
int32_t target_path_len = 0;
int32_t target_path_idx = 0;
int32_t err = MZ_OK;
uint8_t *target_path_utf8 = NULL;
if (path == NULL)
return MZ_PARAM_ERROR;
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
#ifdef MZ_WINRT_API
CREATEFILE2_EXTENDED_PARAMETERS extended_params;
memset(&extended_params, 0, sizeof(extended_params));
extended_params.dwSize = sizeof(extended_params);
extended_params.dwFileAttributes = FILE_ATTRIBUTE_NORMAL;
extended_params.dwFileFlags = FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT;
extended_params.dwSecurityQosFlags = SECURITY_ANONYMOUS;
extended_params.lpSecurityAttributes = NULL;
extended_params.hTemplateFile = NULL;
handle = CreateFile2(path_wide, FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE, OPEN_EXISTING, &extended_params);
#else
handle = CreateFileW(path_wide, FILE_READ_EA, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL);
#endif
if (handle == INVALID_HANDLE_VALUE) {
mz_os_unicode_string_delete(&path_wide);
return MZ_OPEN_ERROR;
}
if (DeviceIoControl(handle, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, sizeof(buffer), &length, NULL) == TRUE) {
reparse_data = (REPARSE_DATA_BUFFER *)buffer;
if ((IsReparseTagMicrosoft(reparse_data->ReparseTag)) &&
(reparse_data->ReparseTag == IO_REPARSE_TAG_SYMLINK)) {
target_path_len = max_target_path * sizeof(wchar_t);
if (target_path_len > reparse_data->SymbolicLinkReparseBuffer.PrintNameLength)
target_path_len = reparse_data->SymbolicLinkReparseBuffer.PrintNameLength;
target_path_wide = (wchar_t *)MZ_ALLOC(target_path_len + sizeof(wchar_t));
if (target_path_wide) {
target_path_idx = reparse_data->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(wchar_t);
memcpy(target_path_wide, &reparse_data->SymbolicLinkReparseBuffer.PathBuffer[target_path_idx],
target_path_len);
target_path_wide[target_path_len / sizeof(wchar_t)] = 0;
target_path_utf8 = mz_os_utf8_string_create_from_unicode(target_path_wide, MZ_ENCODING_UTF8);
if (target_path_utf8) {
strncpy(target_path, (const char *)target_path_utf8, max_target_path - 1);
target_path[max_target_path - 1] = 0;
/* Ensure directories have slash at the end so we can recreate them later */
if (mz_os_is_dir((const char *)target_path_utf8) == MZ_OK)
mz_path_append_slash(target_path, max_target_path, MZ_PATH_SLASH_PLATFORM);
mz_os_utf8_string_delete(&target_path_utf8);
} else {
err = MZ_MEM_ERROR;
}
MZ_FREE(target_path_wide);
} else {
err = MZ_MEM_ERROR;
}
}
} else {
err = MZ_INTERNAL_ERROR;
}
CloseHandle(handle);
mz_os_unicode_string_delete(&path_wide);
return err;
}
uint64_t mz_os_ms_time(void) {
SYSTEMTIME system_time;
FILETIME file_time;
uint64_t quad_file_time = 0;
GetSystemTime(&system_time);
SystemTimeToFileTime(&system_time, &file_time);
quad_file_time = file_time.dwLowDateTime;
quad_file_time |= ((uint64_t)file_time.dwHighDateTime << 32);
return quad_file_time / 10000 - 11644473600000LL;
}

560
externals/minizip/mz_strm.c vendored Normal file
View File

@ -0,0 +1,560 @@
/* mz_strm.c -- Stream interface
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
/***************************************************************************/
#define MZ_STREAM_FIND_SIZE (1024)
/***************************************************************************/
int32_t mz_stream_open(void *stream, const char *path, int32_t mode) {
mz_stream *strm = (mz_stream *)stream;
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->open == NULL)
return MZ_STREAM_ERROR;
return strm->vtbl->open(strm, path, mode);
}
int32_t mz_stream_is_open(void *stream) {
mz_stream *strm = (mz_stream *)stream;
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->is_open == NULL)
return MZ_STREAM_ERROR;
return strm->vtbl->is_open(strm);
}
int32_t mz_stream_read(void *stream, void *buf, int32_t size) {
mz_stream *strm = (mz_stream *)stream;
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->read == NULL)
return MZ_PARAM_ERROR;
if (mz_stream_is_open(stream) != MZ_OK)
return MZ_STREAM_ERROR;
return strm->vtbl->read(strm, buf, size);
}
static int32_t mz_stream_read_value(void *stream, uint64_t *value, int32_t len) {
uint8_t buf[8];
int32_t n = 0;
int32_t i = 0;
*value = 0;
if (mz_stream_read(stream, buf, len) == len) {
for (n = 0; n < len; n += 1, i += 8)
*value += ((uint64_t)buf[n]) << i;
} else if (mz_stream_error(stream))
return MZ_STREAM_ERROR;
else
return MZ_END_OF_STREAM;
return MZ_OK;
}
int32_t mz_stream_read_uint8(void *stream, uint8_t *value) {
int32_t err = MZ_OK;
uint64_t value64 = 0;
*value = 0;
err = mz_stream_read_value(stream, &value64, sizeof(uint8_t));
if (err == MZ_OK)
*value = (uint8_t)value64;
return err;
}
int32_t mz_stream_read_uint16(void *stream, uint16_t *value) {
int32_t err = MZ_OK;
uint64_t value64 = 0;
*value = 0;
err = mz_stream_read_value(stream, &value64, sizeof(uint16_t));
if (err == MZ_OK)
*value = (uint16_t)value64;
return err;
}
int32_t mz_stream_read_uint32(void *stream, uint32_t *value) {
int32_t err = MZ_OK;
uint64_t value64 = 0;
*value = 0;
err = mz_stream_read_value(stream, &value64, sizeof(uint32_t));
if (err == MZ_OK)
*value = (uint32_t)value64;
return err;
}
int32_t mz_stream_read_int64(void *stream, int64_t *value) {
return mz_stream_read_value(stream, (uint64_t *)value, sizeof(uint64_t));
}
int32_t mz_stream_read_uint64(void *stream, uint64_t *value) {
return mz_stream_read_value(stream, value, sizeof(uint64_t));
}
int32_t mz_stream_write(void *stream, const void *buf, int32_t size) {
mz_stream *strm = (mz_stream *)stream;
if (size == 0)
return size;
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->write == NULL)
return MZ_PARAM_ERROR;
if (mz_stream_is_open(stream) != MZ_OK)
return MZ_STREAM_ERROR;
return strm->vtbl->write(strm, buf, size);
}
static int32_t mz_stream_write_value(void *stream, uint64_t value, int32_t len) {
uint8_t buf[8];
int32_t n = 0;
for (n = 0; n < len; n += 1) {
buf[n] = (uint8_t)(value & 0xff);
value >>= 8;
}
if (value != 0) {
/* Data overflow - hack for ZIP64 (X Roche) */
for (n = 0; n < len; n += 1)
buf[n] = 0xff;
}
if (mz_stream_write(stream, buf, len) != len)
return MZ_STREAM_ERROR;
return MZ_OK;
}
int32_t mz_stream_write_uint8(void *stream, uint8_t value) {
return mz_stream_write_value(stream, value, sizeof(uint8_t));
}
int32_t mz_stream_write_uint16(void *stream, uint16_t value) {
return mz_stream_write_value(stream, value, sizeof(uint16_t));
}
int32_t mz_stream_write_uint32(void *stream, uint32_t value) {
return mz_stream_write_value(stream, value, sizeof(uint32_t));
}
int32_t mz_stream_write_int64(void *stream, int64_t value) {
return mz_stream_write_value(stream, (uint64_t)value, sizeof(uint64_t));
}
int32_t mz_stream_write_uint64(void *stream, uint64_t value) {
return mz_stream_write_value(stream, value, sizeof(uint64_t));
}
int32_t mz_stream_copy(void *target, void *source, int32_t len) {
return mz_stream_copy_stream(target, NULL, source, NULL, len);
}
int32_t mz_stream_copy_to_end(void *target, void *source) {
return mz_stream_copy_stream_to_end(target, NULL, source, NULL);
}
int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source,
mz_stream_read_cb read_cb, int32_t len) {
uint8_t buf[16384];
int32_t bytes_to_copy = 0;
int32_t read = 0;
int32_t written = 0;
if (write_cb == NULL)
write_cb = mz_stream_write;
if (read_cb == NULL)
read_cb = mz_stream_read;
while (len > 0) {
bytes_to_copy = len;
if (bytes_to_copy > (int32_t)sizeof(buf))
bytes_to_copy = sizeof(buf);
read = read_cb(source, buf, bytes_to_copy);
if (read <= 0)
return MZ_STREAM_ERROR;
written = write_cb(target, buf, read);
if (written != read)
return MZ_STREAM_ERROR;
len -= read;
}
return MZ_OK;
}
int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source,
mz_stream_read_cb read_cb) {
uint8_t buf[16384];
int32_t read = 0;
int32_t written = 0;
if (write_cb == NULL)
write_cb = mz_stream_write;
if (read_cb == NULL)
read_cb = mz_stream_read;
read = read_cb(source, buf, sizeof(buf));
while (read > 0) {
written = write_cb(target, buf, read);
if (written != read)
return MZ_STREAM_ERROR;
read = read_cb(source, buf, sizeof(buf));
}
if (read < 0)
return MZ_STREAM_ERROR;
return MZ_OK;
}
int64_t mz_stream_tell(void *stream) {
mz_stream *strm = (mz_stream *)stream;
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->tell == NULL)
return MZ_PARAM_ERROR;
if (mz_stream_is_open(stream) != MZ_OK)
return MZ_STREAM_ERROR;
return strm->vtbl->tell(strm);
}
int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream *strm = (mz_stream *)stream;
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->seek == NULL)
return MZ_PARAM_ERROR;
if (mz_stream_is_open(stream) != MZ_OK)
return MZ_STREAM_ERROR;
if (origin == MZ_SEEK_SET && offset < 0)
return MZ_SEEK_ERROR;
return strm->vtbl->seek(strm, offset, origin);
}
int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position) {
uint8_t buf[MZ_STREAM_FIND_SIZE];
int32_t buf_pos = 0;
int32_t read_size = sizeof(buf);
int32_t read = 0;
int64_t read_pos = 0;
int64_t start_pos = 0;
int64_t disk_pos = 0;
int32_t i = 0;
uint8_t first = 1;
int32_t err = MZ_OK;
if (stream == NULL || find == NULL || position == NULL)
return MZ_PARAM_ERROR;
if (find_size < 0 || find_size >= (int32_t)sizeof(buf))
return MZ_PARAM_ERROR;
*position = -1;
start_pos = mz_stream_tell(stream);
while (read_pos < max_seek) {
if (read_size > (int32_t)(max_seek - read_pos - buf_pos) && (max_seek - read_pos - buf_pos) < (int64_t)sizeof(buf))
read_size = (int32_t)(max_seek - read_pos - buf_pos);
read = mz_stream_read(stream, buf + buf_pos, read_size);
if ((read <= 0) || (read + buf_pos < find_size))
break;
for (i = 0; i <= read + buf_pos - find_size; i += 1) {
if (memcmp(&buf[i], find, find_size) != 0)
continue;
disk_pos = mz_stream_tell(stream);
/* Seek to position on disk where the data was found */
err = mz_stream_seek(stream, disk_pos - ((int64_t)read + buf_pos - i), MZ_SEEK_SET);
if (err != MZ_OK)
return MZ_EXIST_ERROR;
*position = start_pos + read_pos + i;
return MZ_OK;
}
if (first) {
read -= find_size;
read_size -= find_size;
buf_pos = find_size;
first = 0;
}
memmove(buf, buf + read, find_size);
read_pos += read;
}
return MZ_EXIST_ERROR;
}
int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position) {
uint8_t buf[MZ_STREAM_FIND_SIZE];
int32_t buf_pos = 0;
int32_t read_size = MZ_STREAM_FIND_SIZE;
int64_t read_pos = 0;
int32_t read = 0;
int64_t start_pos = 0;
int64_t disk_pos = 0;
uint8_t first = 1;
int32_t i = 0;
int32_t err = MZ_OK;
if (stream == NULL || find == NULL || position == NULL)
return MZ_PARAM_ERROR;
if (find_size < 0 || find_size >= (int32_t)sizeof(buf))
return MZ_PARAM_ERROR;
*position = -1;
start_pos = mz_stream_tell(stream);
while (read_pos < max_seek) {
if (read_size > (int32_t)(max_seek - read_pos) && (max_seek - read_pos) < (int64_t)sizeof(buf))
read_size = (int32_t)(max_seek - read_pos);
if (mz_stream_seek(stream, start_pos - (read_pos + read_size), MZ_SEEK_SET) != MZ_OK)
break;
read = mz_stream_read(stream, buf, read_size);
if ((read <= 0) || (read + buf_pos < find_size))
break;
if (read + buf_pos < MZ_STREAM_FIND_SIZE)
memmove(buf + MZ_STREAM_FIND_SIZE - (read + buf_pos), buf, read);
for (i = find_size; i <= (read + buf_pos); i += 1) {
if (memcmp(&buf[MZ_STREAM_FIND_SIZE - i], find, find_size) != 0)
continue;
disk_pos = mz_stream_tell(stream);
/* Seek to position on disk where the data was found */
err = mz_stream_seek(stream, disk_pos + buf_pos - i, MZ_SEEK_SET);
if (err != MZ_OK)
return MZ_EXIST_ERROR;
*position = start_pos - (read_pos - buf_pos + i);
return MZ_OK;
}
if (first) {
read -= find_size;
read_size -= find_size;
buf_pos = find_size;
first = 0;
}
if (read == 0)
break;
memmove(buf + read_size, buf, find_size);
read_pos += read;
}
return MZ_EXIST_ERROR;
}
int32_t mz_stream_close(void *stream) {
mz_stream *strm = (mz_stream *)stream;
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->close == NULL)
return MZ_PARAM_ERROR;
if (mz_stream_is_open(stream) != MZ_OK)
return MZ_STREAM_ERROR;
return strm->vtbl->close(strm);
}
int32_t mz_stream_error(void *stream) {
mz_stream *strm = (mz_stream *)stream;
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->error == NULL)
return MZ_PARAM_ERROR;
return strm->vtbl->error(strm);
}
int32_t mz_stream_set_base(void *stream, void *base) {
mz_stream *strm = (mz_stream *)stream;
strm->base = (mz_stream *)base;
return MZ_OK;
}
void* mz_stream_get_interface(void *stream) {
mz_stream *strm = (mz_stream *)stream;
if (strm == NULL || strm->vtbl == NULL)
return NULL;
return (void *)strm->vtbl;
}
int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream *strm = (mz_stream *)stream;
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->get_prop_int64 == NULL)
return MZ_PARAM_ERROR;
return strm->vtbl->get_prop_int64(stream, prop, value);
}
int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream *strm = (mz_stream *)stream;
if (strm == NULL || strm->vtbl == NULL || strm->vtbl->set_prop_int64 == NULL)
return MZ_PARAM_ERROR;
return strm->vtbl->set_prop_int64(stream, prop, value);
}
void *mz_stream_create(void **stream, mz_stream_vtbl *vtbl) {
if (stream == NULL)
return NULL;
if (vtbl == NULL || vtbl->create == NULL)
return NULL;
return vtbl->create(stream);
}
void mz_stream_delete(void **stream) {
mz_stream *strm = NULL;
if (stream == NULL)
return;
strm = (mz_stream *)*stream;
if (strm != NULL && strm->vtbl != NULL && strm->vtbl->destroy != NULL)
strm->vtbl->destroy(stream);
*stream = NULL;
}
/***************************************************************************/
typedef struct mz_stream_raw_s {
mz_stream stream;
int64_t total_in;
int64_t total_out;
int64_t max_total_in;
} mz_stream_raw;
/***************************************************************************/
int32_t mz_stream_raw_open(void *stream, const char *path, int32_t mode) {
MZ_UNUSED(stream);
MZ_UNUSED(path);
MZ_UNUSED(mode);
return MZ_OK;
}
int32_t mz_stream_raw_is_open(void *stream) {
mz_stream_raw *raw = (mz_stream_raw *)stream;
return mz_stream_is_open(raw->stream.base);
}
int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size) {
mz_stream_raw *raw = (mz_stream_raw *)stream;
int32_t bytes_to_read = size;
int32_t read = 0;
if (raw->max_total_in > 0) {
if ((int64_t)bytes_to_read > (raw->max_total_in - raw->total_in))
bytes_to_read = (int32_t)(raw->max_total_in - raw->total_in);
}
read = mz_stream_read(raw->stream.base, buf, bytes_to_read);
if (read > 0) {
raw->total_in += read;
raw->total_out += read;
}
return read;
}
int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size) {
mz_stream_raw *raw = (mz_stream_raw *)stream;
int32_t written = 0;
written = mz_stream_write(raw->stream.base, buf, size);
if (written > 0) {
raw->total_out += written;
raw->total_in += written;
}
return written;
}
int64_t mz_stream_raw_tell(void *stream) {
mz_stream_raw *raw = (mz_stream_raw *)stream;
return mz_stream_tell(raw->stream.base);
}
int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_raw *raw = (mz_stream_raw *)stream;
return mz_stream_seek(raw->stream.base, offset, origin);
}
int32_t mz_stream_raw_close(void *stream) {
MZ_UNUSED(stream);
return MZ_OK;
}
int32_t mz_stream_raw_error(void *stream) {
mz_stream_raw *raw = (mz_stream_raw *)stream;
return mz_stream_error(raw->stream.base);
}
int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_raw *raw = (mz_stream_raw *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = raw->total_in;
return MZ_OK;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = raw->total_out;
return MZ_OK;
}
return MZ_EXIST_ERROR;
}
int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_raw *raw = (mz_stream_raw *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN_MAX:
raw->max_total_in = value;
return MZ_OK;
}
return MZ_EXIST_ERROR;
}
/***************************************************************************/
static mz_stream_vtbl mz_stream_raw_vtbl = {
mz_stream_raw_open,
mz_stream_raw_is_open,
mz_stream_raw_read,
mz_stream_raw_write,
mz_stream_raw_tell,
mz_stream_raw_seek,
mz_stream_raw_close,
mz_stream_raw_error,
mz_stream_raw_create,
mz_stream_raw_delete,
mz_stream_raw_get_prop_int64,
mz_stream_raw_set_prop_int64
};
/***************************************************************************/
void *mz_stream_raw_create(void **stream) {
mz_stream_raw *raw = NULL;
raw = (mz_stream_raw *)MZ_ALLOC(sizeof(mz_stream_raw));
if (raw != NULL) {
memset(raw, 0, sizeof(mz_stream_raw));
raw->stream.vtbl = &mz_stream_raw_vtbl;
}
if (stream != NULL)
*stream = raw;
return raw;
}
void mz_stream_raw_delete(void **stream) {
mz_stream_raw *raw = NULL;
if (stream == NULL)
return;
raw = (mz_stream_raw *)*stream;
if (raw != NULL)
MZ_FREE(raw);
*stream = NULL;
}

132
externals/minizip/mz_strm.h vendored Normal file
View File

@ -0,0 +1,132 @@
/* mz_strm.h -- Stream interface
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_H
#define MZ_STREAM_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
#define MZ_STREAM_PROP_TOTAL_IN (1)
#define MZ_STREAM_PROP_TOTAL_IN_MAX (2)
#define MZ_STREAM_PROP_TOTAL_OUT (3)
#define MZ_STREAM_PROP_TOTAL_OUT_MAX (4)
#define MZ_STREAM_PROP_HEADER_SIZE (5)
#define MZ_STREAM_PROP_FOOTER_SIZE (6)
#define MZ_STREAM_PROP_DISK_SIZE (7)
#define MZ_STREAM_PROP_DISK_NUMBER (8)
#define MZ_STREAM_PROP_COMPRESS_LEVEL (9)
#define MZ_STREAM_PROP_COMPRESS_METHOD (10)
#define MZ_STREAM_PROP_COMPRESS_WINDOW (11)
/***************************************************************************/
typedef int32_t (*mz_stream_open_cb) (void *stream, const char *path, int32_t mode);
typedef int32_t (*mz_stream_is_open_cb) (void *stream);
typedef int32_t (*mz_stream_read_cb) (void *stream, void *buf, int32_t size);
typedef int32_t (*mz_stream_write_cb) (void *stream, const void *buf, int32_t size);
typedef int64_t (*mz_stream_tell_cb) (void *stream);
typedef int32_t (*mz_stream_seek_cb) (void *stream, int64_t offset, int32_t origin);
typedef int32_t (*mz_stream_close_cb) (void *stream);
typedef int32_t (*mz_stream_error_cb) (void *stream);
typedef void* (*mz_stream_create_cb) (void **stream);
typedef void (*mz_stream_destroy_cb) (void **stream);
typedef int32_t (*mz_stream_get_prop_int64_cb) (void *stream, int32_t prop, int64_t *value);
typedef int32_t (*mz_stream_set_prop_int64_cb) (void *stream, int32_t prop, int64_t value);
typedef int32_t (*mz_stream_find_cb) (void *stream, const void *find, int32_t find_size,
int64_t max_seek, int64_t *position);
/***************************************************************************/
typedef struct mz_stream_vtbl_s {
mz_stream_open_cb open;
mz_stream_is_open_cb is_open;
mz_stream_read_cb read;
mz_stream_write_cb write;
mz_stream_tell_cb tell;
mz_stream_seek_cb seek;
mz_stream_close_cb close;
mz_stream_error_cb error;
mz_stream_create_cb create;
mz_stream_destroy_cb destroy;
mz_stream_get_prop_int64_cb get_prop_int64;
mz_stream_set_prop_int64_cb set_prop_int64;
} mz_stream_vtbl;
typedef struct mz_stream_s {
mz_stream_vtbl *vtbl;
struct mz_stream_s *base;
} mz_stream;
/***************************************************************************/
int32_t mz_stream_open(void *stream, const char *path, int32_t mode);
int32_t mz_stream_is_open(void *stream);
int32_t mz_stream_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_read_uint8(void *stream, uint8_t *value);
int32_t mz_stream_read_uint16(void *stream, uint16_t *value);
int32_t mz_stream_read_uint32(void *stream, uint32_t *value);
int32_t mz_stream_read_int64(void *stream, int64_t *value);
int32_t mz_stream_read_uint64(void *stream, uint64_t *value);
int32_t mz_stream_write(void *stream, const void *buf, int32_t size);
int32_t mz_stream_write_uint8(void *stream, uint8_t value);
int32_t mz_stream_write_uint16(void *stream, uint16_t value);
int32_t mz_stream_write_uint32(void *stream, uint32_t value);
int32_t mz_stream_write_int64(void *stream, int64_t value);
int32_t mz_stream_write_uint64(void *stream, uint64_t value);
int32_t mz_stream_copy(void *target, void *source, int32_t len);
int32_t mz_stream_copy_to_end(void *target, void *source);
int32_t mz_stream_copy_stream(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb, int32_t len);
int32_t mz_stream_copy_stream_to_end(void *target, mz_stream_write_cb write_cb, void *source, mz_stream_read_cb read_cb);
int64_t mz_stream_tell(void *stream);
int32_t mz_stream_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_find(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position);
int32_t mz_stream_find_reverse(void *stream, const void *find, int32_t find_size, int64_t max_seek, int64_t *position);
int32_t mz_stream_close(void *stream);
int32_t mz_stream_error(void *stream);
int32_t mz_stream_set_base(void *stream, void *base);
void* mz_stream_get_interface(void *stream);
int32_t mz_stream_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_set_prop_int64(void *stream, int32_t prop, int64_t value);
void* mz_stream_create(void **stream, mz_stream_vtbl *vtbl);
void mz_stream_delete(void **stream);
/***************************************************************************/
int32_t mz_stream_raw_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_raw_is_open(void *stream);
int32_t mz_stream_raw_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_raw_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_raw_tell(void *stream);
int32_t mz_stream_raw_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_raw_close(void *stream);
int32_t mz_stream_raw_error(void *stream);
int32_t mz_stream_raw_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_raw_set_prop_int64(void *stream, int32_t prop, int64_t value);
void* mz_stream_raw_create(void **stream);
void mz_stream_raw_delete(void **stream);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

385
externals/minizip/mz_strm_buf.c vendored Normal file
View File

@ -0,0 +1,385 @@
/* mz_strm_buf.c -- Stream for buffering reads/writes
part of the minizip-ng project
This version of ioapi is designed to buffer IO.
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_buf.h"
/***************************************************************************/
static mz_stream_vtbl mz_stream_buffered_vtbl = {
mz_stream_buffered_open,
mz_stream_buffered_is_open,
mz_stream_buffered_read,
mz_stream_buffered_write,
mz_stream_buffered_tell,
mz_stream_buffered_seek,
mz_stream_buffered_close,
mz_stream_buffered_error,
mz_stream_buffered_create,
mz_stream_buffered_delete,
NULL,
NULL
};
/***************************************************************************/
typedef struct mz_stream_buffered_s {
mz_stream stream;
int32_t error;
char readbuf[INT16_MAX];
int32_t readbuf_len;
int32_t readbuf_pos;
int32_t readbuf_hits;
int32_t readbuf_misses;
char writebuf[INT16_MAX];
int32_t writebuf_len;
int32_t writebuf_pos;
int32_t writebuf_hits;
int32_t writebuf_misses;
int64_t position;
} mz_stream_buffered;
/***************************************************************************/
#if 0
# define mz_stream_buffered_print printf
#else
# define mz_stream_buffered_print(fmt,...)
#endif
/***************************************************************************/
static int32_t mz_stream_buffered_reset(void *stream) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
buffered->readbuf_len = 0;
buffered->readbuf_pos = 0;
buffered->writebuf_len = 0;
buffered->writebuf_pos = 0;
buffered->position = 0;
return MZ_OK;
}
int32_t mz_stream_buffered_open(void *stream, const char *path, int32_t mode) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
mz_stream_buffered_print("Buffered - Open (mode %" PRId32 ")\n", mode);
mz_stream_buffered_reset(buffered);
return mz_stream_open(buffered->stream.base, path, mode);
}
int32_t mz_stream_buffered_is_open(void *stream) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
return mz_stream_is_open(buffered->stream.base);
}
static int32_t mz_stream_buffered_flush(void *stream, int32_t *written) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int32_t total_bytes_written = 0;
int32_t bytes_to_write = buffered->writebuf_len;
int32_t bytes_left_to_write = buffered->writebuf_len;
int32_t bytes_written = 0;
*written = 0;
while (bytes_left_to_write > 0) {
bytes_written = mz_stream_write(buffered->stream.base,
buffered->writebuf + (bytes_to_write - bytes_left_to_write), bytes_left_to_write);
if (bytes_written != bytes_left_to_write)
return MZ_WRITE_ERROR;
buffered->writebuf_misses += 1;
mz_stream_buffered_print("Buffered - Write flush (%" PRId32 ":%" PRId32 " len %" PRId32 ")\n",
bytes_to_write, bytes_left_to_write, buffered->writebuf_len);
total_bytes_written += bytes_written;
bytes_left_to_write -= bytes_written;
buffered->position += bytes_written;
}
buffered->writebuf_len = 0;
buffered->writebuf_pos = 0;
*written = total_bytes_written;
return MZ_OK;
}
int32_t mz_stream_buffered_read(void *stream, void *buf, int32_t size) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int32_t buf_len = 0;
int32_t bytes_to_read = 0;
int32_t bytes_to_copy = 0;
int32_t bytes_left_to_read = size;
int32_t bytes_read = 0;
int32_t bytes_flushed = 0;
mz_stream_buffered_print("Buffered - Read (size %" PRId32 " pos %" PRId64 ")\n", size, buffered->position);
if (buffered->writebuf_len > 0) {
int64_t position = buffered->position + buffered->writebuf_pos
mz_stream_buffered_print("Buffered - Switch from write to read, flushing (pos %" PRId64 ")\n", position);
mz_stream_buffered_flush(stream, &bytes_flushed);
mz_stream_buffered_seek(stream, position, MZ_SEEK_SET);
}
while (bytes_left_to_read > 0) {
if ((buffered->readbuf_len == 0) || (buffered->readbuf_pos == buffered->readbuf_len)) {
if (buffered->readbuf_len == sizeof(buffered->readbuf)) {
buffered->readbuf_pos = 0;
buffered->readbuf_len = 0;
}
bytes_to_read = (int32_t)sizeof(buffered->readbuf) - (buffered->readbuf_len - buffered->readbuf_pos);
bytes_read = mz_stream_read(buffered->stream.base, buffered->readbuf + buffered->readbuf_pos, bytes_to_read);
if (bytes_read < 0)
return bytes_read;
buffered->readbuf_misses += 1;
buffered->readbuf_len += bytes_read;
buffered->position += bytes_read;
mz_stream_buffered_print("Buffered - Filled (read %" PRId32 "/%" PRId32 " buf %" PRId32 ":%" PRId32 " pos %" PRId64 ")\n",
bytes_read, bytes_to_read, buffered->readbuf_pos, buffered->readbuf_len, buffered->position);
if (bytes_read == 0)
break;
}
if ((buffered->readbuf_len - buffered->readbuf_pos) > 0) {
bytes_to_copy = buffered->readbuf_len - buffered->readbuf_pos;
if (bytes_to_copy > bytes_left_to_read)
bytes_to_copy = bytes_left_to_read;
memcpy((char *)buf + buf_len, buffered->readbuf + buffered->readbuf_pos, bytes_to_copy);
buf_len += bytes_to_copy;
bytes_left_to_read -= bytes_to_copy;
buffered->readbuf_hits += 1;
buffered->readbuf_pos += bytes_to_copy;
mz_stream_buffered_print("Buffered - Emptied (copied %" PRId32 " remaining %" PRId32 " buf %" PRId32 ":%" PRId32 " pos %" PRId64 ")\n",
bytes_to_copy, bytes_left_to_read, buffered->readbuf_pos, buffered->readbuf_len, buffered->position);
}
}
return size - bytes_left_to_read;
}
int32_t mz_stream_buffered_write(void *stream, const void *buf, int32_t size) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int32_t bytes_to_write = size;
int32_t bytes_left_to_write = size;
int32_t bytes_to_copy = 0;
int32_t bytes_used = 0;
int32_t bytes_flushed = 0;
int32_t err = MZ_OK;
mz_stream_buffered_print("Buffered - Write (size %" PRId32 " len %" PRId32 " pos %" PRId64 ")\n",
size, buffered->writebuf_len, buffered->position);
if (buffered->readbuf_len > 0) {
buffered->position -= buffered->readbuf_len;
buffered->position += buffered->readbuf_pos;
buffered->readbuf_len = 0;
buffered->readbuf_pos = 0;
mz_stream_buffered_print("Buffered - Switch from read to write (pos %" PRId64 ")\n", buffered->position);
err = mz_stream_seek(buffered->stream.base, buffered->position, MZ_SEEK_SET);
if (err != MZ_OK)
return err;
}
while (bytes_left_to_write > 0) {
bytes_used = buffered->writebuf_len;
if (bytes_used > buffered->writebuf_pos)
bytes_used = buffered->writebuf_pos;
bytes_to_copy = (int32_t)sizeof(buffered->writebuf) - bytes_used;
if (bytes_to_copy > bytes_left_to_write)
bytes_to_copy = bytes_left_to_write;
if (bytes_to_copy == 0) {
err = mz_stream_buffered_flush(stream, &bytes_flushed);
if (err != MZ_OK)
return err;
if (bytes_flushed == 0)
return 0;
continue;
}
memcpy(buffered->writebuf + buffered->writebuf_pos,
(const char *)buf + (bytes_to_write - bytes_left_to_write), bytes_to_copy);
mz_stream_buffered_print("Buffered - Write copy (remaining %" PRId32 " write %" PRId32 ":%" PRId32 " len %" PRId32 ")\n",
bytes_to_copy, bytes_to_write, bytes_left_to_write, buffered->writebuf_len);
bytes_left_to_write -= bytes_to_copy;
buffered->writebuf_pos += bytes_to_copy;
buffered->writebuf_hits += 1;
if (buffered->writebuf_pos > buffered->writebuf_len)
buffered->writebuf_len += buffered->writebuf_pos - buffered->writebuf_len;
}
return size - bytes_left_to_write;
}
int64_t mz_stream_buffered_tell(void *stream) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int64_t position = mz_stream_tell(buffered->stream.base);
buffered->position = position;
mz_stream_buffered_print("Buffered - Tell (pos %" PRId64 " readpos %" PRId32 " writepos %" PRId32 ")\n",
buffered->position, buffered->readbuf_pos, buffered->writebuf_pos);
if (buffered->readbuf_len > 0)
position -= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos);
if (buffered->writebuf_len > 0)
position += buffered->writebuf_pos;
return position;
}
int32_t mz_stream_buffered_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int32_t bytes_flushed = 0;
int32_t err = MZ_OK;
mz_stream_buffered_print("Buffered - Seek (origin %" PRId32 " offset %" PRId64 " pos %" PRId64 ")\n",
origin, offset, buffered->position);
switch (origin) {
case MZ_SEEK_SET:
if ((buffered->readbuf_len > 0) && (offset < buffered->position) &&
(offset >= buffered->position - buffered->readbuf_len)) {
buffered->readbuf_pos = (int32_t)(offset - (buffered->position - buffered->readbuf_len));
return MZ_OK;
}
if (buffered->writebuf_len > 0) {
if ((offset >= buffered->position) && (offset <= buffered->position + buffered->writebuf_len)) {
buffered->writebuf_pos = (int32_t)(offset - buffered->position);
return MZ_OK;
}
}
err = mz_stream_buffered_flush(stream, &bytes_flushed);
if (err != MZ_OK)
return err;
buffered->position = offset;
break;
case MZ_SEEK_CUR:
if (buffered->readbuf_len > 0) {
if (offset <= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos)) {
buffered->readbuf_pos += (uint32_t)offset;
return MZ_OK;
}
offset -= ((int64_t)buffered->readbuf_len - buffered->readbuf_pos);
buffered->position += offset;
}
if (buffered->writebuf_len > 0) {
if (offset <= ((int64_t)buffered->writebuf_len - buffered->writebuf_pos)) {
buffered->writebuf_pos += (uint32_t)offset;
return MZ_OK;
}
/* offset -= (buffered->writebuf_len - buffered->writebuf_pos); */
}
err = mz_stream_buffered_flush(stream, &bytes_flushed);
if (err != MZ_OK)
return err;
break;
case MZ_SEEK_END:
if (buffered->writebuf_len > 0) {
buffered->writebuf_pos = buffered->writebuf_len;
return MZ_OK;
}
break;
}
buffered->readbuf_len = 0;
buffered->readbuf_pos = 0;
buffered->writebuf_len = 0;
buffered->writebuf_pos = 0;
return mz_stream_seek(buffered->stream.base, offset, origin);
}
int32_t mz_stream_buffered_close(void *stream) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
int32_t bytes_flushed = 0;
mz_stream_buffered_flush(stream, &bytes_flushed);
mz_stream_buffered_print("Buffered - Close (flushed %" PRId32 ")\n", bytes_flushed);
if (buffered->readbuf_hits + buffered->readbuf_misses > 0) {
mz_stream_buffered_print("Buffered - Read efficiency %.02f%%\n",
(buffered->readbuf_hits / ((float)buffered->readbuf_hits + buffered->readbuf_misses)) * 100);
}
if (buffered->writebuf_hits + buffered->writebuf_misses > 0) {
mz_stream_buffered_print("Buffered - Write efficiency %.02f%%\n",
(buffered->writebuf_hits / ((float)buffered->writebuf_hits + buffered->writebuf_misses)) * 100);
}
mz_stream_buffered_reset(buffered);
return mz_stream_close(buffered->stream.base);
}
int32_t mz_stream_buffered_error(void *stream) {
mz_stream_buffered *buffered = (mz_stream_buffered *)stream;
return mz_stream_error(buffered->stream.base);
}
void *mz_stream_buffered_create(void **stream) {
mz_stream_buffered *buffered = NULL;
buffered = (mz_stream_buffered *)MZ_ALLOC(sizeof(mz_stream_buffered));
if (buffered != NULL) {
memset(buffered, 0, sizeof(mz_stream_buffered));
buffered->stream.vtbl = &mz_stream_buffered_vtbl;
}
if (stream != NULL)
*stream = buffered;
return buffered;
}
void mz_stream_buffered_delete(void **stream) {
mz_stream_buffered *buffered = NULL;
if (stream == NULL)
return;
buffered = (mz_stream_buffered *)*stream;
if (buffered != NULL)
MZ_FREE(buffered);
*stream = NULL;
}
void *mz_stream_buffered_get_interface(void) {
return (void *)&mz_stream_buffered_vtbl;
}

42
externals/minizip/mz_strm_buf.h vendored Normal file
View File

@ -0,0 +1,42 @@
/* mz_strm_buf.h -- Stream for buffering reads/writes
part of the minizip-ng project
This version of ioapi is designed to buffer IO.
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_BUFFERED_H
#define MZ_STREAM_BUFFERED_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_buffered_open(void *stream, const char *path, int32_t mode);
int32_t mz_stream_buffered_is_open(void *stream);
int32_t mz_stream_buffered_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_buffered_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_buffered_tell(void *stream);
int32_t mz_stream_buffered_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_buffered_close(void *stream);
int32_t mz_stream_buffered_error(void *stream);
void* mz_stream_buffered_create(void **stream);
void mz_stream_buffered_delete(void **stream);
void* mz_stream_buffered_get_interface(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

374
externals/minizip/mz_strm_bzip.c vendored Normal file
View File

@ -0,0 +1,374 @@
/* mz_strm_bzip.c -- Stream for bzip inflate/deflate
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_bzip.h"
#include "bzlib.h"
/***************************************************************************/
static mz_stream_vtbl mz_stream_bzip_vtbl = {
mz_stream_bzip_open,
mz_stream_bzip_is_open,
mz_stream_bzip_read,
mz_stream_bzip_write,
mz_stream_bzip_tell,
mz_stream_bzip_seek,
mz_stream_bzip_close,
mz_stream_bzip_error,
mz_stream_bzip_create,
mz_stream_bzip_delete,
mz_stream_bzip_get_prop_int64,
mz_stream_bzip_set_prop_int64
};
/***************************************************************************/
typedef struct mz_stream_bzip_s {
mz_stream stream;
bz_stream bzstream;
int32_t mode;
int32_t error;
uint8_t buffer[INT16_MAX];
int32_t buffer_len;
int16_t stream_end;
int64_t total_in;
int64_t total_out;
int64_t max_total_in;
int8_t initialized;
int16_t level;
} mz_stream_bzip;
/***************************************************************************/
int32_t mz_stream_bzip_open(void *stream, const char *path, int32_t mode) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
MZ_UNUSED(path);
bzip->bzstream.bzalloc = 0;
bzip->bzstream.bzfree = 0;
bzip->bzstream.opaque = 0;
bzip->bzstream.total_in_lo32 = 0;
bzip->bzstream.total_in_hi32 = 0;
bzip->bzstream.total_out_lo32 = 0;
bzip->bzstream.total_out_hi32 = 0;
bzip->total_in = 0;
bzip->total_out = 0;
if (mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
bzip->bzstream.next_out = (char *)bzip->buffer;
bzip->bzstream.avail_out = sizeof(bzip->buffer);
bzip->error = BZ2_bzCompressInit(&bzip->bzstream, bzip->level, 0, 0);
#endif
} else if (mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
bzip->bzstream.next_in = (char *)bzip->buffer;
bzip->bzstream.avail_in = 0;
bzip->error = BZ2_bzDecompressInit(&bzip->bzstream, 0, 0);
#endif
}
if (bzip->error != BZ_OK)
return MZ_OPEN_ERROR;
bzip->initialized = 1;
bzip->stream_end = 0;
bzip->mode = mode;
return MZ_OK;
}
int32_t mz_stream_bzip_is_open(void *stream) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
if (bzip->initialized != 1)
return MZ_OPEN_ERROR;
return MZ_OK;
}
int32_t mz_stream_bzip_read(void *stream, void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
uint64_t total_in_before = 0;
uint64_t total_out_before = 0;
uint64_t total_in_after = 0;
uint64_t total_out_after = 0;
int32_t total_in = 0;
int32_t total_out = 0;
int32_t in_bytes = 0;
int32_t out_bytes = 0;
int32_t bytes_to_read = sizeof(bzip->buffer);
int32_t read = 0;
int32_t err = BZ_OK;
if (bzip->stream_end)
return 0;
bzip->bzstream.next_out = (char *)buf;
bzip->bzstream.avail_out = (unsigned int)size;
do {
if (bzip->bzstream.avail_in == 0) {
if (bzip->max_total_in > 0) {
if ((int64_t)bytes_to_read > (bzip->max_total_in - bzip->total_in))
bytes_to_read = (int32_t)(bzip->max_total_in - bzip->total_in);
}
read = mz_stream_read(bzip->stream.base, bzip->buffer, bytes_to_read);
if (read < 0)
return read;
bzip->bzstream.next_in = (char *)bzip->buffer;
bzip->bzstream.avail_in = (uint32_t)read;
}
total_in_before = bzip->bzstream.avail_in;
total_out_before = bzip->bzstream.total_out_lo32 +
(((uint64_t)bzip->bzstream.total_out_hi32) << 32);
err = BZ2_bzDecompress(&bzip->bzstream);
total_in_after = bzip->bzstream.avail_in;
total_out_after = bzip->bzstream.total_out_lo32 +
(((uint64_t)bzip->bzstream.total_out_hi32) << 32);
in_bytes = (int32_t)(total_in_before - total_in_after);
out_bytes = (int32_t)(total_out_after - total_out_before);
total_in += in_bytes;
total_out += out_bytes;
bzip->total_in += in_bytes;
bzip->total_out += out_bytes;
if (err == BZ_STREAM_END) {
bzip->stream_end = 1;
break;
}
if (err != BZ_OK && err != BZ_RUN_OK) {
bzip->error = err;
break;
}
} while (bzip->bzstream.avail_out > 0);
if (bzip->error != 0)
return MZ_DATA_ERROR;
return total_out;
#endif
}
#ifndef MZ_ZIP_NO_COMPRESSION
static int32_t mz_stream_bzip_flush(void *stream) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
if (mz_stream_write(bzip->stream.base, bzip->buffer, bzip->buffer_len) != bzip->buffer_len)
return MZ_WRITE_ERROR;
return MZ_OK;
}
static int32_t mz_stream_bzip_compress(void *stream, int flush) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
uint32_t out_bytes = 0;
int32_t err = BZ_OK;
do {
if (bzip->bzstream.avail_out == 0) {
err = mz_stream_bzip_flush(bzip);
if (err != MZ_OK)
return err;
bzip->bzstream.avail_out = sizeof(bzip->buffer);
bzip->bzstream.next_out = (char *)bzip->buffer;
bzip->buffer_len = 0;
}
total_out_before = bzip->bzstream.total_out_lo32 +
(((uint64_t)bzip->bzstream.total_out_hi32) << 32);
err = BZ2_bzCompress(&bzip->bzstream, flush);
total_out_after = bzip->bzstream.total_out_lo32 +
(((uint64_t)bzip->bzstream.total_out_hi32) << 32);
out_bytes = (uint32_t)(total_out_after - total_out_before);
bzip->buffer_len += out_bytes;
bzip->total_out += out_bytes;
if (err == BZ_STREAM_END)
break;
if (err < 0) {
bzip->error = err;
return MZ_DATA_ERROR;
}
} while ((bzip->bzstream.avail_in > 0) || (flush == BZ_FINISH && err == BZ_FINISH_OK));
return MZ_OK;
}
#endif
int32_t mz_stream_bzip_write(void *stream, const void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_COMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
int32_t err = MZ_OK;
bzip->bzstream.next_in = (char *)(intptr_t)buf;
bzip->bzstream.avail_in = (unsigned int)size;
err = mz_stream_bzip_compress(stream, BZ_RUN);
if (err != MZ_OK) {
return err;
}
bzip->total_in += size;
return size;
#endif
}
int64_t mz_stream_bzip_tell(void *stream) {
MZ_UNUSED(stream);
return MZ_TELL_ERROR;
}
int32_t mz_stream_bzip_seek(void *stream, int64_t offset, int32_t origin) {
MZ_UNUSED(stream);
MZ_UNUSED(offset);
MZ_UNUSED(origin);
return MZ_SEEK_ERROR;
}
int32_t mz_stream_bzip_close(void *stream) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
if (bzip->mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
mz_stream_bzip_compress(stream, BZ_FINISH);
mz_stream_bzip_flush(stream);
BZ2_bzCompressEnd(&bzip->bzstream);
#endif
} else if (bzip->mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
BZ2_bzDecompressEnd(&bzip->bzstream);
#endif
}
bzip->initialized = 0;
if (bzip->error != BZ_OK)
return MZ_CLOSE_ERROR;
return MZ_OK;
}
int32_t mz_stream_bzip_error(void *stream) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
return bzip->error;
}
int32_t mz_stream_bzip_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = bzip->total_in;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = bzip->max_total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = bzip->total_out;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = 0;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
int32_t mz_stream_bzip_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_bzip *bzip = (mz_stream_bzip *)stream;
switch (prop) {
case MZ_STREAM_PROP_COMPRESS_LEVEL:
if (value < 0)
bzip->level = 6;
else
bzip->level = (int16_t)value;
return MZ_OK;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
bzip->max_total_in = value;
return MZ_OK;
}
return MZ_EXIST_ERROR;
}
void *mz_stream_bzip_create(void **stream) {
mz_stream_bzip *bzip = NULL;
bzip = (mz_stream_bzip *)MZ_ALLOC(sizeof(mz_stream_bzip));
if (bzip != NULL) {
memset(bzip, 0, sizeof(mz_stream_bzip));
bzip->stream.vtbl = &mz_stream_bzip_vtbl;
bzip->level = 6;
}
if (stream != NULL)
*stream = bzip;
return bzip;
}
void mz_stream_bzip_delete(void **stream) {
mz_stream_bzip *bzip = NULL;
if (stream == NULL)
return;
bzip = (mz_stream_bzip *)*stream;
if (bzip != NULL)
MZ_FREE(bzip);
*stream = NULL;
}
void *mz_stream_bzip_get_interface(void) {
return (void *)&mz_stream_bzip_vtbl;
}
extern void bz_internal_error(int errcode) {
MZ_UNUSED(errcode);
}

45
externals/minizip/mz_strm_bzip.h vendored Normal file
View File

@ -0,0 +1,45 @@
/* mz_strm_bzip.h -- Stream for bzip inflate/deflate
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_BZIP_H
#define MZ_STREAM_BZIP_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_bzip_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_bzip_is_open(void *stream);
int32_t mz_stream_bzip_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_bzip_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_bzip_tell(void *stream);
int32_t mz_stream_bzip_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_bzip_close(void *stream);
int32_t mz_stream_bzip_error(void *stream);
int32_t mz_stream_bzip_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_bzip_set_prop_int64(void *stream, int32_t prop, int64_t value);
void* mz_stream_bzip_create(void **stream);
void mz_stream_bzip_delete(void **stream);
void* mz_stream_bzip_get_interface(void);
void bz_internal_error(int errcode);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

356
externals/minizip/mz_strm_libcomp.c vendored Normal file
View File

@ -0,0 +1,356 @@
/* mz_strm_libcomp.c -- Stream for apple compression
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_libcomp.h"
#include <compression.h>
/***************************************************************************/
static mz_stream_vtbl mz_stream_libcomp_vtbl = {
mz_stream_libcomp_open,
mz_stream_libcomp_is_open,
mz_stream_libcomp_read,
mz_stream_libcomp_write,
mz_stream_libcomp_tell,
mz_stream_libcomp_seek,
mz_stream_libcomp_close,
mz_stream_libcomp_error,
mz_stream_libcomp_create,
mz_stream_libcomp_delete,
mz_stream_libcomp_get_prop_int64,
mz_stream_libcomp_set_prop_int64
};
/***************************************************************************/
typedef struct mz_stream_libcomp_s {
mz_stream stream;
compression_stream
cstream;
uint8_t buffer[INT16_MAX];
int32_t buffer_len;
int64_t total_in;
int64_t total_out;
int64_t max_total_in;
int8_t initialized;
int32_t mode;
int32_t error;
int16_t method;
} mz_stream_libcomp;
/***************************************************************************/
int32_t mz_stream_libcomp_open(void *stream, const char *path, int32_t mode) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
int32_t err = 0;
int16_t operation = 0;
compression_algorithm algorithm = 0;
MZ_UNUSED(path);
if (libcomp->method == 0)
return MZ_PARAM_ERROR;
libcomp->total_in = 0;
libcomp->total_out = 0;
if (mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
operation = COMPRESSION_STREAM_ENCODE;
#endif
} else if (mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
operation = COMPRESSION_STREAM_DECODE;
#endif
}
if (libcomp->method == MZ_COMPRESS_METHOD_DEFLATE)
algorithm = COMPRESSION_ZLIB;
else if (libcomp->method == MZ_COMPRESS_METHOD_XZ)
algorithm = COMPRESSION_LZMA;
else
return MZ_SUPPORT_ERROR;
err = compression_stream_init(&libcomp->cstream, (compression_stream_operation)operation, algorithm);
if (err == COMPRESSION_STATUS_ERROR) {
libcomp->error = err;
return MZ_OPEN_ERROR;
}
libcomp->initialized = 1;
libcomp->mode = mode;
return MZ_OK;
}
int32_t mz_stream_libcomp_is_open(void *stream) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
if (libcomp->initialized != 1)
return MZ_OPEN_ERROR;
return MZ_OK;
}
int32_t mz_stream_libcomp_read(void *stream, void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
uint64_t total_in_before = 0;
uint64_t total_in_after = 0;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
int32_t total_in = 0;
int32_t total_out = 0;
int32_t in_bytes = 0;
int32_t out_bytes = 0;
int32_t bytes_to_read = sizeof(libcomp->buffer);
int32_t read = 0;
int32_t err = MZ_OK;
int16_t flags = 0;
libcomp->cstream.dst_ptr = buf;
libcomp->cstream.dst_size = (size_t)size;
do {
if (libcomp->cstream.src_size == 0) {
if (libcomp->max_total_in > 0) {
if ((int64_t)bytes_to_read > (libcomp->max_total_in - libcomp->total_in))
bytes_to_read = (int32_t)(libcomp->max_total_in - libcomp->total_in);
}
read = mz_stream_read(libcomp->stream.base, libcomp->buffer, bytes_to_read);
if (read < 0)
return read;
if (read == 0)
flags = COMPRESSION_STREAM_FINALIZE;
libcomp->cstream.src_ptr = libcomp->buffer;
libcomp->cstream.src_size = (size_t)read;
}
total_in_before = libcomp->cstream.src_size;
total_out_before = libcomp->cstream.dst_size;
err = compression_stream_process(&libcomp->cstream, flags);
if (err == COMPRESSION_STATUS_ERROR) {
libcomp->error = err;
break;
}
total_in_after = libcomp->cstream.src_size;
total_out_after = libcomp->cstream.dst_size;
in_bytes = (int32_t)(total_in_before - total_in_after);
out_bytes = (int32_t)(total_out_before - total_out_after);
total_in += in_bytes;
total_out += out_bytes;
libcomp->total_in += in_bytes;
libcomp->total_out += out_bytes;
if (err == COMPRESSION_STATUS_END)
break;
if (err != COMPRESSION_STATUS_OK) {
libcomp->error = err;
break;
}
} while (libcomp->cstream.dst_size > 0);
if (libcomp->error != 0)
return MZ_DATA_ERROR;
return total_out;
#endif
}
static int32_t mz_stream_libcomp_flush(void *stream) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
if (mz_stream_write(libcomp->stream.base, libcomp->buffer, libcomp->buffer_len) != libcomp->buffer_len)
return MZ_WRITE_ERROR;
return MZ_OK;
}
static int32_t mz_stream_libcomp_deflate(void *stream, int flush) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
uint32_t out_bytes = 0;
int32_t err = MZ_OK;
do {
if (libcomp->cstream.dst_size == 0) {
err = mz_stream_libcomp_flush(libcomp);
if (err != MZ_OK) {
libcomp->error = err;
return err;
}
libcomp->cstream.dst_size = sizeof(libcomp->buffer);
libcomp->cstream.dst_ptr = libcomp->buffer;
libcomp->buffer_len = 0;
}
total_out_before = libcomp->cstream.dst_size;
err = compression_stream_process(&libcomp->cstream, flush);
total_out_after = libcomp->cstream.dst_size;
out_bytes = (uint32_t)(total_out_before - total_out_after);
libcomp->buffer_len += out_bytes;
libcomp->total_out += out_bytes;
if (err == COMPRESSION_STATUS_END)
break;
if (err != COMPRESSION_STATUS_OK) {
libcomp->error = err;
return MZ_DATA_ERROR;
}
} while ((libcomp->cstream.src_size > 0) || (flush == COMPRESSION_STREAM_FINALIZE && err == COMPRESSION_STATUS_OK));
return MZ_OK;
}
int32_t mz_stream_libcomp_write(void *stream, const void *buf, int32_t size) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
int32_t err = size;
#ifdef MZ_ZIP_NO_COMPRESSION
MZ_UNUSED(libcomp);
err = MZ_SUPPORT_ERROR;
#else
libcomp->cstream.src_ptr = buf;
libcomp->cstream.src_size = (size_t)size;
mz_stream_libcomp_deflate(stream, 0);
libcomp->total_in += size;
#endif
return err;
}
int64_t mz_stream_libcomp_tell(void *stream) {
MZ_UNUSED(stream);
return MZ_TELL_ERROR;
}
int32_t mz_stream_libcomp_seek(void *stream, int64_t offset, int32_t origin) {
MZ_UNUSED(stream);
MZ_UNUSED(offset);
MZ_UNUSED(origin);
return MZ_SEEK_ERROR;
}
int32_t mz_stream_libcomp_close(void *stream) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
if (libcomp->mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
mz_stream_libcomp_deflate(stream, COMPRESSION_STREAM_FINALIZE);
mz_stream_libcomp_flush(stream);
#endif
} else if (libcomp->mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#endif
}
compression_stream_destroy(&libcomp->cstream);
libcomp->initialized = 0;
if (libcomp->error != MZ_OK)
return MZ_CLOSE_ERROR;
return MZ_OK;
}
int32_t mz_stream_libcomp_error(void *stream) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
return libcomp->error;
}
int32_t mz_stream_libcomp_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = libcomp->total_in;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = libcomp->max_total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = libcomp->total_out;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = 0;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
int32_t mz_stream_libcomp_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_libcomp *libcomp = (mz_stream_libcomp *)stream;
switch (prop) {
case MZ_STREAM_PROP_COMPRESS_METHOD:
libcomp->method = (int16_t)value;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
libcomp->max_total_in = value;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
void *mz_stream_libcomp_create(void **stream) {
mz_stream_libcomp *libcomp = NULL;
libcomp = (mz_stream_libcomp *)MZ_ALLOC(sizeof(mz_stream_libcomp));
if (libcomp != NULL) {
memset(libcomp, 0, sizeof(mz_stream_libcomp));
libcomp->stream.vtbl = &mz_stream_libcomp_vtbl;
}
if (stream != NULL)
*stream = libcomp;
return libcomp;
}
void mz_stream_libcomp_delete(void **stream) {
mz_stream_libcomp *libcomp = NULL;
if (stream == NULL)
return;
libcomp = (mz_stream_libcomp *)*stream;
if (libcomp != NULL)
MZ_FREE(libcomp);
*stream = NULL;
}

45
externals/minizip/mz_strm_libcomp.h vendored Normal file
View File

@ -0,0 +1,45 @@
/* mz_strm_libcomp.h -- Stream for apple compression
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_LIBCOMP_H
#define MZ_STREAM_LIBCOMP_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_libcomp_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_libcomp_is_open(void *stream);
int32_t mz_stream_libcomp_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_libcomp_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_libcomp_tell(void *stream);
int32_t mz_stream_libcomp_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_libcomp_close(void *stream);
int32_t mz_stream_libcomp_error(void *stream);
int32_t mz_stream_libcomp_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_libcomp_set_prop_int64(void *stream, int32_t prop, int64_t value);
void* mz_stream_libcomp_create(void **stream);
void mz_stream_libcomp_delete(void **stream);
void* mz_stream_libcomp_get_interface(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

470
externals/minizip/mz_strm_lzma.c vendored Normal file
View File

@ -0,0 +1,470 @@
/* mz_strm_lzma.c -- Stream for lzma inflate/deflate
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_lzma.h"
#include "lzma.h"
/***************************************************************************/
#define MZ_LZMA_MAGIC_SIZE (4)
#define MZ_LZMA_ZIP_HEADER_SIZE (5)
#define MZ_LZMA_ALONE_HEADER_SIZE (MZ_LZMA_ZIP_HEADER_SIZE + 8)
/***************************************************************************/
static mz_stream_vtbl mz_stream_lzma_vtbl = {
mz_stream_lzma_open,
mz_stream_lzma_is_open,
mz_stream_lzma_read,
mz_stream_lzma_write,
mz_stream_lzma_tell,
mz_stream_lzma_seek,
mz_stream_lzma_close,
mz_stream_lzma_error,
mz_stream_lzma_create,
mz_stream_lzma_delete,
mz_stream_lzma_get_prop_int64,
mz_stream_lzma_set_prop_int64
};
/***************************************************************************/
typedef struct mz_stream_lzma_s {
mz_stream stream;
lzma_stream lstream;
int32_t mode;
int32_t error;
uint8_t buffer[INT16_MAX];
int32_t buffer_len;
int64_t total_in;
int64_t total_out;
int64_t max_total_in;
int64_t max_total_out;
int8_t initialized;
int8_t header;
int32_t header_size;
uint32_t preset;
int16_t method;
} mz_stream_lzma;
/***************************************************************************/
int32_t mz_stream_lzma_open(void *stream, const char *path, int32_t mode) {
mz_stream_lzma *lzma = (mz_stream_lzma *)stream;
lzma_filter filters[LZMA_FILTERS_MAX + 1];
lzma_options_lzma opt_lzma;
uint32_t size = 0;
uint8_t major = 0;
uint8_t minor = 0;
MZ_UNUSED(path);
memset(&opt_lzma, 0, sizeof(opt_lzma));
lzma->lstream.total_in = 0;
lzma->lstream.total_out = 0;
lzma->total_in = 0;
lzma->total_out = 0;
lzma->header = 0;
if (mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
MZ_UNUSED(filters);
MZ_UNUSED(major);
MZ_UNUSED(minor);
return MZ_SUPPORT_ERROR;
#else
lzma->lstream.next_out = lzma->buffer;
lzma->lstream.avail_out = sizeof(lzma->buffer);
if (lzma_lzma_preset(&opt_lzma, lzma->preset))
return MZ_OPEN_ERROR;
memset(&filters, 0, sizeof(filters));
if (lzma->method == MZ_COMPRESS_METHOD_LZMA)
filters[0].id = LZMA_FILTER_LZMA1;
else if (lzma->method == MZ_COMPRESS_METHOD_XZ)
filters[0].id = LZMA_FILTER_LZMA2;
filters[0].options = &opt_lzma;
filters[1].id = LZMA_VLI_UNKNOWN;
lzma_properties_size(&size, (lzma_filter *)&filters);
if (lzma->method == MZ_COMPRESS_METHOD_LZMA) {
mz_stream_write_uint8(lzma->stream.base, LZMA_VERSION_MAJOR);
mz_stream_write_uint8(lzma->stream.base, LZMA_VERSION_MINOR);
mz_stream_write_uint16(lzma->stream.base, (uint16_t)size);
lzma->header = 1;
lzma->total_out += MZ_LZMA_MAGIC_SIZE;
lzma->error = lzma_alone_encoder(&lzma->lstream, &opt_lzma);
} else if (lzma->method == MZ_COMPRESS_METHOD_XZ)
lzma->error = lzma_stream_encoder(&lzma->lstream, filters, LZMA_CHECK_CRC64);
#endif
} else if (mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
MZ_UNUSED(filters);
MZ_UNUSED(major);
MZ_UNUSED(minor);
return MZ_SUPPORT_ERROR;
#else
lzma->lstream.next_in = lzma->buffer;
lzma->lstream.avail_in = 0;
if (lzma->method == MZ_COMPRESS_METHOD_LZMA) {
mz_stream_read_uint8(lzma->stream.base, &major);
mz_stream_read_uint8(lzma->stream.base, &minor);
mz_stream_read_uint16(lzma->stream.base, (uint16_t *)&size);
lzma->header = 1;
lzma->total_in += MZ_LZMA_MAGIC_SIZE;
lzma->error = lzma_alone_decoder(&lzma->lstream, UINT64_MAX);
} else if (lzma->method == MZ_COMPRESS_METHOD_XZ)
lzma->error = lzma_stream_decoder(&lzma->lstream, UINT64_MAX, 0);
#endif
}
if (lzma->error != LZMA_OK)
return MZ_OPEN_ERROR;
lzma->initialized = 1;
lzma->mode = mode;
return MZ_OK;
}
int32_t mz_stream_lzma_is_open(void *stream) {
mz_stream_lzma *lzma = (mz_stream_lzma *)stream;
if (lzma->initialized != 1)
return MZ_OPEN_ERROR;
return MZ_OK;
}
int32_t mz_stream_lzma_read(void *stream, void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_lzma *lzma = (mz_stream_lzma *)stream;
uint64_t total_in_before = 0;
uint64_t total_out_before = 0;
uint64_t total_in_after = 0;
uint64_t total_out_after = 0;
int32_t total_in = 0;
int32_t total_out = 0;
int32_t in_bytes = 0;
int32_t out_bytes = 0;
int32_t bytes_to_read = sizeof(lzma->buffer);
int32_t read = 0;
int32_t err = LZMA_OK;
lzma->lstream.next_out = (uint8_t*)buf;
lzma->lstream.avail_out = (size_t)size;
do {
if (lzma->lstream.avail_in == 0) {
if (lzma->max_total_in > 0) {
if ((int64_t)bytes_to_read > (lzma->max_total_in - lzma->total_in))
bytes_to_read = (int32_t)(lzma->max_total_in - lzma->total_in);
}
if (lzma->header) {
bytes_to_read = MZ_LZMA_ZIP_HEADER_SIZE - lzma->header_size;
}
read = mz_stream_read(lzma->stream.base, lzma->buffer, bytes_to_read);
if (read < 0)
return read;
/* Write uncompressed size for lzma alone header not in zip format */
if (lzma->header) {
lzma->header_size += read;
if (lzma->header_size == MZ_LZMA_ZIP_HEADER_SIZE) {
uint64_t uncompressed_size = UINT64_MAX;
memcpy(lzma->buffer + MZ_LZMA_ZIP_HEADER_SIZE, &uncompressed_size, sizeof(uncompressed_size));
read += sizeof(uncompressed_size);
bytes_to_read = sizeof(lzma->buffer);
lzma->total_in -= sizeof(uncompressed_size);
lzma->header = 0;
}
}
lzma->lstream.next_in = lzma->buffer;
lzma->lstream.avail_in = (size_t)read;
}
total_in_before = lzma->lstream.avail_in;
total_out_before = lzma->lstream.total_out;
err = lzma_code(&lzma->lstream, LZMA_RUN);
total_in_after = lzma->lstream.avail_in;
total_out_after = lzma->lstream.total_out;
if ((lzma->max_total_out != -1) && (int64_t)total_out_after > lzma->max_total_out)
total_out_after = (uint64_t)lzma->max_total_out;
in_bytes = (int32_t)(total_in_before - total_in_after);
out_bytes = (int32_t)(total_out_after - total_out_before);
total_in += in_bytes;
total_out += out_bytes;
lzma->total_in += in_bytes;
lzma->total_out += out_bytes;
if (err == LZMA_STREAM_END)
break;
if (err != LZMA_OK) {
lzma->error = err;
break;
}
} while (lzma->lstream.avail_out > 0);
if (lzma->error != 0)
return MZ_DATA_ERROR;
return total_out;
#endif
}
#ifndef MZ_ZIP_NO_COMPRESSION
static int32_t mz_stream_lzma_flush(void *stream) {
mz_stream_lzma *lzma = (mz_stream_lzma *)stream;
int32_t buffer_len = lzma->buffer_len;
uint8_t *buffer = lzma->buffer;
/* Skip writing lzma_alone header uncompressed size for zip format */
if (lzma->header) {
uint64_t uncompressed_size = 0;
if (lzma->buffer_len < MZ_LZMA_ALONE_HEADER_SIZE)
return MZ_OK;
if (mz_stream_write(lzma->stream.base, buffer, MZ_LZMA_ZIP_HEADER_SIZE) != MZ_LZMA_ZIP_HEADER_SIZE)
return MZ_WRITE_ERROR;
buffer += MZ_LZMA_ALONE_HEADER_SIZE;
buffer_len -= MZ_LZMA_ALONE_HEADER_SIZE;
lzma->buffer_len -= sizeof(uncompressed_size);
lzma->total_out -= sizeof(uncompressed_size);
lzma->header = 0;
}
if (mz_stream_write(lzma->stream.base, buffer, buffer_len) != buffer_len)
return MZ_WRITE_ERROR;
return MZ_OK;
}
static int32_t mz_stream_lzma_code(void *stream, int32_t flush) {
mz_stream_lzma *lzma = (mz_stream_lzma *)stream;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
uint32_t out_bytes = 0;
int32_t err = LZMA_OK;
do {
if (lzma->lstream.avail_out == 0) {
err = mz_stream_lzma_flush(lzma);
if (err != MZ_OK)
return err;
lzma->lstream.avail_out = sizeof(lzma->buffer);
lzma->lstream.next_out = lzma->buffer;
lzma->buffer_len = 0;
}
total_out_before = lzma->lstream.total_out;
err = lzma_code(&lzma->lstream, (lzma_action)flush);
total_out_after = lzma->lstream.total_out;
out_bytes = (uint32_t)(total_out_after - total_out_before);
if (err != LZMA_OK && err != LZMA_STREAM_END) {
lzma->error = err;
return MZ_DATA_ERROR;
}
lzma->buffer_len += out_bytes;
lzma->total_out += out_bytes;
} while ((lzma->lstream.avail_in > 0) || (flush == LZMA_FINISH && err == LZMA_OK));
return MZ_OK;
}
#endif
int32_t mz_stream_lzma_write(void *stream, const void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_COMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_lzma *lzma = (mz_stream_lzma *)stream;
int32_t err = MZ_OK;
lzma->lstream.next_in = (uint8_t*)(intptr_t)buf;
lzma->lstream.avail_in = (size_t)size;
err = mz_stream_lzma_code(stream, LZMA_RUN);
if (err != MZ_OK) {
return err;
}
lzma->total_in += size;
return size;
#endif
}
int64_t mz_stream_lzma_tell(void *stream) {
MZ_UNUSED(stream);
return MZ_TELL_ERROR;
}
int32_t mz_stream_lzma_seek(void *stream, int64_t offset, int32_t origin) {
MZ_UNUSED(stream);
MZ_UNUSED(offset);
MZ_UNUSED(origin);
return MZ_SEEK_ERROR;
}
int32_t mz_stream_lzma_close(void *stream) {
mz_stream_lzma *lzma = (mz_stream_lzma *)stream;
if (lzma->mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
mz_stream_lzma_code(stream, LZMA_FINISH);
mz_stream_lzma_flush(stream);
lzma_end(&lzma->lstream);
#endif
} else if (lzma->mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
lzma_end(&lzma->lstream);
#endif
}
lzma->initialized = 0;
if (lzma->error != LZMA_OK)
return MZ_CLOSE_ERROR;
return MZ_OK;
}
int32_t mz_stream_lzma_error(void *stream) {
mz_stream_lzma *lzma = (mz_stream_lzma *)stream;
return lzma->error;
}
int32_t mz_stream_lzma_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_lzma *lzma = (mz_stream_lzma *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = lzma->total_in;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = lzma->max_total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = lzma->total_out;
break;
case MZ_STREAM_PROP_TOTAL_OUT_MAX:
*value = lzma->max_total_out;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = MZ_LZMA_MAGIC_SIZE;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
int32_t mz_stream_lzma_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_lzma *lzma = (mz_stream_lzma *)stream;
switch (prop) {
case MZ_STREAM_PROP_COMPRESS_LEVEL:
if (value >= 9)
lzma->preset = LZMA_PRESET_EXTREME;
else
lzma->preset = LZMA_PRESET_DEFAULT;
break;
case MZ_STREAM_PROP_COMPRESS_METHOD:
lzma->method = (int16_t)value;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
lzma->max_total_in = value;
break;
case MZ_STREAM_PROP_TOTAL_OUT_MAX:
if (value < -1)
return MZ_PARAM_ERROR;
lzma->max_total_out = value;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
void *mz_stream_lzma_create(void **stream) {
mz_stream_lzma *lzma = NULL;
lzma = (mz_stream_lzma *)MZ_ALLOC(sizeof(mz_stream_lzma));
if (lzma != NULL) {
memset(lzma, 0, sizeof(mz_stream_lzma));
lzma->stream.vtbl = &mz_stream_lzma_vtbl;
lzma->method = MZ_COMPRESS_METHOD_LZMA;
lzma->preset = LZMA_PRESET_DEFAULT;
lzma->max_total_out = -1;
}
if (stream != NULL)
*stream = lzma;
return lzma;
}
void mz_stream_lzma_delete(void **stream) {
mz_stream_lzma *lzma = NULL;
if (stream == NULL)
return;
lzma = (mz_stream_lzma *)*stream;
if (lzma != NULL)
MZ_FREE(lzma);
*stream = NULL;
}
void *mz_stream_lzma_get_interface(void) {
return (void *)&mz_stream_lzma_vtbl;
}

43
externals/minizip/mz_strm_lzma.h vendored Normal file
View File

@ -0,0 +1,43 @@
/* mz_strm_lzma.h -- Stream for lzma inflate/deflate
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as lzma.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_LZMA_H
#define MZ_STREAM_LZMA_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_lzma_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_lzma_is_open(void *stream);
int32_t mz_stream_lzma_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_lzma_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_lzma_tell(void *stream);
int32_t mz_stream_lzma_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_lzma_close(void *stream);
int32_t mz_stream_lzma_error(void *stream);
int32_t mz_stream_lzma_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_lzma_set_prop_int64(void *stream, int32_t prop, int64_t value);
void* mz_stream_lzma_create(void **stream);
void mz_stream_lzma_delete(void **stream);
void* mz_stream_lzma_get_interface(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

272
externals/minizip/mz_strm_mem.c vendored Normal file
View File

@ -0,0 +1,272 @@
/* mz_strm_mem.c -- Stream for memory access
part of the minizip-ng project
This interface is designed to access memory rather than files.
We do use a region of memory to put data in to and take it out of.
Based on Unzip ioapi.c version 0.22, May 19th, 2003
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 2003 Justin Fletcher
Copyright (C) 1998-2003 Gilles Vollant
https://www.winimage.com/zLibDll/minizip.html
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_mem.h"
/***************************************************************************/
static mz_stream_vtbl mz_stream_mem_vtbl = {
mz_stream_mem_open,
mz_stream_mem_is_open,
mz_stream_mem_read,
mz_stream_mem_write,
mz_stream_mem_tell,
mz_stream_mem_seek,
mz_stream_mem_close,
mz_stream_mem_error,
mz_stream_mem_create,
mz_stream_mem_delete,
NULL,
NULL
};
/***************************************************************************/
typedef struct mz_stream_mem_s {
mz_stream stream;
int32_t mode;
uint8_t *buffer; /* Memory buffer pointer */
int32_t size; /* Size of the memory buffer */
int32_t limit; /* Furthest we've written */
int32_t position; /* Current position in the memory */
int32_t grow_size; /* Size to grow when full */
} mz_stream_mem;
/***************************************************************************/
static int32_t mz_stream_mem_set_size(void *stream, int32_t size) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
int32_t new_size = size;
uint8_t *new_buf = NULL;
new_buf = (uint8_t *)MZ_ALLOC((uint32_t)new_size);
if (new_buf == NULL)
return MZ_BUF_ERROR;
if (mem->buffer) {
memcpy(new_buf, mem->buffer, mem->size);
MZ_FREE(mem->buffer);
}
mem->buffer = new_buf;
mem->size = new_size;
return MZ_OK;
}
int32_t mz_stream_mem_open(void *stream, const char *path, int32_t mode) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
int32_t err = MZ_OK;
MZ_UNUSED(path);
mem->mode = mode;
mem->limit = 0;
mem->position = 0;
if (mem->mode & MZ_OPEN_MODE_CREATE)
err = mz_stream_mem_set_size(stream, mem->grow_size);
else
mem->limit = mem->size;
return err;
}
int32_t mz_stream_mem_is_open(void *stream) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
if (mem->buffer == NULL)
return MZ_OPEN_ERROR;
return MZ_OK;
}
int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
if (size > mem->size - mem->position)
size = mem->size - mem->position;
if (mem->position + size > mem->limit)
size = mem->limit - mem->position;
if (size <= 0)
return 0;
memcpy(buf, mem->buffer + mem->position, size);
mem->position += size;
return size;
}
int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
int32_t new_size = 0;
int32_t err = MZ_OK;
if (size == 0)
return size;
if (size > mem->size - mem->position) {
if (mem->mode & MZ_OPEN_MODE_CREATE) {
new_size = mem->size;
if (size < mem->grow_size)
new_size += mem->grow_size;
else
new_size += size;
err = mz_stream_mem_set_size(stream, new_size);
if (err != MZ_OK)
return err;
} else {
size = mem->size - mem->position;
}
}
memcpy(mem->buffer + mem->position, buf, size);
mem->position += size;
if (mem->position > mem->limit)
mem->limit = mem->position;
return size;
}
int64_t mz_stream_mem_tell(void *stream) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
return mem->position;
}
int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
int64_t new_pos = 0;
int32_t err = MZ_OK;
switch (origin) {
case MZ_SEEK_CUR:
new_pos = mem->position + offset;
break;
case MZ_SEEK_END:
new_pos = mem->limit + offset;
break;
case MZ_SEEK_SET:
new_pos = offset;
break;
default:
return MZ_SEEK_ERROR;
}
if (new_pos > mem->size) {
if ((mem->mode & MZ_OPEN_MODE_CREATE) == 0)
return MZ_SEEK_ERROR;
err = mz_stream_mem_set_size(stream, (int32_t)new_pos);
if (err != MZ_OK)
return err;
} else if (new_pos < 0) {
return MZ_SEEK_ERROR;
}
mem->position = (int32_t)new_pos;
return MZ_OK;
}
int32_t mz_stream_mem_close(void *stream) {
MZ_UNUSED(stream);
/* We never return errors */
return MZ_OK;
}
int32_t mz_stream_mem_error(void *stream) {
MZ_UNUSED(stream);
/* We never return errors */
return MZ_OK;
}
void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
mem->buffer = (uint8_t *)buf;
mem->size = size;
mem->limit = size;
}
int32_t mz_stream_mem_get_buffer(void *stream, const void **buf) {
return mz_stream_mem_get_buffer_at(stream, 0, buf);
}
int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
if (buf == NULL || position < 0 || mem->size < position || mem->buffer == NULL)
return MZ_SEEK_ERROR;
*buf = mem->buffer + position;
return MZ_OK;
}
int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
return mz_stream_mem_get_buffer_at(stream, mem->position, buf);
}
void mz_stream_mem_get_buffer_length(void *stream, int32_t *length) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
*length = mem->limit;
}
void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
mem->limit = limit;
}
void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size) {
mz_stream_mem *mem = (mz_stream_mem *)stream;
mem->grow_size = grow_size;
}
void *mz_stream_mem_create(void **stream) {
mz_stream_mem *mem = NULL;
mem = (mz_stream_mem *)MZ_ALLOC(sizeof(mz_stream_mem));
if (mem != NULL) {
memset(mem, 0, sizeof(mz_stream_mem));
mem->stream.vtbl = &mz_stream_mem_vtbl;
mem->grow_size = 4096;
}
if (stream != NULL)
*stream = mem;
return mem;
}
void mz_stream_mem_delete(void **stream) {
mz_stream_mem *mem = NULL;
if (stream == NULL)
return;
mem = (mz_stream_mem *)*stream;
if (mem != NULL) {
if ((mem->mode & MZ_OPEN_MODE_CREATE) && (mem->buffer != NULL))
MZ_FREE(mem->buffer);
MZ_FREE(mem);
}
*stream = NULL;
}
void *mz_stream_mem_get_interface(void) {
return (void *)&mz_stream_mem_vtbl;
}

48
externals/minizip/mz_strm_mem.h vendored Normal file
View File

@ -0,0 +1,48 @@
/* mz_strm_mem.h -- Stream for memory access
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_MEM_H
#define MZ_STREAM_MEM_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_mem_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_mem_is_open(void *stream);
int32_t mz_stream_mem_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_mem_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_mem_tell(void *stream);
int32_t mz_stream_mem_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_mem_close(void *stream);
int32_t mz_stream_mem_error(void *stream);
void mz_stream_mem_set_buffer(void *stream, void *buf, int32_t size);
int32_t mz_stream_mem_get_buffer(void *stream, const void **buf);
int32_t mz_stream_mem_get_buffer_at(void *stream, int64_t position, const void **buf);
int32_t mz_stream_mem_get_buffer_at_current(void *stream, const void **buf);
void mz_stream_mem_get_buffer_length(void *stream, int32_t *length);
void mz_stream_mem_set_buffer_limit(void *stream, int32_t limit);
void mz_stream_mem_set_grow_size(void *stream, int32_t grow_size);
void* mz_stream_mem_create(void **stream);
void mz_stream_mem_delete(void **stream);
void* mz_stream_mem_get_interface(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

40
externals/minizip/mz_strm_os.h vendored Normal file
View File

@ -0,0 +1,40 @@
/* mz_sstrm_os.h -- Stream for filesystem access
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_OS_H
#define MZ_STREAM_OS_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode);
int32_t mz_stream_os_is_open(void *stream);
int32_t mz_stream_os_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_os_tell(void *stream);
int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_os_close(void *stream);
int32_t mz_stream_os_error(void *stream);
void* mz_stream_os_create(void **stream);
void mz_stream_os_delete(void **stream);
void* mz_stream_os_get_interface(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

206
externals/minizip/mz_strm_os_posix.c vendored Normal file
View File

@ -0,0 +1,206 @@
/* mz_strm_posix.c -- Stream for filesystem access for posix/linux
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Modifications for Zip64 support
Copyright (C) 2009-2010 Mathias Svensson
http://result42.com
Copyright (C) 1998-2010 Gilles Vollant
https://www.winimage.com/zLibDll/minizip.html
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_os.h"
#include <stdio.h> /* fopen, fread.. */
#include <errno.h>
/***************************************************************************/
#define fopen64 fopen
#ifndef MZ_FILE32_API
# ifndef NO_FSEEKO
# define ftello64 ftello
# define fseeko64 fseeko
# elif defined(_MSC_VER) && (_MSC_VER >= 1400)
# define ftello64 _ftelli64
# define fseeko64 _fseeki64
# endif
#endif
#ifndef ftello64
# define ftello64 ftell
#endif
#ifndef fseeko64
# define fseeko64 fseek
#endif
/***************************************************************************/
static mz_stream_vtbl mz_stream_os_vtbl = {
mz_stream_os_open,
mz_stream_os_is_open,
mz_stream_os_read,
mz_stream_os_write,
mz_stream_os_tell,
mz_stream_os_seek,
mz_stream_os_close,
mz_stream_os_error,
mz_stream_os_create,
mz_stream_os_delete,
NULL,
NULL
};
/***************************************************************************/
typedef struct mz_stream_posix_s {
mz_stream stream;
int32_t error;
FILE *handle;
} mz_stream_posix;
/***************************************************************************/
int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) {
mz_stream_posix *posix = (mz_stream_posix *)stream;
const char *mode_fopen = NULL;
if (path == NULL)
return MZ_PARAM_ERROR;
if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ)
mode_fopen = "rb";
else if (mode & MZ_OPEN_MODE_APPEND)
mode_fopen = "r+b";
else if (mode & MZ_OPEN_MODE_CREATE)
mode_fopen = "wb";
else
return MZ_OPEN_ERROR;
posix->handle = fopen64(path, mode_fopen);
if (posix->handle == NULL) {
posix->error = errno;
return MZ_OPEN_ERROR;
}
if (mode & MZ_OPEN_MODE_APPEND)
return mz_stream_os_seek(stream, 0, MZ_SEEK_END);
return MZ_OK;
}
int32_t mz_stream_os_is_open(void *stream) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
if (posix->handle == NULL)
return MZ_OPEN_ERROR;
return MZ_OK;
}
int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
int32_t read = (int32_t)fread(buf, 1, (size_t)size, posix->handle);
if (read < size && ferror(posix->handle)) {
posix->error = errno;
return MZ_READ_ERROR;
}
return read;
}
int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
int32_t written = (int32_t)fwrite(buf, 1, (size_t)size, posix->handle);
if (written < size && ferror(posix->handle)) {
posix->error = errno;
return MZ_WRITE_ERROR;
}
return written;
}
int64_t mz_stream_os_tell(void *stream) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
int64_t position = ftello64(posix->handle);
if (position == -1) {
posix->error = errno;
return MZ_TELL_ERROR;
}
return position;
}
int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
int32_t fseek_origin = 0;
switch (origin) {
case MZ_SEEK_CUR:
fseek_origin = SEEK_CUR;
break;
case MZ_SEEK_END:
fseek_origin = SEEK_END;
break;
case MZ_SEEK_SET:
fseek_origin = SEEK_SET;
break;
default:
return MZ_SEEK_ERROR;
}
if (fseeko64(posix->handle, offset, fseek_origin) != 0) {
posix->error = errno;
return MZ_SEEK_ERROR;
}
return MZ_OK;
}
int32_t mz_stream_os_close(void *stream) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
int32_t closed = 0;
if (posix->handle != NULL) {
closed = fclose(posix->handle);
posix->handle = NULL;
}
if (closed != 0) {
posix->error = errno;
return MZ_CLOSE_ERROR;
}
return MZ_OK;
}
int32_t mz_stream_os_error(void *stream) {
mz_stream_posix *posix = (mz_stream_posix*)stream;
return posix->error;
}
void *mz_stream_os_create(void **stream) {
mz_stream_posix *posix = NULL;
posix = (mz_stream_posix *)MZ_ALLOC(sizeof(mz_stream_posix));
if (posix != NULL) {
memset(posix, 0, sizeof(mz_stream_posix));
posix->stream.vtbl = &mz_stream_os_vtbl;
}
if (stream != NULL)
*stream = posix;
return posix;
}
void mz_stream_os_delete(void **stream) {
mz_stream_posix *posix = NULL;
if (stream == NULL)
return;
posix = (mz_stream_posix *)*stream;
if (posix != NULL)
MZ_FREE(posix);
*stream = NULL;
}
void *mz_stream_os_get_interface(void) {
return (void *)&mz_stream_os_vtbl;
}

296
externals/minizip/mz_strm_os_win32.c vendored Normal file
View File

@ -0,0 +1,296 @@
/* mz_strm_win32.c -- Stream for filesystem access for windows
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 2009-2010 Mathias Svensson
Modifications for Zip64 support
http://result42.com
Copyright (C) 1998-2010 Gilles Vollant
https://www.winimage.com/zLibDll/minizip.html
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include "mz_strm.h"
#include "mz_strm_os.h"
#include <windows.h>
/***************************************************************************/
#ifndef INVALID_HANDLE_VALUE
# define INVALID_HANDLE_VALUE (0xFFFFFFFF)
#endif
#ifndef INVALID_SET_FILE_POINTER
# define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
#if defined(WINAPI_FAMILY_ONE_PARTITION) && !defined(MZ_WINRT_API)
# if WINAPI_FAMILY_ONE_PARTITION(WINAPI_FAMILY, WINAPI_PARTITION_APP)
# define MZ_WINRT_API 1
# endif
#endif
/***************************************************************************/
static mz_stream_vtbl mz_stream_os_vtbl = {
mz_stream_os_open,
mz_stream_os_is_open,
mz_stream_os_read,
mz_stream_os_write,
mz_stream_os_tell,
mz_stream_os_seek,
mz_stream_os_close,
mz_stream_os_error,
mz_stream_os_create,
mz_stream_os_delete,
NULL,
NULL
};
/***************************************************************************/
typedef struct mz_stream_win32_s {
mz_stream stream;
HANDLE handle;
int32_t error;
} mz_stream_win32;
/***************************************************************************/
#if 0
# define mz_stream_os_print printf
#else
# define mz_stream_os_print(fmt,...)
#endif
/***************************************************************************/
int32_t mz_stream_os_open(void *stream, const char *path, int32_t mode) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
uint32_t desired_access = 0;
uint32_t creation_disposition = 0;
uint32_t share_mode = FILE_SHARE_READ;
uint32_t flags_attribs = FILE_ATTRIBUTE_NORMAL;
wchar_t *path_wide = NULL;
if (path == NULL)
return MZ_PARAM_ERROR;
/* Some use cases require write sharing as well */
share_mode |= FILE_SHARE_WRITE;
if ((mode & MZ_OPEN_MODE_READWRITE) == MZ_OPEN_MODE_READ) {
desired_access = GENERIC_READ;
creation_disposition = OPEN_EXISTING;
} else if (mode & MZ_OPEN_MODE_APPEND) {
desired_access = GENERIC_WRITE | GENERIC_READ;
creation_disposition = OPEN_EXISTING;
} else if (mode & MZ_OPEN_MODE_CREATE) {
desired_access = GENERIC_WRITE | GENERIC_READ;
creation_disposition = CREATE_ALWAYS;
} else {
return MZ_PARAM_ERROR;
}
mz_stream_os_print("Win32 - Open - %s (mode %" PRId32 ")\n", path);
path_wide = mz_os_unicode_string_create(path, MZ_ENCODING_UTF8);
if (path_wide == NULL)
return MZ_PARAM_ERROR;
#ifdef MZ_WINRT_API
win32->handle = CreateFile2(path_wide, desired_access, share_mode,
creation_disposition, NULL);
#else
win32->handle = CreateFileW(path_wide, desired_access, share_mode, NULL,
creation_disposition, flags_attribs, NULL);
#endif
mz_os_unicode_string_delete(&path_wide);
if (mz_stream_os_is_open(stream) != MZ_OK) {
win32->error = GetLastError();
return MZ_OPEN_ERROR;
}
if (mode & MZ_OPEN_MODE_APPEND)
return mz_stream_os_seek(stream, 0, MZ_SEEK_END);
return MZ_OK;
}
int32_t mz_stream_os_is_open(void *stream) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
if (win32->handle == NULL || win32->handle == INVALID_HANDLE_VALUE)
return MZ_OPEN_ERROR;
return MZ_OK;
}
int32_t mz_stream_os_read(void *stream, void *buf, int32_t size) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
uint32_t read = 0;
if (mz_stream_os_is_open(stream) != MZ_OK)
return MZ_OPEN_ERROR;
if (!ReadFile(win32->handle, buf, size, (DWORD *)&read, NULL)) {
win32->error = GetLastError();
if (win32->error == ERROR_HANDLE_EOF)
win32->error = 0;
}
mz_stream_os_print("Win32 - Read - %" PRId32 "\n", read);
return read;
}
int32_t mz_stream_os_write(void *stream, const void *buf, int32_t size) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
int32_t written = 0;
if (mz_stream_os_is_open(stream) != MZ_OK)
return MZ_OPEN_ERROR;
if (!WriteFile(win32->handle, buf, size, (DWORD *)&written, NULL)) {
win32->error = GetLastError();
if (win32->error == ERROR_HANDLE_EOF)
win32->error = 0;
}
mz_stream_os_print("Win32 - Write - %" PRId32 "\n", written);
return written;
}
static int32_t mz_stream_os_seekinternal(HANDLE handle, LARGE_INTEGER large_pos,
LARGE_INTEGER *new_pos, uint32_t move_method) {
#ifdef MZ_WINRT_API
BOOL success = FALSE;
success = SetFilePointerEx(handle, large_pos, new_pos, move_method);
if ((success == FALSE) && (GetLastError() != NO_ERROR))
return MZ_SEEK_ERROR;
return MZ_OK;
#else
LONG high_part = 0;
uint32_t pos = 0;
high_part = large_pos.HighPart;
pos = SetFilePointer(handle, large_pos.LowPart, &high_part, move_method);
if ((pos == INVALID_SET_FILE_POINTER) && (GetLastError() != NO_ERROR))
return MZ_SEEK_ERROR;
if (new_pos != NULL) {
new_pos->LowPart = pos;
new_pos->HighPart = high_part;
}
return MZ_OK;
#endif
}
int64_t mz_stream_os_tell(void *stream) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
LARGE_INTEGER large_pos;
if (mz_stream_os_is_open(stream) != MZ_OK)
return MZ_OPEN_ERROR;
large_pos.QuadPart = 0;
if (mz_stream_os_seekinternal(win32->handle, large_pos, &large_pos, FILE_CURRENT) != MZ_OK)
win32->error = GetLastError();
mz_stream_os_print("Win32 - Tell - %" PRId64 "\n", large_pos.QuadPart);
return large_pos.QuadPart;
}
int32_t mz_stream_os_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
uint32_t move_method = 0xFFFFFFFF;
int32_t err = MZ_OK;
LARGE_INTEGER large_pos;
if (mz_stream_os_is_open(stream) != MZ_OK)
return MZ_OPEN_ERROR;
switch (origin) {
case MZ_SEEK_CUR:
move_method = FILE_CURRENT;
break;
case MZ_SEEK_END:
move_method = FILE_END;
break;
case MZ_SEEK_SET:
move_method = FILE_BEGIN;
break;
default:
return MZ_SEEK_ERROR;
}
mz_stream_os_print("Win32 - Seek - %" PRId64 " (origin %" PRId32 ")\n", offset, origin);
large_pos.QuadPart = offset;
err = mz_stream_os_seekinternal(win32->handle, large_pos, NULL, move_method);
if (err != MZ_OK) {
win32->error = GetLastError();
return err;
}
return MZ_OK;
}
int32_t mz_stream_os_close(void *stream) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
if (win32->handle != NULL)
CloseHandle(win32->handle);
mz_stream_os_print("Win32 - Close\n");
win32->handle = NULL;
return MZ_OK;
}
int32_t mz_stream_os_error(void *stream) {
mz_stream_win32 *win32 = (mz_stream_win32 *)stream;
return win32->error;
}
void *mz_stream_os_create(void **stream) {
mz_stream_win32 *win32 = NULL;
win32 = (mz_stream_win32 *)MZ_ALLOC(sizeof(mz_stream_win32));
if (win32 != NULL) {
memset(win32, 0, sizeof(mz_stream_win32));
win32->stream.vtbl = &mz_stream_os_vtbl;
}
if (stream != NULL)
*stream = win32;
return win32;
}
void mz_stream_os_delete(void **stream) {
mz_stream_win32 *win32 = NULL;
if (stream == NULL)
return;
win32 = (mz_stream_win32 *)*stream;
if (win32 != NULL)
MZ_FREE(win32);
*stream = NULL;
}
void *mz_stream_os_get_interface(void) {
return (void *)&mz_stream_os_vtbl;
}

338
externals/minizip/mz_strm_pkcrypt.c vendored Normal file
View File

@ -0,0 +1,338 @@
/* mz_strm_pkcrypt.c -- Code for traditional PKWARE encryption
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 1998-2005 Gilles Vollant
Modifications for Info-ZIP crypting
https://www.winimage.com/zLibDll/minizip.html
Copyright (C) 2003 Terry Thorsen
This code is a modified version of crypting code in Info-ZIP distribution
Copyright (C) 1990-2000 Info-ZIP. All rights reserved.
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities).
*/
#include "mz.h"
#include "mz_crypt.h"
#include "mz_strm.h"
#include "mz_strm_pkcrypt.h"
/***************************************************************************/
static mz_stream_vtbl mz_stream_pkcrypt_vtbl = {
mz_stream_pkcrypt_open,
mz_stream_pkcrypt_is_open,
mz_stream_pkcrypt_read,
mz_stream_pkcrypt_write,
mz_stream_pkcrypt_tell,
mz_stream_pkcrypt_seek,
mz_stream_pkcrypt_close,
mz_stream_pkcrypt_error,
mz_stream_pkcrypt_create,
mz_stream_pkcrypt_delete,
mz_stream_pkcrypt_get_prop_int64,
mz_stream_pkcrypt_set_prop_int64
};
/***************************************************************************/
typedef struct mz_stream_pkcrypt_s {
mz_stream stream;
int32_t error;
int16_t initialized;
uint8_t buffer[UINT16_MAX];
int64_t total_in;
int64_t max_total_in;
int64_t total_out;
uint32_t keys[3]; /* keys defining the pseudo-random sequence */
uint8_t verify1;
uint8_t verify2;
const char *password;
} mz_stream_pkcrypt;
/***************************************************************************/
#define mz_stream_pkcrypt_decode(strm, c) \
(mz_stream_pkcrypt_update_keys(strm, \
c ^= mz_stream_pkcrypt_decrypt_byte(strm)))
#define mz_stream_pkcrypt_encode(strm, c, t) \
(t = mz_stream_pkcrypt_decrypt_byte(strm), \
mz_stream_pkcrypt_update_keys(strm, (uint8_t)c), (uint8_t)(t^(c)))
/***************************************************************************/
static uint8_t mz_stream_pkcrypt_decrypt_byte(void *stream) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an */
/* unpredictable manner on 16-bit systems; not a problem */
/* with any known compiler so far, though. */
temp = pkcrypt->keys[2] | 2;
return (uint8_t)(((temp * (temp ^ 1)) >> 8) & 0xff);
}
static uint8_t mz_stream_pkcrypt_update_keys(void *stream, uint8_t c) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
uint8_t buf = c;
pkcrypt->keys[0] = (uint32_t)~mz_crypt_crc32_update(~pkcrypt->keys[0], &buf, 1);
pkcrypt->keys[1] += pkcrypt->keys[0] & 0xff;
pkcrypt->keys[1] *= 134775813L;
pkcrypt->keys[1] += 1;
buf = (uint8_t)(pkcrypt->keys[1] >> 24);
pkcrypt->keys[2] = (uint32_t)~mz_crypt_crc32_update(~pkcrypt->keys[2], &buf, 1);
return (uint8_t)c;
}
static void mz_stream_pkcrypt_init_keys(void *stream, const char *password) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
pkcrypt->keys[0] = 305419896L;
pkcrypt->keys[1] = 591751049L;
pkcrypt->keys[2] = 878082192L;
while (*password != 0) {
mz_stream_pkcrypt_update_keys(stream, (uint8_t)*password);
password += 1;
}
}
/***************************************************************************/
int32_t mz_stream_pkcrypt_open(void *stream, const char *path, int32_t mode) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
uint16_t t = 0;
int16_t i = 0;
uint8_t verify1 = 0;
uint8_t verify2 = 0;
uint8_t header[MZ_PKCRYPT_HEADER_SIZE];
const char *password = path;
pkcrypt->total_in = 0;
pkcrypt->total_out = 0;
pkcrypt->initialized = 0;
if (mz_stream_is_open(pkcrypt->stream.base) != MZ_OK)
return MZ_OPEN_ERROR;
if (password == NULL)
password = pkcrypt->password;
if (password == NULL)
return MZ_PARAM_ERROR;
mz_stream_pkcrypt_init_keys(stream, password);
if (mode & MZ_OPEN_MODE_WRITE) {
/* First generate RAND_HEAD_LEN - 2 random bytes. */
mz_crypt_rand(header, MZ_PKCRYPT_HEADER_SIZE - 2);
/* Encrypt random header (last two bytes is high word of crc) */
for (i = 0; i < MZ_PKCRYPT_HEADER_SIZE - 2; i++)
header[i] = mz_stream_pkcrypt_encode(stream, header[i], t);
header[i++] = mz_stream_pkcrypt_encode(stream, pkcrypt->verify1, t);
header[i++] = mz_stream_pkcrypt_encode(stream, pkcrypt->verify2, t);
if (mz_stream_write(pkcrypt->stream.base, header, sizeof(header)) != sizeof(header))
return MZ_WRITE_ERROR;
pkcrypt->total_out += MZ_PKCRYPT_HEADER_SIZE;
} else if (mode & MZ_OPEN_MODE_READ) {
if (mz_stream_read(pkcrypt->stream.base, header, sizeof(header)) != sizeof(header))
return MZ_READ_ERROR;
for (i = 0; i < MZ_PKCRYPT_HEADER_SIZE - 2; i++)
header[i] = mz_stream_pkcrypt_decode(stream, header[i]);
verify1 = mz_stream_pkcrypt_decode(stream, header[i++]);
verify2 = mz_stream_pkcrypt_decode(stream, header[i++]);
/* Older versions used 2 byte check, newer versions use 1 byte check. */
MZ_UNUSED(verify1);
if ((verify2 != 0) && (verify2 != pkcrypt->verify2))
return MZ_PASSWORD_ERROR;
pkcrypt->total_in += MZ_PKCRYPT_HEADER_SIZE;
}
pkcrypt->initialized = 1;
return MZ_OK;
}
int32_t mz_stream_pkcrypt_is_open(void *stream) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
if (pkcrypt->initialized == 0)
return MZ_OPEN_ERROR;
return MZ_OK;
}
int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
uint8_t *buf_ptr = (uint8_t *)buf;
int32_t bytes_to_read = size;
int32_t read = 0;
int32_t i = 0;
if ((int64_t)bytes_to_read > (pkcrypt->max_total_in - pkcrypt->total_in))
bytes_to_read = (int32_t)(pkcrypt->max_total_in - pkcrypt->total_in);
read = mz_stream_read(pkcrypt->stream.base, buf, bytes_to_read);
for (i = 0; i < read; i++)
buf_ptr[i] = mz_stream_pkcrypt_decode(stream, buf_ptr[i]);
if (read > 0)
pkcrypt->total_in += read;
return read;
}
int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
const uint8_t *buf_ptr = (const uint8_t *)buf;
int32_t bytes_to_write = sizeof(pkcrypt->buffer);
int32_t total_written = 0;
int32_t written = 0;
int32_t i = 0;
uint16_t t = 0;
if (size < 0)
return MZ_PARAM_ERROR;
do {
if (bytes_to_write > (size - total_written))
bytes_to_write = (size - total_written);
for (i = 0; i < bytes_to_write; i += 1) {
pkcrypt->buffer[i] = mz_stream_pkcrypt_encode(stream, *buf_ptr, t);
buf_ptr += 1;
}
written = mz_stream_write(pkcrypt->stream.base, pkcrypt->buffer, bytes_to_write);
if (written < 0)
return written;
total_written += written;
} while (total_written < size && written > 0);
pkcrypt->total_out += total_written;
return total_written;
}
int64_t mz_stream_pkcrypt_tell(void *stream) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
return mz_stream_tell(pkcrypt->stream.base);
}
int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
return mz_stream_seek(pkcrypt->stream.base, offset, origin);
}
int32_t mz_stream_pkcrypt_close(void *stream) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
pkcrypt->initialized = 0;
return MZ_OK;
}
int32_t mz_stream_pkcrypt_error(void *stream) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
return pkcrypt->error;
}
void mz_stream_pkcrypt_set_password(void *stream, const char *password) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
pkcrypt->password = password;
}
void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
pkcrypt->verify1 = verify1;
pkcrypt->verify2 = verify2;
}
void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
*verify1 = pkcrypt->verify1;
*verify2 = pkcrypt->verify2;
}
int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = pkcrypt->total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = pkcrypt->total_out;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = pkcrypt->max_total_in;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = MZ_PKCRYPT_HEADER_SIZE;
break;
case MZ_STREAM_PROP_FOOTER_SIZE:
*value = 0;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_pkcrypt *pkcrypt = (mz_stream_pkcrypt *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN_MAX:
pkcrypt->max_total_in = value;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
void *mz_stream_pkcrypt_create(void **stream) {
mz_stream_pkcrypt *pkcrypt = NULL;
pkcrypt = (mz_stream_pkcrypt *)MZ_ALLOC(sizeof(mz_stream_pkcrypt));
if (pkcrypt != NULL) {
memset(pkcrypt, 0, sizeof(mz_stream_pkcrypt));
pkcrypt->stream.vtbl = &mz_stream_pkcrypt_vtbl;
}
if (stream != NULL)
*stream = pkcrypt;
return pkcrypt;
}
void mz_stream_pkcrypt_delete(void **stream) {
mz_stream_pkcrypt *pkcrypt = NULL;
if (stream == NULL)
return;
pkcrypt = (mz_stream_pkcrypt *)*stream;
if (pkcrypt != NULL)
MZ_FREE(pkcrypt);
*stream = NULL;
}
void *mz_stream_pkcrypt_get_interface(void) {
return (void *)&mz_stream_pkcrypt_vtbl;
}

46
externals/minizip/mz_strm_pkcrypt.h vendored Normal file
View File

@ -0,0 +1,46 @@
/* mz_strm_pkcrypt.h -- Code for traditional PKWARE encryption
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_PKCRYPT_H
#define MZ_STREAM_PKCRYPT_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_pkcrypt_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_pkcrypt_is_open(void *stream);
int32_t mz_stream_pkcrypt_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_pkcrypt_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_pkcrypt_tell(void *stream);
int32_t mz_stream_pkcrypt_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_pkcrypt_close(void *stream);
int32_t mz_stream_pkcrypt_error(void *stream);
void mz_stream_pkcrypt_set_password(void *stream, const char *password);
void mz_stream_pkcrypt_set_verify(void *stream, uint8_t verify1, uint8_t verify2);
void mz_stream_pkcrypt_get_verify(void *stream, uint8_t *verify1, uint8_t *verify2);
int32_t mz_stream_pkcrypt_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_pkcrypt_set_prop_int64(void *stream, int32_t prop, int64_t value);
void* mz_stream_pkcrypt_create(void **stream);
void mz_stream_pkcrypt_delete(void **stream);
void* mz_stream_pkcrypt_get_interface(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

438
externals/minizip/mz_strm_split.c vendored Normal file
View File

@ -0,0 +1,438 @@
/* mz_strm_split.c -- Stream for split files
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_os.h"
#include "mz_strm.h"
#include "mz_strm_split.h"
#include <stdio.h> /* snprintf */
#if defined(_MSC_VER) && (_MSC_VER < 1900)
# define snprintf _snprintf
#endif
/***************************************************************************/
#define MZ_ZIP_MAGIC_DISKHEADER (0x08074b50)
/***************************************************************************/
static mz_stream_vtbl mz_stream_split_vtbl = {
mz_stream_split_open,
mz_stream_split_is_open,
mz_stream_split_read,
mz_stream_split_write,
mz_stream_split_tell,
mz_stream_split_seek,
mz_stream_split_close,
mz_stream_split_error,
mz_stream_split_create,
mz_stream_split_delete,
mz_stream_split_get_prop_int64,
mz_stream_split_set_prop_int64
};
/***************************************************************************/
typedef struct mz_stream_split_s {
mz_stream stream;
int32_t is_open;
int64_t disk_size;
int64_t total_in;
int64_t total_in_disk;
int64_t total_out;
int64_t total_out_disk;
int32_t mode;
char *path_cd;
uint32_t path_cd_size;
char *path_disk;
uint32_t path_disk_size;
int32_t number_disk;
int32_t current_disk;
int64_t current_disk_size;
int32_t reached_end;
} mz_stream_split;
/***************************************************************************/
#if 0
# define mz_stream_split_print printf
#else
# define mz_stream_split_print(fmt,...)
#endif
/***************************************************************************/
static int32_t mz_stream_split_open_disk(void *stream, int32_t number_disk) {
mz_stream_split *split = (mz_stream_split *)stream;
uint32_t magic = 0;
int64_t position = 0;
int32_t i = 0;
int32_t err = MZ_OK;
int16_t disk_part = 0;
/* Check if we are reading or writing a disk part or the cd disk */
if (number_disk >= 0) {
if ((split->mode & MZ_OPEN_MODE_WRITE) == 0)
disk_part = MZ_OPEN_MODE_READ;
else if (split->disk_size > 0)
disk_part = MZ_OPEN_MODE_WRITE;
}
/* Construct disk path */
if (disk_part > 0) {
for (i = (int32_t)strlen(split->path_disk) - 1; i >= 0; i -= 1) {
if (split->path_disk[i] != '.')
continue;
snprintf(&split->path_disk[i], split->path_disk_size - (uint32_t)i,
".z%02" PRId32, number_disk + 1);
break;
}
} else {
strncpy(split->path_disk, split->path_cd, split->path_disk_size - 1);
split->path_disk[split->path_disk_size - 1] = 0;
}
mz_stream_split_print("Split - Goto disk - %s (disk %" PRId32 ")\n", split->path_disk, number_disk);
/* If disk part doesn't exist during reading then return MZ_EXIST_ERROR */
if (disk_part == MZ_OPEN_MODE_READ)
err = mz_os_file_exists(split->path_disk);
if (err == MZ_OK)
err = mz_stream_open(split->stream.base, split->path_disk, split->mode);
if (err == MZ_OK) {
split->total_in_disk = 0;
split->total_out_disk = 0;
split->current_disk = number_disk;
if (split->mode & MZ_OPEN_MODE_WRITE) {
if ((split->current_disk == 0) && (split->disk_size > 0)) {
err = mz_stream_write_uint32(split->stream.base, MZ_ZIP_MAGIC_DISKHEADER);
split->total_out_disk += 4;
split->total_out += split->total_out_disk;
}
} else if (split->mode & MZ_OPEN_MODE_READ) {
if (split->current_disk == 0) {
err = mz_stream_read_uint32(split->stream.base, &magic);
if (magic != MZ_ZIP_MAGIC_DISKHEADER)
err = MZ_FORMAT_ERROR;
}
}
}
if (err == MZ_OK) {
/* Get the size of the current disk we are on */
position = mz_stream_tell(split->stream.base);
mz_stream_seek(split->stream.base, 0, MZ_SEEK_END);
split->current_disk_size = mz_stream_tell(split->stream.base);
mz_stream_seek(split->stream.base, position, MZ_SEEK_SET);
split->is_open = 1;
}
return err;
}
static int32_t mz_stream_split_close_disk(void *stream) {
mz_stream_split *split = (mz_stream_split *)stream;
if (mz_stream_is_open(split->stream.base) != MZ_OK)
return MZ_OK;
mz_stream_split_print("Split - Close disk\n");
return mz_stream_close(split->stream.base);
}
static int32_t mz_stream_split_goto_disk(void *stream, int32_t number_disk) {
mz_stream_split *split = (mz_stream_split *)stream;
int32_t err = MZ_OK;
int32_t err_is_open = MZ_OK;
err_is_open = mz_stream_is_open(split->stream.base);
if ((split->disk_size == 0) && (split->mode & MZ_OPEN_MODE_WRITE)) {
if (err_is_open != MZ_OK)
err = mz_stream_split_open_disk(stream, number_disk);
} else if ((number_disk != split->current_disk) || (err_is_open != MZ_OK)) {
err = mz_stream_split_close_disk(stream);
if (err == MZ_OK) {
err = mz_stream_split_open_disk(stream, number_disk);
if (err == MZ_OK)
split->number_disk = number_disk;
}
}
return err;
}
int32_t mz_stream_split_open(void *stream, const char *path, int32_t mode) {
mz_stream_split *split = (mz_stream_split *)stream;
int32_t number_disk = 0;
split->mode = mode;
split->path_cd_size = (uint32_t)strlen(path) + 1;
split->path_cd = (char *)MZ_ALLOC(split->path_cd_size);
if (split->path_cd == NULL)
return MZ_MEM_ERROR;
strncpy(split->path_cd, path, split->path_cd_size - 1);
split->path_cd[split->path_cd_size - 1] = 0;
mz_stream_split_print("Split - Open - %s (disk %" PRId32 ")\n", split->path_cd, number_disk);
split->path_disk_size = (uint32_t)strlen(path) + 10;
split->path_disk = (char *)MZ_ALLOC(split->path_disk_size);
if (split->path_disk == NULL) {
MZ_FREE(split->path_cd);
return MZ_MEM_ERROR;
}
strncpy(split->path_disk, path, split->path_disk_size - 1);
split->path_disk[split->path_disk_size - 1] = 0;
if ((mode & MZ_OPEN_MODE_WRITE) && ((mode & MZ_OPEN_MODE_APPEND) == 0)) {
number_disk = 0;
split->current_disk = -1;
} else {
number_disk = -1;
split->current_disk = 0;
}
return mz_stream_split_goto_disk(stream, number_disk);
}
int32_t mz_stream_split_is_open(void *stream) {
mz_stream_split *split = (mz_stream_split *)stream;
if (split->is_open != 1)
return MZ_OPEN_ERROR;
return MZ_OK;
}
int32_t mz_stream_split_read(void *stream, void *buf, int32_t size) {
mz_stream_split *split = (mz_stream_split *)stream;
int32_t bytes_left = size;
int32_t read = 0;
int32_t err = MZ_OK;
uint8_t *buf_ptr = (uint8_t *)buf;
err = mz_stream_split_goto_disk(stream, split->number_disk);
if (err != MZ_OK)
return err;
while (bytes_left > 0) {
read = mz_stream_read(split->stream.base, buf_ptr, bytes_left);
mz_stream_split_print("Split - Read disk - %" PRId32 "\n", read);
if (read < 0)
return read;
if (read == 0) {
if (split->current_disk < 0) /* No more disks to goto */
break;
err = mz_stream_split_goto_disk(stream, split->current_disk + 1);
if (err == MZ_EXIST_ERROR) {
split->current_disk = -1;
break;
}
if (err != MZ_OK)
return err;
}
bytes_left -= read;
buf_ptr += read;
split->total_in += read;
split->total_in_disk += read;
}
return size - bytes_left;
}
int32_t mz_stream_split_write(void *stream, const void *buf, int32_t size) {
mz_stream_split *split = (mz_stream_split *)stream;
int64_t position = 0;
int32_t written = 0;
int32_t bytes_left = size;
int32_t bytes_to_write = 0;
int32_t bytes_avail = 0;
int32_t number_disk = -1;
int32_t err = MZ_OK;
const uint8_t *buf_ptr = (const uint8_t *)buf;
position = mz_stream_tell(split->stream.base);
while (bytes_left > 0) {
bytes_to_write = bytes_left;
if (split->disk_size > 0) {
if ((split->total_out_disk == split->disk_size && split->total_out > 0) ||
(split->number_disk == -1 && split->number_disk != split->current_disk)) {
if (split->number_disk != -1)
number_disk = split->current_disk + 1;
err = mz_stream_split_goto_disk(stream, number_disk);
if (err != MZ_OK)
return err;
}
if (split->number_disk != -1) {
bytes_avail = (int32_t)(split->disk_size - split->total_out_disk);
if (bytes_to_write > bytes_avail)
bytes_to_write = bytes_avail;
}
}
written = mz_stream_write(split->stream.base, buf_ptr, bytes_to_write);
if (written != bytes_to_write)
return MZ_WRITE_ERROR;
mz_stream_split_print("Split - Write disk - %" PRId32 "\n", written);
bytes_left -= written;
buf_ptr += written;
split->total_out += written;
split->total_out_disk += written;
if (position == split->current_disk_size) {
split->current_disk_size += written;
position = split->current_disk_size;
}
}
return size - bytes_left;
}
int64_t mz_stream_split_tell(void *stream) {
mz_stream_split *split = (mz_stream_split *)stream;
int32_t err = MZ_OK;
err = mz_stream_split_goto_disk(stream, split->number_disk);
if (err != MZ_OK)
return err;
return mz_stream_tell(split->stream.base);
}
int32_t mz_stream_split_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_split *split = (mz_stream_split *)stream;
int64_t disk_left = 0;
int64_t position = 0;
int32_t err = MZ_OK;
err = mz_stream_split_goto_disk(stream, split->number_disk);
if (err != MZ_OK)
return err;
mz_stream_split_print("Split - Seek disk - %" PRId64 " (origin %" PRId32 ")\n", offset, origin);
if ((origin == MZ_SEEK_CUR) && (split->number_disk != -1)) {
position = mz_stream_tell(split->stream.base);
disk_left = split->current_disk_size - position;
while (offset > disk_left) {
err = mz_stream_split_goto_disk(stream, split->current_disk + 1);
if (err != MZ_OK)
return err;
offset -= disk_left;
disk_left = split->current_disk_size;
}
}
return mz_stream_seek(split->stream.base, offset, origin);
}
int32_t mz_stream_split_close(void *stream) {
mz_stream_split *split = (mz_stream_split *)stream;
int32_t err = MZ_OK;
err = mz_stream_split_close_disk(stream);
split->is_open = 0;
return err;
}
int32_t mz_stream_split_error(void *stream) {
mz_stream_split *split = (mz_stream_split *)stream;
return mz_stream_error(split->stream.base);
}
int32_t mz_stream_split_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_split *split = (mz_stream_split *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_OUT:
*value = split->total_out;
break;
case MZ_STREAM_PROP_DISK_NUMBER:
*value = split->number_disk;
break;
case MZ_STREAM_PROP_DISK_SIZE:
*value = split->disk_size;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_split *split = (mz_stream_split *)stream;
switch (prop) {
case MZ_STREAM_PROP_DISK_NUMBER:
split->number_disk = (int32_t)value;
break;
case MZ_STREAM_PROP_DISK_SIZE:
split->disk_size = value;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
void *mz_stream_split_create(void **stream) {
mz_stream_split *split = NULL;
split = (mz_stream_split *)MZ_ALLOC(sizeof(mz_stream_split));
if (split != NULL) {
memset(split, 0, sizeof(mz_stream_split));
split->stream.vtbl = &mz_stream_split_vtbl;
}
if (stream != NULL)
*stream = split;
return split;
}
void mz_stream_split_delete(void **stream) {
mz_stream_split *split = NULL;
if (stream == NULL)
return;
split = (mz_stream_split *)*stream;
if (split != NULL) {
if (split->path_cd)
MZ_FREE(split->path_cd);
if (split->path_disk)
MZ_FREE(split->path_disk);
MZ_FREE(split);
}
*stream = NULL;
}
void *mz_stream_split_get_interface(void) {
return (void *)&mz_stream_split_vtbl;
}

43
externals/minizip/mz_strm_split.h vendored Normal file
View File

@ -0,0 +1,43 @@
/* mz_strm_split.h -- Stream for split files
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_SPLIT_H
#define MZ_STREAM_SPLIT_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_split_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_split_is_open(void *stream);
int32_t mz_stream_split_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_split_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_split_tell(void *stream);
int32_t mz_stream_split_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_split_close(void *stream);
int32_t mz_stream_split_error(void *stream);
int32_t mz_stream_split_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_split_set_prop_int64(void *stream, int32_t prop, int64_t value);
void* mz_stream_split_create(void **stream);
void mz_stream_split_delete(void **stream);
void* mz_stream_split_get_interface(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

362
externals/minizip/mz_strm_wzaes.c vendored Normal file
View File

@ -0,0 +1,362 @@
/* mz_strm_wzaes.c -- Stream for WinZip AES encryption
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 1998-2010 Brian Gladman, Worcester, UK
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_crypt.h"
#include "mz_strm.h"
#include "mz_strm_wzaes.h"
/***************************************************************************/
#define MZ_AES_KEYING_ITERATIONS (1000)
#define MZ_AES_SALT_LENGTH(MODE) (4 * (MODE & 3) + 4)
#define MZ_AES_SALT_LENGTH_MAX (16)
#define MZ_AES_PW_LENGTH_MAX (128)
#define MZ_AES_PW_VERIFY_SIZE (2)
#define MZ_AES_AUTHCODE_SIZE (10)
/***************************************************************************/
static mz_stream_vtbl mz_stream_wzaes_vtbl = {
mz_stream_wzaes_open,
mz_stream_wzaes_is_open,
mz_stream_wzaes_read,
mz_stream_wzaes_write,
mz_stream_wzaes_tell,
mz_stream_wzaes_seek,
mz_stream_wzaes_close,
mz_stream_wzaes_error,
mz_stream_wzaes_create,
mz_stream_wzaes_delete,
mz_stream_wzaes_get_prop_int64,
mz_stream_wzaes_set_prop_int64
};
/***************************************************************************/
typedef struct mz_stream_wzaes_s {
mz_stream stream;
int32_t mode;
int32_t error;
int16_t initialized;
uint8_t buffer[UINT16_MAX];
int64_t total_in;
int64_t max_total_in;
int64_t total_out;
int16_t encryption_mode;
const char *password;
void *aes;
uint32_t crypt_pos;
uint8_t crypt_block[MZ_AES_BLOCK_SIZE];
void *hmac;
uint8_t nonce[MZ_AES_BLOCK_SIZE];
} mz_stream_wzaes;
/***************************************************************************/
int32_t mz_stream_wzaes_open(void *stream, const char *path, int32_t mode) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
uint16_t salt_length = 0;
uint16_t password_length = 0;
uint16_t key_length = 0;
uint8_t kbuf[2 * MZ_AES_KEY_LENGTH_MAX + MZ_AES_PW_VERIFY_SIZE];
uint8_t verify[MZ_AES_PW_VERIFY_SIZE];
uint8_t verify_expected[MZ_AES_PW_VERIFY_SIZE];
uint8_t salt_value[MZ_AES_SALT_LENGTH_MAX];
const char *password = path;
wzaes->total_in = 0;
wzaes->total_out = 0;
wzaes->initialized = 0;
if (mz_stream_is_open(wzaes->stream.base) != MZ_OK)
return MZ_OPEN_ERROR;
if (password == NULL)
password = wzaes->password;
if (password == NULL)
return MZ_PARAM_ERROR;
password_length = (uint16_t)strlen(password);
if (password_length > MZ_AES_PW_LENGTH_MAX)
return MZ_PARAM_ERROR;
if (wzaes->encryption_mode < 1 || wzaes->encryption_mode > 3)
return MZ_PARAM_ERROR;
salt_length = MZ_AES_SALT_LENGTH(wzaes->encryption_mode);
if (mode & MZ_OPEN_MODE_WRITE) {
mz_crypt_rand(salt_value, salt_length);
} else if (mode & MZ_OPEN_MODE_READ) {
if (mz_stream_read(wzaes->stream.base, salt_value, salt_length) != salt_length)
return MZ_READ_ERROR;
}
key_length = MZ_AES_KEY_LENGTH(wzaes->encryption_mode);
/* Derive the encryption and authentication keys and the password verifier */
mz_crypt_pbkdf2((uint8_t *)password, password_length, salt_value, salt_length,
MZ_AES_KEYING_ITERATIONS, kbuf, 2 * key_length + MZ_AES_PW_VERIFY_SIZE);
/* Initialize the encryption nonce and buffer pos */
wzaes->crypt_pos = MZ_AES_BLOCK_SIZE;
memset(wzaes->nonce, 0, sizeof(wzaes->nonce));
/* Initialize for encryption using key 1 */
mz_crypt_aes_reset(wzaes->aes);
mz_crypt_aes_set_mode(wzaes->aes, wzaes->encryption_mode);
mz_crypt_aes_set_encrypt_key(wzaes->aes, kbuf, key_length);
/* Initialize for authentication using key 2 */
mz_crypt_hmac_reset(wzaes->hmac);
mz_crypt_hmac_set_algorithm(wzaes->hmac, MZ_HASH_SHA1);
mz_crypt_hmac_init(wzaes->hmac, kbuf + key_length, key_length);
memcpy(verify, kbuf + (2 * key_length), MZ_AES_PW_VERIFY_SIZE);
if (mode & MZ_OPEN_MODE_WRITE) {
if (mz_stream_write(wzaes->stream.base, salt_value, salt_length) != salt_length)
return MZ_WRITE_ERROR;
wzaes->total_out += salt_length;
if (mz_stream_write(wzaes->stream.base, verify, MZ_AES_PW_VERIFY_SIZE) != MZ_AES_PW_VERIFY_SIZE)
return MZ_WRITE_ERROR;
wzaes->total_out += MZ_AES_PW_VERIFY_SIZE;
} else if (mode & MZ_OPEN_MODE_READ) {
wzaes->total_in += salt_length;
if (mz_stream_read(wzaes->stream.base, verify_expected, MZ_AES_PW_VERIFY_SIZE) != MZ_AES_PW_VERIFY_SIZE)
return MZ_READ_ERROR;
wzaes->total_in += MZ_AES_PW_VERIFY_SIZE;
if (memcmp(verify_expected, verify, MZ_AES_PW_VERIFY_SIZE) != 0)
return MZ_PASSWORD_ERROR;
}
wzaes->mode = mode;
wzaes->initialized = 1;
return MZ_OK;
}
int32_t mz_stream_wzaes_is_open(void *stream) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
if (wzaes->initialized == 0)
return MZ_OPEN_ERROR;
return MZ_OK;
}
static int32_t mz_stream_wzaes_ctr_encrypt(void *stream, uint8_t *buf, int32_t size) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
uint32_t pos = wzaes->crypt_pos;
uint32_t i = 0;
int32_t err = MZ_OK;
while (i < (uint32_t)size) {
if (pos == MZ_AES_BLOCK_SIZE) {
uint32_t j = 0;
/* Increment encryption nonce */
while (j < 8 && !++wzaes->nonce[j])
j += 1;
/* Encrypt the nonce to form next xor buffer */
memcpy(wzaes->crypt_block, wzaes->nonce, MZ_AES_BLOCK_SIZE);
mz_crypt_aes_encrypt(wzaes->aes, wzaes->crypt_block, sizeof(wzaes->crypt_block));
pos = 0;
}
buf[i++] ^= wzaes->crypt_block[pos++];
}
wzaes->crypt_pos = pos;
return err;
}
int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
int64_t max_total_in = 0;
int32_t bytes_to_read = size;
int32_t read = 0;
max_total_in = wzaes->max_total_in - MZ_AES_FOOTER_SIZE;
if ((int64_t)bytes_to_read > (max_total_in - wzaes->total_in))
bytes_to_read = (int32_t)(max_total_in - wzaes->total_in);
read = mz_stream_read(wzaes->stream.base, buf, bytes_to_read);
if (read > 0) {
mz_crypt_hmac_update(wzaes->hmac, (uint8_t *)buf, read);
mz_stream_wzaes_ctr_encrypt(stream, (uint8_t *)buf, read);
wzaes->total_in += read;
}
return read;
}
int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
const uint8_t *buf_ptr = (const uint8_t *)buf;
int32_t bytes_to_write = sizeof(wzaes->buffer);
int32_t total_written = 0;
int32_t written = 0;
if (size < 0)
return MZ_PARAM_ERROR;
do {
if (bytes_to_write > (size - total_written))
bytes_to_write = (size - total_written);
memcpy(wzaes->buffer, buf_ptr, bytes_to_write);
buf_ptr += bytes_to_write;
mz_stream_wzaes_ctr_encrypt(stream, (uint8_t *)wzaes->buffer, bytes_to_write);
mz_crypt_hmac_update(wzaes->hmac, wzaes->buffer, bytes_to_write);
written = mz_stream_write(wzaes->stream.base, wzaes->buffer, bytes_to_write);
if (written < 0)
return written;
total_written += written;
} while (total_written < size && written > 0);
wzaes->total_out += total_written;
return total_written;
}
int64_t mz_stream_wzaes_tell(void *stream) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
return mz_stream_tell(wzaes->stream.base);
}
int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
return mz_stream_seek(wzaes->stream.base, offset, origin);
}
int32_t mz_stream_wzaes_close(void *stream) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
uint8_t expected_hash[MZ_AES_AUTHCODE_SIZE];
uint8_t computed_hash[MZ_HASH_SHA1_SIZE];
mz_crypt_hmac_end(wzaes->hmac, computed_hash, sizeof(computed_hash));
if (wzaes->mode & MZ_OPEN_MODE_WRITE) {
if (mz_stream_write(wzaes->stream.base, computed_hash, MZ_AES_AUTHCODE_SIZE) != MZ_AES_AUTHCODE_SIZE)
return MZ_WRITE_ERROR;
wzaes->total_out += MZ_AES_AUTHCODE_SIZE;
} else if (wzaes->mode & MZ_OPEN_MODE_READ) {
if (mz_stream_read(wzaes->stream.base, expected_hash, MZ_AES_AUTHCODE_SIZE) != MZ_AES_AUTHCODE_SIZE)
return MZ_READ_ERROR;
wzaes->total_in += MZ_AES_AUTHCODE_SIZE;
/* If entire entry was not read this will fail */
if (memcmp(computed_hash, expected_hash, MZ_AES_AUTHCODE_SIZE) != 0)
return MZ_CRC_ERROR;
}
wzaes->initialized = 0;
return MZ_OK;
}
int32_t mz_stream_wzaes_error(void *stream) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
return wzaes->error;
}
void mz_stream_wzaes_set_password(void *stream, const char *password) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
wzaes->password = password;
}
void mz_stream_wzaes_set_encryption_mode(void *stream, int16_t encryption_mode) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
wzaes->encryption_mode = encryption_mode;
}
int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = wzaes->total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = wzaes->total_out;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = wzaes->max_total_in;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = MZ_AES_SALT_LENGTH((int64_t)wzaes->encryption_mode) + MZ_AES_PW_VERIFY_SIZE;
break;
case MZ_STREAM_PROP_FOOTER_SIZE:
*value = MZ_AES_AUTHCODE_SIZE;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_wzaes *wzaes = (mz_stream_wzaes *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN_MAX:
wzaes->max_total_in = value;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
void *mz_stream_wzaes_create(void **stream) {
mz_stream_wzaes *wzaes = NULL;
wzaes = (mz_stream_wzaes *)MZ_ALLOC(sizeof(mz_stream_wzaes));
if (wzaes != NULL) {
memset(wzaes, 0, sizeof(mz_stream_wzaes));
wzaes->stream.vtbl = &mz_stream_wzaes_vtbl;
wzaes->encryption_mode = MZ_AES_ENCRYPTION_MODE_256;
mz_crypt_hmac_create(&wzaes->hmac);
mz_crypt_aes_create(&wzaes->aes);
}
if (stream != NULL)
*stream = wzaes;
return wzaes;
}
void mz_stream_wzaes_delete(void **stream) {
mz_stream_wzaes *wzaes = NULL;
if (stream == NULL)
return;
wzaes = (mz_stream_wzaes *)*stream;
if (wzaes != NULL) {
mz_crypt_aes_delete(&wzaes->aes);
mz_crypt_hmac_delete(&wzaes->hmac);
MZ_FREE(wzaes);
}
*stream = NULL;
}
void *mz_stream_wzaes_get_interface(void) {
return (void *)&mz_stream_wzaes_vtbl;
}

46
externals/minizip/mz_strm_wzaes.h vendored Normal file
View File

@ -0,0 +1,46 @@
/* mz_strm_wzaes.h -- Stream for WinZIP AES encryption
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_WZAES_SHA1_H
#define MZ_STREAM_WZAES_SHA1_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_wzaes_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_wzaes_is_open(void *stream);
int32_t mz_stream_wzaes_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_wzaes_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_wzaes_tell(void *stream);
int32_t mz_stream_wzaes_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_wzaes_close(void *stream);
int32_t mz_stream_wzaes_error(void *stream);
void mz_stream_wzaes_set_password(void *stream, const char *password);
void mz_stream_wzaes_set_encryption_mode(void *stream, int16_t encryption_mode);
int32_t mz_stream_wzaes_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_wzaes_set_prop_int64(void *stream, int32_t prop, int64_t value);
void* mz_stream_wzaes_create(void **stream);
void mz_stream_wzaes_delete(void **stream);
void* mz_stream_wzaes_get_interface(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

393
externals/minizip/mz_strm_zlib.c vendored Normal file
View File

@ -0,0 +1,393 @@
/* mz_strm_zlib.c -- Stream for zlib inflate/deflate
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_zlib.h"
#include "zlib.h"
#if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
# include "zlib-ng.h"
#endif
/***************************************************************************/
#if defined(ZLIBNG_VERNUM) && !defined(ZLIB_COMPAT)
# define ZLIB_PREFIX(x) zng_ ## x
typedef zng_stream zlib_stream;
#else
# define ZLIB_PREFIX(x) x
typedef z_stream zlib_stream;
#endif
#if !defined(DEF_MEM_LEVEL)
# if MAX_MEM_LEVEL >= 8
# define DEF_MEM_LEVEL 8
# else
# define DEF_MEM_LEVEL MAX_MEM_LEVEL
# endif
#endif
/***************************************************************************/
static mz_stream_vtbl mz_stream_zlib_vtbl = {
mz_stream_zlib_open,
mz_stream_zlib_is_open,
mz_stream_zlib_read,
mz_stream_zlib_write,
mz_stream_zlib_tell,
mz_stream_zlib_seek,
mz_stream_zlib_close,
mz_stream_zlib_error,
mz_stream_zlib_create,
mz_stream_zlib_delete,
mz_stream_zlib_get_prop_int64,
mz_stream_zlib_set_prop_int64
};
/***************************************************************************/
typedef struct mz_stream_zlib_s {
mz_stream stream;
zlib_stream zstream;
uint8_t buffer[INT16_MAX];
int32_t buffer_len;
int64_t total_in;
int64_t total_out;
int64_t max_total_in;
int8_t initialized;
int16_t level;
int32_t window_bits;
int32_t mode;
int32_t error;
} mz_stream_zlib;
/***************************************************************************/
int32_t mz_stream_zlib_open(void *stream, const char *path, int32_t mode) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
MZ_UNUSED(path);
zlib->zstream.data_type = Z_BINARY;
zlib->zstream.zalloc = Z_NULL;
zlib->zstream.zfree = Z_NULL;
zlib->zstream.opaque = Z_NULL;
zlib->zstream.total_in = 0;
zlib->zstream.total_out = 0;
zlib->total_in = 0;
zlib->total_out = 0;
if (mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
zlib->zstream.next_out = zlib->buffer;
zlib->zstream.avail_out = sizeof(zlib->buffer);
zlib->error = ZLIB_PREFIX(deflateInit2)(&zlib->zstream, (int8_t)zlib->level, Z_DEFLATED,
zlib->window_bits, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY);
#endif
} else if (mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
zlib->zstream.next_in = zlib->buffer;
zlib->zstream.avail_in = 0;
zlib->error = ZLIB_PREFIX(inflateInit2)(&zlib->zstream, zlib->window_bits);
#endif
}
if (zlib->error != Z_OK)
return MZ_OPEN_ERROR;
zlib->initialized = 1;
zlib->mode = mode;
return MZ_OK;
}
int32_t mz_stream_zlib_is_open(void *stream) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
if (zlib->initialized != 1)
return MZ_OPEN_ERROR;
return MZ_OK;
}
int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
uint64_t total_in_before = 0;
uint64_t total_in_after = 0;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
uint32_t total_in = 0;
uint32_t total_out = 0;
uint32_t in_bytes = 0;
uint32_t out_bytes = 0;
int32_t bytes_to_read = sizeof(zlib->buffer);
int32_t read = 0;
int32_t err = Z_OK;
zlib->zstream.next_out = (Bytef*)buf;
zlib->zstream.avail_out = (uInt)size;
do {
if (zlib->zstream.avail_in == 0) {
if (zlib->max_total_in > 0) {
if ((int64_t)bytes_to_read > (zlib->max_total_in - zlib->total_in))
bytes_to_read = (int32_t)(zlib->max_total_in - zlib->total_in);
}
read = mz_stream_read(zlib->stream.base, zlib->buffer, bytes_to_read);
if (read < 0)
return read;
zlib->zstream.next_in = zlib->buffer;
zlib->zstream.avail_in = read;
}
total_in_before = zlib->zstream.avail_in;
total_out_before = zlib->zstream.total_out;
err = ZLIB_PREFIX(inflate)(&zlib->zstream, Z_SYNC_FLUSH);
if ((err >= Z_OK) && (zlib->zstream.msg != NULL)) {
zlib->error = Z_DATA_ERROR;
break;
}
total_in_after = zlib->zstream.avail_in;
total_out_after = zlib->zstream.total_out;
in_bytes = (uint32_t)(total_in_before - total_in_after);
out_bytes = (uint32_t)(total_out_after - total_out_before);
total_in += in_bytes;
total_out += out_bytes;
zlib->total_in += in_bytes;
zlib->total_out += out_bytes;
if (err == Z_STREAM_END)
break;
if (err != Z_OK) {
zlib->error = err;
break;
}
} while (zlib->zstream.avail_out > 0);
if (zlib->error != 0) {
/* Zlib errors are compatible with MZ */
return zlib->error;
}
return total_out;
#endif
}
#ifndef MZ_ZIP_NO_COMPRESSION
static int32_t mz_stream_zlib_flush(void *stream) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
if (mz_stream_write(zlib->stream.base, zlib->buffer, zlib->buffer_len) != zlib->buffer_len)
return MZ_WRITE_ERROR;
return MZ_OK;
}
static int32_t mz_stream_zlib_deflate(void *stream, int flush) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
int32_t out_bytes = 0;
int32_t err = Z_OK;
do {
if (zlib->zstream.avail_out == 0) {
err = mz_stream_zlib_flush(zlib);
if (err != MZ_OK)
return err;
zlib->zstream.avail_out = sizeof(zlib->buffer);
zlib->zstream.next_out = zlib->buffer;
zlib->buffer_len = 0;
}
total_out_before = zlib->zstream.total_out;
err = ZLIB_PREFIX(deflate)(&zlib->zstream, flush);
total_out_after = zlib->zstream.total_out;
out_bytes = (uint32_t)(total_out_after - total_out_before);
zlib->buffer_len += out_bytes;
zlib->total_out += out_bytes;
if (err == Z_STREAM_END)
break;
if (err != Z_OK) {
zlib->error = err;
return MZ_DATA_ERROR;
}
} while ((zlib->zstream.avail_in > 0) || (flush == Z_FINISH && err == Z_OK));
return MZ_OK;
}
#endif
int32_t mz_stream_zlib_write(void *stream, const void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_COMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
int32_t err = MZ_OK;
zlib->zstream.next_in = (Bytef*)(intptr_t)buf;
zlib->zstream.avail_in = (uInt)size;
err = mz_stream_zlib_deflate(stream, Z_NO_FLUSH);
if (err != MZ_OK) {
return err;
}
zlib->total_in += size;
return size;
#endif
}
int64_t mz_stream_zlib_tell(void *stream) {
MZ_UNUSED(stream);
return MZ_TELL_ERROR;
}
int32_t mz_stream_zlib_seek(void *stream, int64_t offset, int32_t origin) {
MZ_UNUSED(stream);
MZ_UNUSED(offset);
MZ_UNUSED(origin);
return MZ_SEEK_ERROR;
}
int32_t mz_stream_zlib_close(void *stream) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
if (zlib->mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
mz_stream_zlib_deflate(stream, Z_FINISH);
mz_stream_zlib_flush(stream);
ZLIB_PREFIX(deflateEnd)(&zlib->zstream);
#endif
} else if (zlib->mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
ZLIB_PREFIX(inflateEnd)(&zlib->zstream);
#endif
}
zlib->initialized = 0;
if (zlib->error != Z_OK)
return MZ_CLOSE_ERROR;
return MZ_OK;
}
int32_t mz_stream_zlib_error(void *stream) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
return zlib->error;
}
int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = zlib->total_in;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = zlib->max_total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = zlib->total_out;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = 0;
break;
case MZ_STREAM_PROP_COMPRESS_WINDOW:
*value = zlib->window_bits;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_zlib *zlib = (mz_stream_zlib *)stream;
switch (prop) {
case MZ_STREAM_PROP_COMPRESS_LEVEL:
zlib->level = (int16_t)value;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
zlib->max_total_in = value;
break;
case MZ_STREAM_PROP_COMPRESS_WINDOW:
zlib->window_bits = (int32_t)value;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
void *mz_stream_zlib_create(void **stream) {
mz_stream_zlib *zlib = NULL;
zlib = (mz_stream_zlib *)MZ_ALLOC(sizeof(mz_stream_zlib));
if (zlib != NULL) {
memset(zlib, 0, sizeof(mz_stream_zlib));
zlib->stream.vtbl = &mz_stream_zlib_vtbl;
zlib->level = Z_DEFAULT_COMPRESSION;
zlib->window_bits = -MAX_WBITS;
}
if (stream != NULL)
*stream = zlib;
return zlib;
}
void mz_stream_zlib_delete(void **stream) {
mz_stream_zlib *zlib = NULL;
if (stream == NULL)
return;
zlib = (mz_stream_zlib *)*stream;
if (zlib != NULL)
MZ_FREE(zlib);
*stream = NULL;
}
void *mz_stream_zlib_get_interface(void) {
return (void *)&mz_stream_zlib_vtbl;
}

43
externals/minizip/mz_strm_zlib.h vendored Normal file
View File

@ -0,0 +1,43 @@
/* mz_strm_zlib.h -- Stream for zlib inflate/deflate
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_ZLIB_H
#define MZ_STREAM_ZLIB_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_zlib_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_zlib_is_open(void *stream);
int32_t mz_stream_zlib_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_zlib_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_zlib_tell(void *stream);
int32_t mz_stream_zlib_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_zlib_close(void *stream);
int32_t mz_stream_zlib_error(void *stream);
int32_t mz_stream_zlib_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_zlib_set_prop_int64(void *stream, int32_t prop, int64_t value);
void* mz_stream_zlib_create(void **stream);
void mz_stream_zlib_delete(void **stream);
void* mz_stream_zlib_get_interface(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

351
externals/minizip/mz_strm_zstd.c vendored Normal file
View File

@ -0,0 +1,351 @@
/* mz_strm_zstd.c -- Stream for zstd compress/decompress
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Authors: Force Charlie
https://github.com/fcharlie
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#include "mz.h"
#include "mz_strm.h"
#include "mz_strm_zstd.h"
#include <zstd.h>
/***************************************************************************/
static mz_stream_vtbl mz_stream_zstd_vtbl = {
mz_stream_zstd_open,
mz_stream_zstd_is_open,
mz_stream_zstd_read,
mz_stream_zstd_write,
mz_stream_zstd_tell,
mz_stream_zstd_seek,
mz_stream_zstd_close,
mz_stream_zstd_error,
mz_stream_zstd_create,
mz_stream_zstd_delete,
mz_stream_zstd_get_prop_int64,
mz_stream_zstd_set_prop_int64
};
/***************************************************************************/
typedef struct mz_stream_zstd_s {
mz_stream stream;
ZSTD_CStream *zcstream;
ZSTD_DStream *zdstream;
ZSTD_outBuffer out;
ZSTD_inBuffer in;
int32_t mode;
int32_t error;
uint8_t buffer[INT16_MAX];
int32_t buffer_len;
int64_t total_in;
int64_t total_out;
int64_t max_total_in;
int64_t max_total_out;
int8_t initialized;
uint32_t preset;
} mz_stream_zstd;
/***************************************************************************/
int32_t mz_stream_zstd_open(void *stream, const char *path, int32_t mode) {
mz_stream_zstd *zstd = (mz_stream_zstd *)stream;
MZ_UNUSED(path);
if (mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
zstd->zcstream = ZSTD_createCStream();
zstd->out.dst = zstd->buffer;
zstd->out.size = sizeof(zstd->buffer);
zstd->out.pos = 0;
#endif
} else if (mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
zstd->zdstream = ZSTD_createDStream();
memset(&zstd->out, 0, sizeof(ZSTD_outBuffer));
#endif
}
memset(&zstd->in, 0, sizeof(ZSTD_inBuffer));
zstd->initialized = 1;
zstd->mode = mode;
zstd->error = MZ_OK;
return MZ_OK;
}
int32_t mz_stream_zstd_is_open(void *stream) {
mz_stream_zstd *zstd = (mz_stream_zstd *)stream;
if (zstd->initialized != 1)
return MZ_OPEN_ERROR;
return MZ_OK;
}
int32_t mz_stream_zstd_read(void *stream, void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_zstd *zstd = (mz_stream_zstd *)stream;
uint64_t total_in_before = 0;
uint64_t total_in_after = 0;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
int32_t total_in = 0;
int32_t total_out = 0;
int32_t in_bytes = 0;
int32_t out_bytes = 0;
int32_t bytes_to_read = sizeof(zstd->buffer);
int32_t read = 0;
size_t result = 0;
zstd->out.dst = (void*)buf;
zstd->out.size = (size_t)size;
zstd->out.pos = 0;
do {
if (zstd->in.pos == zstd->in.size) {
if (zstd->max_total_in > 0) {
if ((int64_t)bytes_to_read > (zstd->max_total_in - zstd->total_in))
bytes_to_read = (int32_t)(zstd->max_total_in - zstd->total_in);
}
read = mz_stream_read(zstd->stream.base, zstd->buffer, bytes_to_read);
if (read < 0)
return read;
zstd->in.src = (const void*)zstd->buffer;
zstd->in.pos = 0;
zstd->in.size = (size_t)read;
}
total_in_before = zstd->in.pos;
total_out_before = zstd->out.pos;
result = ZSTD_decompressStream(zstd->zdstream, &zstd->out, &zstd->in);
if (ZSTD_isError(result)) {
zstd->error = (int32_t)result;
return MZ_DATA_ERROR;
}
total_in_after = zstd->in.pos;
total_out_after = zstd->out.pos;
if ((zstd->max_total_out != -1) && (int64_t)total_out_after > zstd->max_total_out)
total_out_after = (uint64_t)zstd->max_total_out;
in_bytes = (int32_t)(total_in_after - total_in_before);
out_bytes = (int32_t)(total_out_after - total_out_before);
total_in += in_bytes;
total_out += out_bytes;
zstd->total_in += in_bytes;
zstd->total_out += out_bytes;
} while ((zstd->in.size > 0 || out_bytes > 0) && (zstd->out.pos < zstd->out.size));
return total_out;
#endif
}
#ifndef MZ_ZIP_NO_COMPRESSION
static int32_t mz_stream_zstd_flush(void *stream) {
mz_stream_zstd *zstd = (mz_stream_zstd *)stream;
if (mz_stream_write(zstd->stream.base, zstd->buffer, zstd->buffer_len) != zstd->buffer_len)
return MZ_WRITE_ERROR;
return MZ_OK;
}
static int32_t mz_stream_zstd_compress(void *stream, ZSTD_EndDirective flush) {
mz_stream_zstd *zstd = (mz_stream_zstd *)stream;
uint64_t total_out_before = 0;
uint64_t total_out_after = 0;
int32_t out_bytes = 0;
size_t result = 0;
int32_t err = 0;
do {
if (zstd->out.pos == zstd->out.size) {
err = mz_stream_zstd_flush(zstd);
if (err != MZ_OK)
return err;
zstd->out.dst = zstd->buffer;
zstd->out.size = sizeof(zstd->buffer);
zstd->out.pos = 0;
zstd->buffer_len = 0;
}
total_out_before = zstd->out.pos;
result = ZSTD_compressStream2(zstd->zcstream, &zstd->out, &zstd->in, flush);
total_out_after = zstd->out.pos;
out_bytes = (uint32_t)(total_out_after - total_out_before);
zstd->buffer_len += out_bytes;
zstd->total_out += out_bytes;
if (ZSTD_isError(result)) {
zstd->error = (int32_t)result;
return MZ_DATA_ERROR;
}
} while ((zstd->in.pos < zstd->in.size) || (flush == ZSTD_e_end && result != 0));
return MZ_OK;
}
#endif
int32_t mz_stream_zstd_write(void *stream, const void *buf, int32_t size) {
#ifdef MZ_ZIP_NO_COMPRESSION
MZ_UNUSED(stream);
MZ_UNUSED(buf);
MZ_UNUSED(size);
return MZ_SUPPORT_ERROR;
#else
mz_stream_zstd *zstd = (mz_stream_zstd *)stream;
int32_t err = MZ_OK;
zstd->in.src = buf;
zstd->in.pos = 0;
zstd->in.size = size;
err = mz_stream_zstd_compress(stream, ZSTD_e_continue);
if (err != MZ_OK) {
return err;
}
zstd->total_in += size;
return size;
#endif
}
int64_t mz_stream_zstd_tell(void *stream) {
MZ_UNUSED(stream);
return MZ_TELL_ERROR;
}
int32_t mz_stream_zstd_seek(void *stream, int64_t offset, int32_t origin) {
MZ_UNUSED(stream);
MZ_UNUSED(offset);
MZ_UNUSED(origin);
return MZ_SEEK_ERROR;
}
int32_t mz_stream_zstd_close(void *stream) {
mz_stream_zstd *zstd = (mz_stream_zstd *)stream;
if (zstd->mode & MZ_OPEN_MODE_WRITE) {
#ifdef MZ_ZIP_NO_COMPRESSION
return MZ_SUPPORT_ERROR;
#else
mz_stream_zstd_compress(stream, ZSTD_e_end);
mz_stream_zstd_flush(stream);
ZSTD_freeCStream(zstd->zcstream);
zstd->zcstream = NULL;
#endif
} else if (zstd->mode & MZ_OPEN_MODE_READ) {
#ifdef MZ_ZIP_NO_DECOMPRESSION
return MZ_SUPPORT_ERROR;
#else
ZSTD_freeDStream(zstd->zdstream);
zstd->zdstream = NULL;
#endif
}
zstd->initialized = 0;
return MZ_OK;
}
int32_t mz_stream_zstd_error(void *stream) {
mz_stream_zstd *zstd = (mz_stream_zstd *)stream;
return zstd->error;
}
int32_t mz_stream_zstd_get_prop_int64(void *stream, int32_t prop, int64_t *value) {
mz_stream_zstd *zstd = (mz_stream_zstd *)stream;
switch (prop) {
case MZ_STREAM_PROP_TOTAL_IN:
*value = zstd->total_in;
break;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
*value = zstd->max_total_in;
break;
case MZ_STREAM_PROP_TOTAL_OUT:
*value = zstd->total_out;
break;
case MZ_STREAM_PROP_TOTAL_OUT_MAX:
*value = zstd->max_total_out;
break;
case MZ_STREAM_PROP_HEADER_SIZE:
*value = 0;
break;
default:
return MZ_EXIST_ERROR;
}
return MZ_OK;
}
int32_t mz_stream_zstd_set_prop_int64(void *stream, int32_t prop, int64_t value) {
mz_stream_zstd *zstd = (mz_stream_zstd *)stream;
switch (prop) {
case MZ_STREAM_PROP_COMPRESS_LEVEL:
if (value < 0)
zstd->preset = 6;
else
zstd->preset = (int16_t)value;
return MZ_OK;
case MZ_STREAM_PROP_TOTAL_IN_MAX:
zstd->max_total_in = value;
return MZ_OK;
}
return MZ_EXIST_ERROR;
}
void *mz_stream_zstd_create(void **stream) {
mz_stream_zstd *zstd = NULL;
zstd = (mz_stream_zstd *)MZ_ALLOC(sizeof(mz_stream_zstd));
if (zstd != NULL) {
memset(zstd, 0, sizeof(mz_stream_zstd));
zstd->stream.vtbl = &mz_stream_zstd_vtbl;
zstd->max_total_out = -1;
}
if (stream != NULL)
*stream = zstd;
return zstd;
}
void mz_stream_zstd_delete(void **stream) {
mz_stream_zstd *zstd = NULL;
if (stream == NULL)
return;
zstd = (mz_stream_zstd *)*stream;
if (zstd != NULL)
MZ_FREE(zstd);
*stream = NULL;
}
void *mz_stream_zstd_get_interface(void) {
return (void *)&mz_stream_zstd_vtbl;
}

44
externals/minizip/mz_strm_zstd.h vendored Normal file
View File

@ -0,0 +1,44 @@
/* mz_strm_zlib.h -- Stream for zlib inflate/deflate
Version 2.9.2, February 12, 2020
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_STREAM_ZSTD_H
#define MZ_STREAM_ZSTD_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
int32_t mz_stream_zstd_open(void *stream, const char *filename, int32_t mode);
int32_t mz_stream_zstd_is_open(void *stream);
int32_t mz_stream_zstd_read(void *stream, void *buf, int32_t size);
int32_t mz_stream_zstd_write(void *stream, const void *buf, int32_t size);
int64_t mz_stream_zstd_tell(void *stream);
int32_t mz_stream_zstd_seek(void *stream, int64_t offset, int32_t origin);
int32_t mz_stream_zstd_close(void *stream);
int32_t mz_stream_zstd_error(void *stream);
int32_t mz_stream_zstd_get_prop_int64(void *stream, int32_t prop, int64_t *value);
int32_t mz_stream_zstd_set_prop_int64(void *stream, int32_t prop, int64_t value);
void* mz_stream_zstd_create(void **stream);
void mz_stream_zstd_delete(void **stream);
void* mz_stream_zstd_get_interface(void);
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

2771
externals/minizip/mz_zip.c vendored Normal file

File diff suppressed because it is too large Load Diff

259
externals/minizip/mz_zip.h vendored Normal file
View File

@ -0,0 +1,259 @@
/* mz_zip.h -- Zip manipulation
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
Copyright (C) 2009-2010 Mathias Svensson
Modifications for Zip64 support
http://result42.com
Copyright (C) 1998-2010 Gilles Vollant
https://www.winimage.com/zLibDll/minizip.html
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_ZIP_H
#define MZ_ZIP_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
typedef struct mz_zip_file_s {
uint16_t version_madeby; /* version made by */
uint16_t version_needed; /* version needed to extract */
uint16_t flag; /* general purpose bit flag */
uint16_t compression_method; /* compression method */
time_t modified_date; /* last modified date in unix time */
time_t accessed_date; /* last accessed date in unix time */
time_t creation_date; /* creation date in unix time */
uint32_t crc; /* crc-32 */
int64_t compressed_size; /* compressed size */
int64_t uncompressed_size; /* uncompressed size */
uint16_t filename_size; /* filename length */
uint16_t extrafield_size; /* extra field length */
uint16_t comment_size; /* file comment length */
uint32_t disk_number; /* disk number start */
int64_t disk_offset; /* relative offset of local header */
uint16_t internal_fa; /* internal file attributes */
uint32_t external_fa; /* external file attributes */
const char *filename; /* filename utf8 null-terminated string */
const uint8_t *extrafield; /* extrafield data */
const char *comment; /* comment utf8 null-terminated string */
const char *linkname; /* sym-link filename utf8 null-terminated string */
uint16_t zip64; /* zip64 extension mode */
uint16_t aes_version; /* winzip aes extension if not 0 */
uint8_t aes_encryption_mode; /* winzip aes encryption mode */
uint16_t pk_verify; /* pkware encryption verifier */
} mz_zip_file, mz_zip_entry;
/***************************************************************************/
typedef int32_t (*mz_zip_locate_entry_cb)(void *handle, void *userdata, mz_zip_file *file_info);
/***************************************************************************/
void * mz_zip_create(void **handle);
/* Create zip instance for opening */
void mz_zip_delete(void **handle);
/* Delete zip object */
int32_t mz_zip_open(void *handle, void *stream, int32_t mode);
/* Create a zip file, no delete file in zip functionality */
int32_t mz_zip_close(void *handle);
/* Close the zip file */
int32_t mz_zip_get_comment(void *handle, const char **comment);
/* Get a pointer to the global comment */
int32_t mz_zip_set_comment(void *handle, const char *comment);
/* Sets the global comment used for writing zip file */
int32_t mz_zip_get_version_madeby(void *handle, uint16_t *version_madeby);
/* Get the version made by */
int32_t mz_zip_set_version_madeby(void *handle, uint16_t version_madeby);
/* Sets the version made by used for writing zip file */
int32_t mz_zip_set_recover(void *handle, uint8_t recover);
/* Sets the ability to recover the central dir by reading local file headers */
int32_t mz_zip_set_data_descriptor(void *handle, uint8_t data_descriptor);
/* Sets the use of data descriptor flag when writing zip entries */
int32_t mz_zip_get_stream(void *handle, void **stream);
/* Get a pointer to the stream used to open */
int32_t mz_zip_set_cd_stream(void *handle, int64_t cd_start_pos, void *cd_stream);
/* Sets the stream to use for reading the central dir */
int32_t mz_zip_get_cd_mem_stream(void *handle, void **cd_mem_stream);
/* Get a pointer to the stream used to store the central dir in memory */
int32_t mz_zip_set_number_entry(void *handle, uint64_t number_entry);
/* Sets the total number of entries */
int32_t mz_zip_get_number_entry(void *handle, uint64_t *number_entry);
/* Get the total number of entries */
int32_t mz_zip_set_disk_number_with_cd(void *handle, uint32_t disk_number_with_cd);
/* Sets the disk number containing the central directory record */
int32_t mz_zip_get_disk_number_with_cd(void *handle, uint32_t *disk_number_with_cd);
/* Get the disk number containing the central directory record */
/***************************************************************************/
int32_t mz_zip_entry_is_open(void *handle);
/* Check to see if entry is open for read/write */
int32_t mz_zip_entry_read_open(void *handle, uint8_t raw, const char *password);
/* Open for reading the current file in the zip file */
int32_t mz_zip_entry_read(void *handle, void *buf, int32_t len);
/* Read bytes from the current file in the zip file */
int32_t mz_zip_entry_read_close(void *handle, uint32_t *crc32, int64_t *compressed_size,
int64_t *uncompressed_size);
/* Close the current file for reading and get data descriptor values */
int32_t mz_zip_entry_write_open(void *handle, const mz_zip_file *file_info,
int16_t compress_level, uint8_t raw, const char *password);
/* Open for writing the current file in the zip file */
int32_t mz_zip_entry_write(void *handle, const void *buf, int32_t len);
/* Write bytes from the current file in the zip file */
int32_t mz_zip_entry_write_close(void *handle, uint32_t crc32, int64_t compressed_size,
int64_t uncompressed_size);
/* Close the current file for writing and set data descriptor values */
int32_t mz_zip_entry_seek_local_header(void *handle);
/* Seeks to the local header for the entry */
int32_t mz_zip_entry_close_raw(void *handle, int64_t uncompressed_size, uint32_t crc32);
/* Close the current file in the zip file where raw is compressed data */
int32_t mz_zip_entry_close(void *handle);
/* Close the current file in the zip file */
/***************************************************************************/
int32_t mz_zip_entry_is_dir(void *handle);
/* Checks to see if the entry is a directory */
int32_t mz_zip_entry_is_symlink(void *handle);
/* Checks to see if the entry is a symbolic link */
int32_t mz_zip_entry_get_info(void *handle, mz_zip_file **file_info);
/* Get info about the current file, only valid while current entry is open */
int32_t mz_zip_entry_get_local_info(void *handle, mz_zip_file **local_file_info);
/* Get local info about the current file, only valid while current entry is being read */
int32_t mz_zip_entry_set_extrafield(void *handle, const uint8_t *extrafield, uint16_t extrafield_size);
/* Sets or updates the extra field for the entry to be used before writing cd */
int64_t mz_zip_get_entry(void *handle);
/* Return offset of the current entry in the zip file */
int32_t mz_zip_goto_entry(void *handle, int64_t cd_pos);
/* Go to specified entry in the zip file */
int32_t mz_zip_goto_first_entry(void *handle);
/* Go to the first entry in the zip file */
int32_t mz_zip_goto_next_entry(void *handle);
/* Go to the next entry in the zip file or MZ_END_OF_LIST if reaching the end */
int32_t mz_zip_locate_entry(void *handle, const char *filename, uint8_t ignore_case);
/* Locate the file with the specified name in the zip file or MZ_END_LIST if not found */
int32_t mz_zip_locate_first_entry(void *handle, void *userdata, mz_zip_locate_entry_cb cb);
/* Locate the first matching entry based on a match callback */
int32_t mz_zip_locate_next_entry(void *handle, void *userdata, mz_zip_locate_entry_cb cb);
/* Locate the next matching entry based on a match callback */
/***************************************************************************/
int32_t mz_zip_attrib_is_dir(uint32_t attrib, int32_t version_madeby);
/* Checks to see if the attribute is a directory based on platform */
int32_t mz_zip_attrib_is_symlink(uint32_t attrib, int32_t version_madeby);
/* Checks to see if the attribute is a symbolic link based on platform */
int32_t mz_zip_attrib_convert(uint8_t src_sys, uint32_t src_attrib, uint8_t target_sys,
uint32_t *target_attrib);
/* Converts file attributes from one host system to another */
int32_t mz_zip_attrib_posix_to_win32(uint32_t posix_attrib, uint32_t *win32_attrib);
/* Converts posix file attributes to win32 file attributes */
int32_t mz_zip_attrib_win32_to_posix(uint32_t win32_attrib, uint32_t *posix_attrib);
/* Converts win32 file attributes to posix file attributes */
/***************************************************************************/
int32_t mz_zip_extrafield_find(void *stream, uint16_t type, int32_t max_seek, uint16_t *length);
/* Seeks to extra field by its type and returns its length */
int32_t mz_zip_extrafield_contains(const uint8_t *extrafield, int32_t extrafield_size,
uint16_t type, uint16_t *length);
/* Gets whether an extrafield exists and its size */
int32_t mz_zip_extrafield_read(void *stream, uint16_t *type, uint16_t *length);
/* Reads an extrafield header from a stream */
int32_t mz_zip_extrafield_write(void *stream, uint16_t type, uint16_t length);
/* Writes an extrafield header to a stream */
/***************************************************************************/
int32_t mz_zip_dosdate_to_tm(uint64_t dos_date, struct tm *ptm);
/* Convert dos date/time format to struct tm */
time_t mz_zip_dosdate_to_time_t(uint64_t dos_date);
/* Convert dos date/time format to time_t */
int32_t mz_zip_time_t_to_tm(time_t unix_time, struct tm *ptm);
/* Convert time_t to time struct */
uint32_t mz_zip_time_t_to_dos_date(time_t unix_time);
/* Convert time_t to dos date/time format */
uint32_t mz_zip_tm_to_dosdate(const struct tm *ptm);
/* Convert struct tm to dos date/time format */
int32_t mz_zip_ntfs_to_unix_time(uint64_t ntfs_time, time_t *unix_time);
/* Convert ntfs time to unix time */
int32_t mz_zip_unix_to_ntfs_time(time_t unix_time, uint64_t *ntfs_time);
/* Convert unix time to ntfs time */
/***************************************************************************/
int32_t mz_zip_path_compare(const char *path1, const char *path2, uint8_t ignore_case);
/* Compare two paths without regard to slashes */
/***************************************************************************/
const
char* mz_zip_get_compression_method_string(int32_t compression_method);
/* Gets a string representing the compression method */
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif /* _ZIP_H */

1943
externals/minizip/mz_zip_rw.c vendored Normal file

File diff suppressed because it is too large Load Diff

285
externals/minizip/mz_zip_rw.h vendored Normal file
View File

@ -0,0 +1,285 @@
/* mz_zip_rw.h -- Zip reader/writer
part of the minizip-ng project
Copyright (C) 2010-2021 Nathan Moinvaziri
https://github.com/zlib-ng/minizip-ng
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_ZIP_RW_H
#define MZ_ZIP_RW_H
#ifdef __cplusplus
extern "C" {
#endif
/***************************************************************************/
typedef int32_t (*mz_zip_reader_overwrite_cb)(void *handle, void *userdata, mz_zip_file *file_info, const char *path);
typedef int32_t (*mz_zip_reader_password_cb)(void *handle, void *userdata, mz_zip_file *file_info, char *password, int32_t max_password);
typedef int32_t (*mz_zip_reader_progress_cb)(void *handle, void *userdata, mz_zip_file *file_info, int64_t position);
typedef int32_t (*mz_zip_reader_entry_cb)(void *handle, void *userdata, mz_zip_file *file_info, const char *path);
/***************************************************************************/
int32_t mz_zip_reader_is_open(void *handle);
/* Checks to see if the zip file is open */
int32_t mz_zip_reader_open(void *handle, void *stream);
/* Opens zip file from stream */
int32_t mz_zip_reader_open_file(void *handle, const char *path);
/* Opens zip file from a file path */
int32_t mz_zip_reader_open_file_in_memory(void *handle, const char *path);
/* Opens zip file from a file path into memory for faster access */
int32_t mz_zip_reader_open_buffer(void *handle, uint8_t *buf, int32_t len, uint8_t copy);
/* Opens zip file from memory buffer */
int32_t mz_zip_reader_close(void *handle);
/* Closes the zip file */
/***************************************************************************/
int32_t mz_zip_reader_unzip_cd(void *handle);
/* Unzip the central directory */
/***************************************************************************/
int32_t mz_zip_reader_goto_first_entry(void *handle);
/* Goto the first entry in the zip file that matches the pattern */
int32_t mz_zip_reader_goto_next_entry(void *handle);
/* Goto the next entry in the zip file that matches the pattern */
int32_t mz_zip_reader_locate_entry(void *handle, const char *filename, uint8_t ignore_case);
/* Locates an entry by filename */
int32_t mz_zip_reader_entry_open(void *handle);
/* Opens an entry for reading */
int32_t mz_zip_reader_entry_close(void *handle);
/* Closes an entry */
int32_t mz_zip_reader_entry_read(void *handle, void *buf, int32_t len);
/* Reads and entry after being opened */
int32_t mz_zip_reader_entry_has_sign(void *handle);
/* Checks to see if the entry has a signature */
int32_t mz_zip_reader_entry_sign_verify(void *handle);
/* Verifies a signature stored with the entry */
int32_t mz_zip_reader_entry_get_hash(void *handle, uint16_t algorithm, uint8_t *digest, int32_t digest_size);
/* Gets a hash algorithm from the entry's extra field */
int32_t mz_zip_reader_entry_get_first_hash(void *handle, uint16_t *algorithm, uint16_t *digest_size);
/* Gets the most secure hash algorithm from the entry's extra field */
int32_t mz_zip_reader_entry_get_info(void *handle, mz_zip_file **file_info);
/* Gets the current entry file info */
int32_t mz_zip_reader_entry_is_dir(void *handle);
/* Gets the current entry is a directory */
int32_t mz_zip_reader_entry_save(void *handle, void *stream, mz_stream_write_cb write_cb);
/* Save the current entry to a stream */
int32_t mz_zip_reader_entry_save_process(void *handle, void *stream, mz_stream_write_cb write_cb);
/* Saves a portion of the current entry to a stream callback */
int32_t mz_zip_reader_entry_save_file(void *handle, const char *path);
/* Save the current entry to a file */
int32_t mz_zip_reader_entry_save_buffer(void *handle, void *buf, int32_t len);
/* Save the current entry to a memory buffer */
int32_t mz_zip_reader_entry_save_buffer_length(void *handle);
/* Gets the length of the buffer required to save */
/***************************************************************************/
int32_t mz_zip_reader_save_all(void *handle, const char *destination_dir);
/* Save all files into a directory */
/***************************************************************************/
void mz_zip_reader_set_pattern(void *handle, const char *pattern, uint8_t ignore_case);
/* Sets the match pattern for entries in the zip file, if null all entries are matched */
void mz_zip_reader_set_password(void *handle, const char *password);
/* Sets the password required for extraction */
void mz_zip_reader_set_raw(void *handle, uint8_t raw);
/* Sets whether or not it should save the entry raw */
int32_t mz_zip_reader_get_raw(void *handle, uint8_t *raw);
/* Gets whether or not it should save the entry raw */
int32_t mz_zip_reader_get_zip_cd(void *handle, uint8_t *zip_cd);
/* Gets whether or not the archive has a zipped central directory */
int32_t mz_zip_reader_get_comment(void *handle, const char **comment);
/* Gets the comment for the central directory */
int32_t mz_zip_reader_set_recover(void *handle, uint8_t recover);
/* Sets the ability to recover the central dir by reading local file headers */
void mz_zip_reader_set_encoding(void *handle, int32_t encoding);
/* Sets whether or not it should support a special character encoding in zip file names. */
void mz_zip_reader_set_sign_required(void *handle, uint8_t sign_required);
/* Sets whether or not it a signature is required */
void mz_zip_reader_set_overwrite_cb(void *handle, void *userdata, mz_zip_reader_overwrite_cb cb);
/* Callback for what to do when a file is being overwritten */
void mz_zip_reader_set_password_cb(void *handle, void *userdata, mz_zip_reader_password_cb cb);
/* Callback for when a password is required and hasn't been set */
void mz_zip_reader_set_progress_cb(void *handle, void *userdata, mz_zip_reader_progress_cb cb);
/* Callback for extraction progress */
void mz_zip_reader_set_progress_interval(void *handle, uint32_t milliseconds);
/* Let at least milliseconds pass between calls to progress callback */
void mz_zip_reader_set_entry_cb(void *handle, void *userdata, mz_zip_reader_entry_cb cb);
/* Callback for zip file entries */
int32_t mz_zip_reader_get_zip_handle(void *handle, void **zip_handle);
/* Gets the underlying zip instance handle */
void* mz_zip_reader_create(void **handle);
/* Create new instance of zip reader */
void mz_zip_reader_delete(void **handle);
/* Delete instance of zip reader */
/***************************************************************************/
typedef int32_t (*mz_zip_writer_overwrite_cb)(void *handle, void *userdata, const char *path);
typedef int32_t (*mz_zip_writer_password_cb)(void *handle, void *userdata, mz_zip_file *file_info, char *password, int32_t max_password);
typedef int32_t (*mz_zip_writer_progress_cb)(void *handle, void *userdata, mz_zip_file *file_info, int64_t position);
typedef int32_t (*mz_zip_writer_entry_cb)(void *handle, void *userdata, mz_zip_file *file_info);
/***************************************************************************/
int32_t mz_zip_writer_is_open(void *handle);
/* Checks to see if the zip file is open */
int32_t mz_zip_writer_open(void *handle, void *stream, uint8_t append);
/* Opens zip file from stream */
int32_t mz_zip_writer_open_file(void *handle, const char *path, int64_t disk_size, uint8_t append);
/* Opens zip file from a file path */
int32_t mz_zip_writer_open_file_in_memory(void *handle, const char *path);
/* Opens zip file from a file path into memory for faster access */
int32_t mz_zip_writer_close(void *handle);
/* Closes the zip file */
/***************************************************************************/
int32_t mz_zip_writer_entry_open(void *handle, mz_zip_file *file_info);
/* Opens an entry in the zip file for writing */
int32_t mz_zip_writer_entry_close(void *handle);
/* Closes entry in zip file */
int32_t mz_zip_writer_entry_write(void *handle, const void *buf, int32_t len);
/* Writes data into entry for zip */
/***************************************************************************/
int32_t mz_zip_writer_add(void *handle, void *stream, mz_stream_read_cb read_cb);
/* Writes all data to the currently open entry in the zip */
int32_t mz_zip_writer_add_process(void *handle, void *stream, mz_stream_read_cb read_cb);
/* Writes a portion of data to the currently open entry in the zip */
int32_t mz_zip_writer_add_info(void *handle, void *stream, mz_stream_read_cb read_cb, mz_zip_file *file_info);
/* Adds an entry to the zip based on the info */
int32_t mz_zip_writer_add_buffer(void *handle, void *buf, int32_t len, mz_zip_file *file_info);
/* Adds an entry to the zip with a memory buffer */
int32_t mz_zip_writer_add_file(void *handle, const char *path, const char *filename_in_zip);
/* Adds an entry to the zip from a file */
int32_t mz_zip_writer_add_path(void *handle, const char *path, const char *root_path, uint8_t include_path,
uint8_t recursive);
/* Enumerates a directory or pattern and adds entries to the zip */
int32_t mz_zip_writer_copy_from_reader(void *handle, void *reader);
/* Adds an entry from a zip reader instance */
/***************************************************************************/
void mz_zip_writer_set_password(void *handle, const char *password);
/* Password to use for encrypting files in the zip */
void mz_zip_writer_set_comment(void *handle, const char *comment);
/* Comment to use for the archive */
void mz_zip_writer_set_raw(void *handle, uint8_t raw);
/* Sets whether or not we should write the entry raw */
int32_t mz_zip_writer_get_raw(void *handle, uint8_t *raw);
/* Gets whether or not we should write the entry raw */
void mz_zip_writer_set_aes(void *handle, uint8_t aes);
/* Use aes encryption when adding files in zip */
void mz_zip_writer_set_compress_method(void *handle, uint16_t compress_method);
/* Sets the compression method when adding files in zip */
void mz_zip_writer_set_compress_level(void *handle, int16_t compress_level);
/* Sets the compression level when adding files in zip */
void mz_zip_writer_set_follow_links(void *handle, uint8_t follow_links);
/* Follow symbolic links when traversing directories and files to add */
void mz_zip_writer_set_store_links(void *handle, uint8_t store_links);
/* Store symbolic links in zip file */
void mz_zip_writer_set_zip_cd(void *handle, uint8_t zip_cd);
/* Sets whether or not central directory should be zipped */
int32_t mz_zip_writer_set_certificate(void *handle, const char *cert_path, const char *cert_pwd);
/* Sets the certificate and timestamp url to use for signing when adding files in zip */
void mz_zip_writer_set_overwrite_cb(void *handle, void *userdata, mz_zip_writer_overwrite_cb cb);
/* Callback for what to do when zip file already exists */
void mz_zip_writer_set_password_cb(void *handle, void *userdata, mz_zip_writer_password_cb cb);
/* Callback for ask if a password is required for adding */
void mz_zip_writer_set_progress_cb(void *handle, void *userdata, mz_zip_writer_progress_cb cb);
/* Callback for compression progress */
void mz_zip_writer_set_progress_interval(void *handle, uint32_t milliseconds);
/* Let at least milliseconds pass between calls to progress callback */
void mz_zip_writer_set_entry_cb(void *handle, void *userdata, mz_zip_writer_entry_cb cb);
/* Callback for zip file entries */
int32_t mz_zip_writer_get_zip_handle(void *handle, void **zip_handle);
/* Gets the underlying zip handle */
void* mz_zip_writer_create(void **handle);
/* Create new instance of zip writer */
void mz_zip_writer_delete(void **handle);
/* Delete instance of zip writer */
/***************************************************************************/
#ifdef __cplusplus
}
#endif
#endif

13
externals/minizip/unzip.h vendored Normal file
View File

@ -0,0 +1,13 @@
/* unzip.h -- Compatibility layer shim
part of the minizip-ng project
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_COMPAT_UNZIP
#define MZ_COMPAT_UNZIP
#include "mz_compat.h"
#endif

13
externals/minizip/zip.h vendored Normal file
View File

@ -0,0 +1,13 @@
/* zip.h -- Compatibility layer shim
part of the minizip-ng project
This program is distributed under the terms of the same license as zlib.
See the accompanying LICENSE file for the full text of the license.
*/
#ifndef MZ_COMPAT_ZIP
#define MZ_COMPAT_ZIP
#include "mz_compat.h"
#endif

14
externals/zlib-ng/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,14 @@
set(ZLIB_ENABLE_TESTS OFF)
set(ZLIB_COMPAT ON)
set(SKIP_INSTALL_ALL ON)
option(BUILD_SHARED_LIBS "Build shared library" OFF)
add_subdirectory(zlib-ng)
# Set ZLIB variables for find_package used by other projects
set(ZLIB_INCLUDE_DIR ${CMAKE_BINARY_DIR}/zlib-ng CACHE STRING "Path to zlib include directory")
set(ZLIB_LIBRARY ZLIB::ZLIB CACHE STRING "Path to zlib library")
# Setup zlib alias project so FindZLIB doesn't recreate it
add_library(ZLIB::ZLIB ALIAS zlib)

1
externals/zlib-ng/zlib-ng vendored Submodule

View File

@ -8,8 +8,6 @@ add_executable(citra
default_ini.h
emu_window/emu_window_sdl2.cpp
emu_window/emu_window_sdl2.h
lodepng_image_interface.cpp
lodepng_image_interface.h
precompiled_headers.h
resource.h
)
@ -17,7 +15,7 @@ add_executable(citra
create_target_directory_groups(citra)
target_link_libraries(citra PRIVATE common core input_common network)
target_link_libraries(citra PRIVATE inih glad lodepng)
target_link_libraries(citra PRIVATE inih glad)
if (MSVC)
target_link_libraries(citra PRIVATE getopt)
endif()

View File

@ -10,7 +10,6 @@
// This needs to be included before getopt.h because the latter #defines symbols used by it
#include "citra/config.h"
#include "citra/emu_window/emu_window_sdl2.h"
#include "citra/lodepng_image_interface.h"
#include "common/common_paths.h"
#include "common/detached_tasks.h"
#include "common/file_util.h"
@ -351,9 +350,6 @@ int main(int argc, char** argv) {
// Register frontend applets
Frontend::RegisterDefaultApplets();
// Register generic image interface
Core::System::GetInstance().RegisterImageInterface(std::make_shared<LodePNGImageInterface>());
EmuWindow_SDL2::InitializeSDL2();
const auto emu_window{std::make_unique<EmuWindow_SDL2>(fullscreen, false)};

View File

@ -1,29 +0,0 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <lodepng.h>
#include "citra/lodepng_image_interface.h"
#include "common/logging/log.h"
bool LodePNGImageInterface::DecodePNG(std::vector<u8>& dst, u32& width, u32& height,
const std::string& path) {
u32 lodepng_ret = lodepng::decode(dst, width, height, path);
if (lodepng_ret) {
LOG_CRITICAL(Frontend, "Failed to decode {} because {}", path,
lodepng_error_text(lodepng_ret));
return false;
}
return true;
}
bool LodePNGImageInterface::EncodePNG(const std::string& path, const std::vector<u8>& src,
u32 width, u32 height) {
u32 lodepng_ret = lodepng::encode(path, src, width, height);
if (lodepng_ret) {
LOG_CRITICAL(Frontend, "Failed to encode {} because {}", path,
lodepng_error_text(lodepng_ret));
return false;
}
return true;
}

View File

@ -1,14 +0,0 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/frontend/image_interface.h"
class LodePNGImageInterface final : public Frontend::ImageInterface {
public:
bool DecodePNG(std::vector<u8>& dst, u32& width, u32& height, const std::string& path) override;
bool EncodePNG(const std::string& path, const std::vector<u8>& src, u32 width,
u32 height) override;
};

View File

@ -165,10 +165,10 @@ add_executable(citra-qt
multiplayer/state.h
multiplayer/validation.h
precompiled_headers.h
resource_pack_manager.cpp
resource_pack_manager.h
uisettings.cpp
uisettings.h
qt_image_interface.cpp
qt_image_interface.h
updater/updater.cpp
updater/updater.h
updater/updater_p.h
@ -266,7 +266,8 @@ endif()
create_target_directory_groups(citra-qt)
target_link_libraries(citra-qt PRIVATE audio_core common core input_common network video_core)
target_link_libraries(citra-qt PRIVATE Boost::boost glad vma vulkan-headers nihstro-headers Qt5::Widgets Qt5::Multimedia)
target_link_libraries(citra-qt PRIVATE Boost::boost glad vma vulkan-headers nihstro-headers)
target_link_libraries(citra-qt PRIVATE Qt5::Widgets Qt5::Multimedia)
target_link_libraries(citra-qt PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)
if (NOT WIN32)

View File

@ -50,7 +50,6 @@
#include "citra_qt/movie/movie_play_dialog.h"
#include "citra_qt/movie/movie_record_dialog.h"
#include "citra_qt/multiplayer/state.h"
#include "citra_qt/qt_image_interface.h"
#include "citra_qt/uisettings.h"
#include "citra_qt/updater/updater.h"
#include "citra_qt/util/clickable_label.h"
@ -561,6 +560,8 @@ void GMainWindow::InitializeHotkeys() {
});
connect_shortcut(QStringLiteral("Toggle Texture Dumping"),
[&] { Settings::values.dump_textures = !Settings::values.dump_textures; });
connect_shortcut(QStringLiteral("Toggle Custom Textures"),
[&] { Settings::values.custom_textures = !Settings::values.custom_textures; });
// We use "static" here in order to avoid capturing by lambda due to a MSVC bug, which makes
// the variable hold a garbage value after this function exits
static constexpr u16 SPEED_LIMIT_STEP = 5;
@ -2649,9 +2650,6 @@ int main(int argc, char* argv[]) {
system.RegisterMiiSelector(std::make_shared<QtMiiSelector>(main_window));
system.RegisterSoftwareKeyboard(std::make_shared<QtKeyboard>(main_window));
// Register Qt image interface
system.RegisterImageInterface(std::make_shared<QtImageInterface>());
main_window.show();
QObject::connect(&app, &QGuiApplication::applicationStateChanged, &main_window,

View File

@ -1,38 +0,0 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <QImage>
#include <QString>
#include "citra_qt/qt_image_interface.h"
#include "common/logging/log.h"
bool QtImageInterface::DecodePNG(std::vector<u8>& dst, u32& width, u32& height,
const std::string& path) {
QImage image(QString::fromStdString(path));
if (image.isNull()) {
LOG_ERROR(Frontend, "Failed to open {} for decoding", path);
return false;
}
width = image.width();
height = image.height();
image = image.convertToFormat(QImage::Format_RGBA8888);
// Write RGBA8 to vector
dst = std::vector<u8>(image.constBits(), image.constBits() + (width * height * 4));
return true;
}
bool QtImageInterface::EncodePNG(const std::string& path, const std::vector<u8>& src, u32 width,
u32 height) {
QImage image(src.data(), width, height, QImage::Format_RGBA8888);
if (!image.save(QString::fromStdString(path), "PNG")) {
LOG_ERROR(Frontend, "Failed to save {}", path);
return false;
}
return true;
}

View File

@ -1,14 +0,0 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include "core/frontend/image_interface.h"
class QtImageInterface final : public Frontend::ImageInterface {
public:
bool DecodePNG(std::vector<u8>& dst, u32& width, u32& height, const std::string& path) override;
bool EncodePNG(const std::string& path, const std::vector<u8>& src, u32 width,
u32 height) override;
};

View File

@ -0,0 +1,311 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <QDesktopServices>
#include <QDialogButtonBox>
#include <QGridLayout>
#include <QHeaderView>
#include <QPushButton>
#include <QTableWidget>
#include <QUrl>
#include "citra_qt/resource_pack/manager.h"
#include "citra_qt/resource_pack_manager.h"
#include "common/file_util.h"
ResourcePackManager::ResourcePackManager(QWidget* widget) : QDialog(widget) {
CreateWidgets();
ConnectWidgets();
RepopulateTable();
setWindowTitle(tr("Resource Pack Manager"));
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
resize(QSize(900, 600));
}
void ResourcePackManager::CreateWidgets() {
auto* layout = new QGridLayout;
m_table_widget = new QTableWidget;
m_table_widget->setTabKeyNavigation(false);
m_open_directory_button = new QPushButton(tr("Open Directory..."));
m_change_button = new QPushButton(tr("Install"));
m_remove_button = new QPushButton(tr("Remove"));
m_refresh_button = new QPushButton(tr("Refresh"));
m_priority_up_button = new QPushButton(tr("Up"));
m_priority_down_button = new QPushButton(tr("Down"));
auto* buttons = new QDialogButtonBox(QDialogButtonBox::Ok);
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
layout->addWidget(m_table_widget, 0, 0, 7, 1);
layout->addWidget(m_open_directory_button, 0, 1);
layout->addWidget(m_change_button, 1, 1);
layout->addWidget(m_remove_button, 2, 1);
layout->addWidget(m_refresh_button, 3, 1);
layout->addWidget(m_priority_up_button, 4, 1);
layout->addWidget(m_priority_down_button, 5, 1);
layout->addWidget(buttons, 7, 1, Qt::AlignRight);
setLayout(layout);
setLayout(layout);
}
void ResourcePackManager::ConnectWidgets() {
connect(m_open_directory_button, &QPushButton::clicked, this,
&ResourcePackManager::OpenResourcePackDir);
connect(m_refresh_button, &QPushButton::clicked, this, &ResourcePackManager::Refresh);
connect(m_change_button, &QPushButton::clicked, this, &ResourcePackManager::Change);
connect(m_remove_button, &QPushButton::clicked, this, &ResourcePackManager::Remove);
connect(m_priority_up_button, &QPushButton::clicked, this, &ResourcePackManager::PriorityUp);
connect(m_priority_down_button, &QPushButton::clicked, this,
&ResourcePackManager::PriorityDown);
connect(m_table_widget, &QTableWidget::itemSelectionChanged, this,
&ResourcePackManager::SelectionChanged);
connect(m_table_widget, &QTableWidget::itemDoubleClicked, this,
&ResourcePackManager::ItemDoubleClicked);
}
void ResourcePackManager::OpenResourcePackDir() {
QDesktopServices::openUrl(
QUrl::fromLocalFile(QString::fromStdString(File::GetUserPath(D_RESOURCEPACK_IDX))));
}
void ResourcePackManager::RepopulateTable() {
m_table_widget->clear();
m_table_widget->setColumnCount(6);
m_table_widget->setHorizontalHeaderLabels(
{QString{}, tr("Name"), tr("Version"), tr("Description"), tr("Author"), tr("Website")});
auto* header = m_table_widget->horizontalHeader();
for (int i = 0; i < 4; i++)
header->setSectionResizeMode(i, QHeaderView::ResizeToContents);
header->setStretchLastSection(true);
header->setHighlightSections(false);
int size = static_cast<int>(ResourcePack::GetPacks().size());
m_table_widget->setSelectionBehavior(QAbstractItemView::SelectRows);
m_table_widget->setSelectionMode(QAbstractItemView::SingleSelection);
m_table_widget->setRowCount(size);
m_table_widget->setIconSize(QSize(32, 32));
for (int i = 0; i < size; i++) {
const auto& pack = ResourcePack::GetPacks()[size - 1 - i];
const auto* manifest = pack.GetManifest();
const auto& authors = manifest->GetAuthors();
auto* logo_item = new QTableWidgetItem;
auto* name_item = new QTableWidgetItem(QString::fromStdString(manifest->GetName()));
auto* version_item = new QTableWidgetItem(QString::fromStdString(manifest->GetVersion()));
auto* author_item =
new QTableWidgetItem(authors ? QString::fromStdString(*authors) : tr("Unknown author"));
auto* description_item =
new QTableWidgetItem(QString::fromStdString(manifest->GetDescription().value_or("")));
auto* website_item =
new QTableWidgetItem(QString::fromStdString(manifest->GetWebsite().value_or("")));
QPixmap logo;
logo.loadFromData(reinterpret_cast<const uchar*>(pack.GetLogo().data()),
(int)pack.GetLogo().size());
logo_item->setIcon(QIcon(logo));
QFont link_font = website_item->font();
link_font.setUnderline(true);
website_item->setFont(link_font);
website_item->setForeground(QBrush(Qt::blue));
website_item->setData(Qt::UserRole, website_item->text());
for (auto* item :
{logo_item, name_item, version_item, author_item, description_item, website_item}) {
item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
if (ResourcePack::IsInstalled(pack)) {
item->setBackground(QColor(Qt::green));
auto font = item->font();
font.setBold(true);
item->setFont(font);
}
}
m_table_widget->setItem(i, 0, logo_item);
m_table_widget->setItem(i, 1, name_item);
m_table_widget->setItem(i, 2, version_item);
m_table_widget->setItem(i, 3, description_item);
m_table_widget->setItem(i, 4, author_item);
m_table_widget->setItem(i, 5, website_item);
}
SelectionChanged();
}
// Revert the indicies as to be more intuitive for users
int ResourcePackManager::GetResourcePackIndex(QTableWidgetItem* item) const {
return m_table_widget->rowCount() - 1 - item->row();
}
void ResourcePackManager::Change() {
auto items = m_table_widget->selectedItems();
if (items.empty())
return;
if (ResourcePack::IsInstalled(ResourcePack::GetPacks()[GetResourcePackIndex(items[0])])) {
Uninstall();
} else {
Install();
}
}
void ResourcePackManager::Install() {
auto items = m_table_widget->selectedItems();
if (items.empty())
return;
auto& item = ResourcePack::GetPacks()[GetResourcePackIndex(items[0])];
bool success = item.Install(File::GetUserPath(D_LOAD_IDX));
if (!success) {
ModalMessageBox::critical(
this, tr("Error"),
tr("Failed to install pack: %1").arg(QString::fromStdString(item.GetError())));
}
RepopulateTable();
}
void ResourcePackManager::Uninstall() {
auto items = m_table_widget->selectedItems();
if (items.empty())
return;
auto& item = ResourcePack::GetPacks()[GetResourcePackIndex(items[0])];
bool success = item.Uninstall(File::GetUserPath(D_LOAD_IDX));
if (!success) {
ModalMessageBox::critical(
this, tr("Error"),
tr("Failed to uninstall pack: %1").arg(QString::fromStdString(item.GetError())));
}
RepopulateTable();
}
void ResourcePackManager::Remove() {
auto items = m_table_widget->selectedItems();
if (items.empty())
return;
ModalMessageBox box(this);
box.setWindowTitle(tr("Confirmation"));
box.setText(tr("Are you sure you want to delete this pack?"));
box.setIcon(QMessageBox::Warning);
box.setStandardButtons(QMessageBox::Yes | QMessageBox::Abort);
if (box.exec() != QMessageBox::Yes)
return;
Uninstall();
File::Delete(ResourcePack::GetPacks()[GetResourcePackIndex(items[0])].GetPath());
RepopulateTable();
}
void ResourcePackManager::PriorityDown() {
auto items = m_table_widget->selectedItems();
if (items.empty())
return;
auto row = GetResourcePackIndex(items[0]);
if (items[0]->row() >= m_table_widget->rowCount())
return;
auto& pack = ResourcePack::GetPacks()[row];
std::string path = pack.GetPath();
row--;
ResourcePack::Remove(pack);
ResourcePack::Add(path, row);
RepopulateTable();
m_table_widget->selectRow(row == 0 ? m_table_widget->rowCount() - 1 : row);
}
void ResourcePackManager::PriorityUp() {
auto items = m_table_widget->selectedItems();
if (items.empty())
return;
auto row = GetResourcePackIndex(items[0]);
if (items[0]->row() == 0)
return;
auto& pack = ResourcePack::GetPacks()[row];
std::string path = pack.GetPath();
row++;
ResourcePack::Remove(pack);
ResourcePack::Add(path, items[0]->row() == m_table_widget->rowCount() ? -1 : row);
RepopulateTable();
m_table_widget->selectRow(row == m_table_widget->rowCount() - 1 ? 0 : row);
}
void ResourcePackManager::Refresh() {
ResourcePack::Init();
RepopulateTable();
}
void ResourcePackManager::SelectionChanged() {
auto items = m_table_widget->selectedItems();
const bool has_selection = !items.empty();
if (has_selection) {
m_change_button->setText(
ResourcePack::IsInstalled(ResourcePack::GetPacks()[GetResourcePackIndex(items[0])])
? tr("Uninstall")
: tr("Install"));
}
for (auto* item : {m_change_button, m_remove_button})
item->setEnabled(has_selection);
m_priority_down_button->setEnabled(has_selection &&
items[0]->row() < m_table_widget->rowCount() - 1);
m_priority_up_button->setEnabled(has_selection && items[0]->row() != 0);
}
void ResourcePackManager::ItemDoubleClicked(QTableWidgetItem* item) {
auto item_data = item->data(Qt::UserRole);
if (item_data.isNull())
return;
QDesktopServices::openUrl(QUrl(item_data.toString()));
}

View File

@ -0,0 +1,42 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <QDialog>
class QPushButton;
class QTableWidget;
class QTableWidgetItem;
class ResourcePackManager : public QDialog {
public:
explicit ResourcePackManager(QWidget* parent = nullptr);
private:
void CreateWidgets();
void ConnectWidgets();
void OpenResourcePackDir();
void RepopulateTable();
void Change();
void Install();
void Uninstall();
void Remove();
void PriorityUp();
void PriorityDown();
void Refresh();
void SelectionChanged();
void ItemDoubleClicked(QTableWidgetItem* item);
int GetResourcePackIndex(QTableWidgetItem* item) const;
QPushButton* m_open_directory_button;
QPushButton* m_change_button;
QPushButton* m_remove_button;
QPushButton* m_refresh_button;
QPushButton* m_priority_up_button;
QPushButton* m_priority_down_button;
QTableWidget* m_table_widget;
};

View File

@ -66,6 +66,7 @@ add_library(common STATIC
detached_tasks.h
bit_field.h
bit_set.h
bit_util.h
cityhash.cpp
cityhash.h
color.h
@ -74,11 +75,14 @@ add_library(common STATIC
common_precompiled_headers.h
common_types.h
construct.h
dds-ktx.h
error.cpp
error.h
file_util.cpp
file_util.h
hash.h
image_util.cpp
image_util.h
linear_disk_cache.h
literals.h
logging/backend.cpp
@ -97,16 +101,24 @@ add_library(common STATIC
microprofile.cpp
microprofile.h
microprofileui.h
minizip_util.h
misc.cpp
param_package.cpp
param_package.h
polyfill_thread.h
precompiled_headers.h
quaternion.h
resource_pack/manager.cpp
resource_pack/manager.h
resource_pack/manifest.cpp
resource_pack/manifest.h
resource_pack/resource_pack.cpp
resource_pack/resource_pack.h
ring_buffer.h
scm_rev.cpp
scm_rev.h
scope_exit.h
scratch_buffer.h
settings.cpp
settings.h
serialization/atomic.h
@ -143,7 +155,7 @@ add_library(common STATIC
create_target_directory_groups(common)
target_link_libraries(common PUBLIC fmt::fmt microprofile Boost::boost Boost::serialization)
target_link_libraries(common PRIVATE libzstd_static)
target_link_libraries(common PRIVATE libzstd_static spng::spng json-headers minizip-ng inih)
set_target_properties(common PROPERTIES INTERPROCEDURAL_OPTIMIZATION ${ENABLE_LTO})
if ("x86_64" IN_LIST ARCHITECTURE)

View File

@ -13,25 +13,27 @@ namespace Common {
struct AsyncHandle {
public:
[[nodiscard]] bool IsBuilt() noexcept {
return is_built.load(std::memory_order::relaxed);
AsyncHandle(bool is_done_ = false) : is_done{is_done_} {}
[[nodiscard]] bool IsDone() noexcept {
return is_done.load(std::memory_order::relaxed);
}
void WaitBuilt() noexcept {
void WaitDone() noexcept {
std::unique_lock lock{mutex};
condvar.wait(lock, [this] { return is_built.load(std::memory_order::relaxed); });
condvar.wait(lock, [this] { return is_done.load(std::memory_order::relaxed); });
}
void MarkBuilt() noexcept {
void MarkDone(bool done = true) noexcept {
std::scoped_lock lock{mutex};
is_built = true;
is_done = done;
condvar.notify_all();
}
private:
std::condition_variable condvar;
std::mutex mutex;
std::atomic_bool is_built{false};
std::atomic_bool is_done{false};
};
} // namespace Common

66
src/common/bit_util.h Normal file
View File

@ -0,0 +1,66 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <bit>
#include <climits>
#include <cstddef>
#include <type_traits>
#include "common/common_types.h"
namespace Common {
/// Gets the size of a specified type T in bits.
template <typename T>
[[nodiscard]] constexpr std::size_t BitSize() {
return sizeof(T) * CHAR_BIT;
}
[[nodiscard]] constexpr u32 MostSignificantBit32(const u32 value) {
return 31U - static_cast<u32>(std::countl_zero(value));
}
[[nodiscard]] constexpr u32 MostSignificantBit64(const u64 value) {
return 63U - static_cast<u32>(std::countl_zero(value));
}
[[nodiscard]] constexpr u32 Log2Floor32(const u32 value) {
return MostSignificantBit32(value);
}
[[nodiscard]] constexpr u32 Log2Floor64(const u64 value) {
return MostSignificantBit64(value);
}
[[nodiscard]] constexpr u32 Log2Ceil32(const u32 value) {
const u32 log2_f = Log2Floor32(value);
return log2_f + static_cast<u32>((value ^ (1U << log2_f)) != 0U);
}
[[nodiscard]] constexpr u32 Log2Ceil64(const u64 value) {
const u64 log2_f = Log2Floor64(value);
return static_cast<u32>(log2_f + static_cast<u64>((value ^ (1ULL << log2_f)) != 0ULL));
}
template <typename T>
requires std::is_unsigned_v<T>
[[nodiscard]] constexpr bool IsPow2(T value) {
return std::has_single_bit(value);
}
template <typename T>
requires std::is_integral_v<T>
[[nodiscard]] T NextPow2(T value) {
return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U)));
}
template <size_t bit_index, typename T>
requires std::is_integral_v<T>
[[nodiscard]] constexpr bool Bit(const T value) {
static_assert(bit_index < BitSize<T>(), "bit_index must be smaller than size of T");
return ((value >> bit_index) & T(1)) == T(1);
}
} // namespace Common

View File

@ -52,6 +52,7 @@
#define LOAD_DIR "load"
#define SHADER_DIR "shaders"
#define STATES_DIR "states"
#define RESOURCEPACK_DIR "resource_packs"
// Filenames
// Files in the directory returned by GetUserPath(UserPath::LogDir)

1465
src/common/dds-ktx.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -473,6 +473,48 @@ u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry,
return ForeachDirectoryEntry(&num_entries, directory, callback) ? num_entries : 0;
}
std::vector<std::string> DoFileSearch(const std::vector<std::string>& directories,
const std::vector<std::string>& exts, bool recursive) {
std::vector<std::string> result;
bool accept_all = exts.empty();
const auto callback = [&exts, accept_all](const FSTEntry& entry) {
if (accept_all) {
return true;
}
if (entry.isDirectory) {
return false;
}
return std::any_of(exts.begin(), exts.end(), [&](const std::string& ext) {
const std::string& name = entry.virtualName;
return name.length() >= ext.length() &&
strcasecmp(name.c_str() + name.length() - ext.length(), ext.c_str()) == 0;
});
};
for (const std::string& directory : directories) {
FSTEntry top;
ScanDirectoryTree(directory, top, recursive);
const std::function<void(FSTEntry&)> DoEntry = [&](FSTEntry& entry) {
if (callback(entry)) {
result.push_back(entry.physicalName);
}
for (auto& child : entry.children) {
DoEntry(child);
}
};
for (auto& child : top.children)
DoEntry(child);
}
// Remove duplicates
std::sort(result.begin(), result.end());
result.erase(std::unique(result.begin(), result.end()), result.end());
return result;
}
void GetAllFilesFromNestedEntries(FSTEntry& directory, std::vector<FSTEntry>& output) {
std::vector<FSTEntry> files;
for (auto& entry : directory.children) {
@ -744,6 +786,7 @@ void SetUserPath(const std::string& path) {
g_paths.emplace(UserPath::DumpDir, user_path + DUMP_DIR DIR_SEP);
g_paths.emplace(UserPath::LoadDir, user_path + LOAD_DIR DIR_SEP);
g_paths.emplace(UserPath::StatesDir, user_path + STATES_DIR DIR_SEP);
g_paths.emplace(UserPath::ResourcePackDir, user_path + RESOURCEPACK_DIR DIR_SEP);
g_default_paths = g_paths;
}

View File

@ -40,6 +40,7 @@ enum class UserPath {
StatesDir,
SysDataDir,
UserDir,
ResourcePackDir,
};
// Replaces install-specific paths with standard placeholders, and back again
@ -159,6 +160,17 @@ bool ForeachDirectoryEntry(u64* num_entries_out, const std::string& directory,
u64 ScanDirectoryTree(const std::string& directory, FSTEntry& parent_entry,
unsigned int recursion = 0);
/**
* Searches a list of directories for files with any of the provided extensions
* @param directories the list of directories to search
* @param exts the extensions of the files to consider
* @param resursive if the search should be recursive
* @return the list of files that were found
*/
std::vector<std::string> DoFileSearch(const std::vector<std::string>& directories,
const std::vector<std::string>& exts = {},
bool recursive = false);
/**
* Recursively searches through a FSTEntry for files, and stores them.
* @param directory The FSTEntry to start scanning from
@ -339,6 +351,9 @@ public:
[[nodiscard]] explicit operator bool() const {
return IsGood();
}
[[nodiscard]] std::FILE* Handle() {
return m_file;
}
bool Seek(s64 off, int origin);
[[nodiscard]] u64 Tell() const;

153
src/common/image_util.cpp Normal file
View File

@ -0,0 +1,153 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <spng.h>
#define DDSKTX_IMPLEMENT
#include "common/file_util.h"
#include "common/image_util.h"
#include "common/logging/log.h"
namespace Common {
namespace {
void spng_free(spng_ctx* ctx) {
if (ctx) {
spng_ctx_free(ctx);
}
}
auto make_spng_ctx(int flags) {
return std::unique_ptr<spng_ctx, decltype(&spng_free)>(spng_ctx_new(flags), spng_free);
}
} // Anonymous namespace
bool ParsePNG(std::span<const u8> png_data, size_t& decoded_size, u32& width, u32& height) {
auto ctx = make_spng_ctx(0);
if (!ctx) [[unlikely]] {
return false;
}
if (spng_set_png_buffer(ctx.get(), png_data.data(), png_data.size())) {
return false;
}
spng_ihdr ihdr{};
if (spng_get_ihdr(ctx.get(), &ihdr)) {
return false;
}
width = ihdr.width;
height = ihdr.height;
const int format = SPNG_FMT_RGBA8;
if (spng_decoded_image_size(ctx.get(), format, &decoded_size)) {
return false;
}
return true;
}
bool DecodePNG(std::span<const u8> png_data, std::span<u8> out_data) {
auto ctx = make_spng_ctx(0);
if (!ctx) [[unlikely]] {
return false;
}
if (spng_set_png_buffer(ctx.get(), png_data.data(), png_data.size())) {
return false;
}
const int format = SPNG_FMT_RGBA8;
size_t decoded_len = 0;
if (spng_decoded_image_size(ctx.get(), format, &decoded_len)) {
return false;
}
ASSERT(out_data.size() == decoded_len);
if (spng_decode_image(ctx.get(), out_data.data(), decoded_len, format, 0)) {
return false;
}
return true;
}
bool ParseDDSKTX(std::span<const u8> in_data, std::vector<u8>& out_data, u32& width, u32& height,
ddsktx_format& format) {
ddsktx_texture_info tc{};
if (!ddsktx_parse(&tc, in_data.data(), in_data.size(), nullptr)) {
return false;
}
width = tc.width;
height = tc.height;
format = tc.format;
ddsktx_sub_data sub_data{};
ddsktx_get_sub(&tc, &sub_data, in_data.data(), in_data.size(), 0, 0, 0);
out_data.resize(sub_data.size_bytes);
std::memcpy(out_data.data(), sub_data.buff, sub_data.size_bytes);
return true;
}
bool EncodePNG(const std::string& out_path, std::span<u8> in_data, u32 width, u32 height,
s32 level) {
auto ctx = make_spng_ctx(SPNG_CTX_ENCODER);
if (!ctx) [[unlikely]] {
return false;
}
if (spng_set_option(ctx.get(), SPNG_IMG_COMPRESSION_LEVEL, level)) {
return false;
}
if (spng_set_option(ctx.get(), SPNG_ENCODE_TO_BUFFER, 1)) {
return false;
}
spng_ihdr ihdr{};
ihdr.width = width;
ihdr.height = height;
ihdr.color_type = SPNG_COLOR_TYPE_TRUECOLOR_ALPHA;
ihdr.bit_depth = 8;
if (spng_set_ihdr(ctx.get(), &ihdr)) {
return false;
}
if (spng_encode_image(ctx.get(), in_data.data(), in_data.size(), SPNG_FMT_PNG,
SPNG_ENCODE_FINALIZE)) {
return false;
}
int ret{};
size_t png_size{};
u8* png_buf = reinterpret_cast<u8*>(spng_get_png_buffer(ctx.get(), &png_size, &ret));
if (!png_buf) {
return false;
}
auto file = FileUtil::IOFile(out_path, "wb");
file.WriteBytes(png_buf, png_size);
size_t image_len = 0;
spng_decoded_image_size(ctx.get(), SPNG_FMT_PNG, &image_len);
LOG_ERROR(Common, "{} byte {} by {} image saved to {} at level {}", image_len, width, height,
out_path, level);
return true;
}
void FlipTexture(std::span<u8> in_data, u32 width, u32 height, u32 stride) {
for (u32 line = 0; line < height / 2; line++) {
const u32 offset_1 = line * stride;
const u32 offset_2 = (height - line - 1) * stride;
// Swap lines
std::swap_ranges(in_data.begin() + offset_1, in_data.begin() + offset_1 + stride,
in_data.begin() + offset_2);
}
}
} // namespace Common

24
src/common/image_util.h Normal file
View File

@ -0,0 +1,24 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <span>
#include <vector>
#include "common/common_types.h"
#include "common/dds-ktx.h"
namespace Common {
bool ParsePNG(std::span<const u8> png_data, size_t& decoded_size, u32& width, u32& height);
bool DecodePNG(std::span<const u8> png_data, std::span<u8> out_data);
bool ParseDDSKTX(std::span<const u8> in_data, std::vector<u8>& out_data, u32& width, u32& height,
ddsktx_format& format);
bool EncodePNG(const std::string& out_path, std::span<u8> in_data, u32 width, u32 height,
s32 level = 6);
void FlipTexture(std::span<u8> in_data, u32 width, u32 height, u32 stride);
} // namespace Common

46
src/common/minizip_util.h Normal file
View File

@ -0,0 +1,46 @@
// Copyright 2019 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <algorithm>
#include <mz_compat.h>
#include "common/common_types.h"
#include "common/scope_exit.h"
namespace Common {
// Reads all of the current file. destination must be big enough to fit the whole file.
inline bool ReadFileFromZip(unzFile file, u8* destination, u64 len) {
const u64 MAX_BUFFER_SIZE = 65535;
if (unzOpenCurrentFile(file) != UNZ_OK) {
return false;
}
SCOPE_EXIT({ unzCloseCurrentFile(file); });
u64 bytes_to_go = len;
while (bytes_to_go > 0) {
// NOTE: multiples of 4G can't cause read_len == 0 && bytes_to_go > 0, as MAX_BUFFER_SIZE is
// small.
const u32 read_len = static_cast<u32>(std::min(bytes_to_go, MAX_BUFFER_SIZE));
const int rv = unzReadCurrentFile(file, destination, read_len);
if (rv < 0) {
return false;
}
const u32 bytes_read = static_cast<u32>(rv);
bytes_to_go -= bytes_read;
destination += bytes_read;
}
return unzEndOfFile(file) == 1;
}
template <typename ContiguousContainer>
bool ReadFileFromZip(unzFile file, ContiguousContainer* destination) {
return ReadFileFromZip(file, reinterpret_cast<u8*>(destination->data()), destination->size());
}
} // namespace Common

View File

@ -0,0 +1,161 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <inih/cpp/INIReader.h>
#include "common/common_types.h"
#include "common/file_util.h"
#include "common/resource_pack/manager.h"
namespace Common::ResourcePack {
Manager::Manager() {
packs_path = FileUtil::GetUserPath(FileUtil::UserPath::ResourcePackDir);
reader = std::make_unique<INIReader>(packs_path);
auto pack_list = FileUtil::DoFileSearch({packs_path}, {".zip"});
auto* order = file.GetOrCreateSection("Order");
struct OrderHelper {
size_t pack_list_index;
std::string manifest_id;
};
std::vector<OrderHelper> pack_list_order;
pack_list_order.reserve(pack_list.size());
for (size_t i = 0; i < pack_list.size(); ++i) {
const std::string pack_path = pack_list[i].physicalName;
const ResourcePack pack(pack_path);
std::string manifest_id = pack.IsValid() ? pack.GetManifest().id : pack_path;
pack_list_order.emplace_back(OrderHelper{i, std::move(manifest_id)});
}
std::sort(
pack_list_order.begin(), pack_list_order.end(),
[](const OrderHelper& a, const OrderHelper& b) { return a.manifest_id < b.manifest_id; });
bool error = false;
for (size_t i = 0; i < pack_list_order.size(); ++i) {
const auto& path = pack_list[pack_list_order[i].pack_list_index].physicalName;
const ResourcePack* const pack = Add(path);
if (pack == nullptr) {
error = true;
continue;
}
order->Set(pack->GetManifest().id, static_cast<u64>(i));
}
file.Save(packs_path);
}
ResourcePack* Manager::Add(const std::string& path, int offset) {
if (offset == -1)
offset = static_cast<int>(packs.size());
ResourcePack pack(path);
if (!pack.IsValid())
return nullptr;
IniFile file = GetPackConfig();
auto* order = file.GetOrCreateSection("Order");
order->Set(pack.GetManifest()->GetID(), offset);
for (int i = offset; i < static_cast<int>(packs.size()); i++)
order->Set(packs[i].GetManifest()->GetID(), i + 1);
file.Save(packs_path);
auto it = packs.insert(packs.begin() + offset, std::move(pack));
return &*it;
}
bool Manager::Remove(ResourcePack& pack) {
const auto result = pack.Uninstall(File::GetUserPath(D_USER_IDX));
if (!result)
return false;
auto pack_iterator = std::find(packs.begin(), packs.end(), pack);
if (pack_iterator == packs.end())
return false;
IniFile file = GetPackConfig();
auto* order = file.GetOrCreateSection("Order");
order->Delete(pack.GetManifest().id);
int offset = pack_iterator - packs.begin();
for (int i = offset + 1; i < static_cast<int>(packs.size()); i++)
order->Set(packs[i].GetManifest().id, i - 1);
file.Save(packs_path);
packs.erase(pack_iterator);
return true;
}
void Manager::SetInstalled(const ResourcePack& pack, bool installed) {
IniFile file = GetPackConfig();
auto* install = file.GetOrCreateSection("Installed");
if (installed)
install->Set(pack.GetManifest().id, installed);
else
install->Delete(pack.GetManifest().id);
file.Save(packs_path);
}
bool Manager::IsInstalled(const ResourcePack& pack) {
IniFile file = GetPackConfig();
auto* install = file.GetOrCreateSection("Installed");
bool installed;
install->Get(pack.GetManifest().id, &installed, false);
return installed;
}
std::vector<ResourcePack*> Manager::GetLowerPriorityPacks(ResourcePack& pack) {
std::vector<ResourcePack*> list;
for (auto it = std::find(packs.begin(), packs.end(), pack) + 1; it != packs.end(); ++it) {
auto& entry = *it;
if (!IsInstalled(pack)) {
continue;
}
list.push_back(&entry);
}
return list;
}
std::vector<ResourcePack*> Manager::GetHigherPriorityPacks(ResourcePack& pack) {
std::vector<ResourcePack*> list;
auto end = std::find(packs.begin(), packs.end(), pack);
for (auto it = packs.begin(); it != end; ++it) {
auto& entry = *it;
if (!IsInstalled(entry)) {
continue;
}
list.push_back(&entry);
}
return list;
}
} // namespace Common::ResourcePack

View File

@ -0,0 +1,49 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <span>
#include <string>
#include <vector>
#include "common/resource_pack/resource_pack.h"
class INIReader;
namespace Common::ResourcePack {
class Manager {
public:
Manager();
ResourcePack* Add(const std::string& path, int offset = -1);
bool Remove(ResourcePack& pack);
void SetInstalled(const ResourcePack& pack, bool installed);
bool IsInstalled(const ResourcePack& pack);
std::span<ResourcePack> GetPacks() {
return packs;
}
std::vector<ResourcePack*> GetHigherPriorityPacks(ResourcePack& pack);
std::vector<ResourcePack*> GetLowerPriorityPacks(ResourcePack& pack);
private:
std::unique_ptr<INIReader> reader;
std::vector<ResourcePack> packs;
std::string packs_path;
};
bool Init();
ResourcePack* Add(const std::string& path, int offset = -1);
bool Remove(ResourcePack& pack);
void SetInstalled(const ResourcePack& pack, bool installed);
bool IsInstalled(const ResourcePack& pack);
std::vector<ResourcePack>& GetPacks();
std::vector<ResourcePack*> GetHigherPriorityPacks(ResourcePack& pack);
std::vector<ResourcePack*> GetLowerPriorityPacks(ResourcePack& pack);
} // namespace Common::ResourcePack

View File

@ -0,0 +1,39 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/resource_pack/manifest.h"
namespace Common::ResourcePack {
template <typename T>
std::optional<T> GetOptional(const nlohmann::json& j, Manifest& manifest, std::string_view name) {
try {
return j.at(name).get<T>();
} catch (const nlohmann::detail::out_of_range&) {
LOG_DEBUG(Common, "Manifest {} does not state property: {}", manifest.name, name);
}
return std::nullopt;
}
void from_json(const nlohmann::json& j, Manifest& manifest) {
try {
manifest.name = j.at("name").get<std::string>();
manifest.version = j.at("version").get<std::string>();
manifest.id = j.at("id").get<std::string>();
manifest.description = j.at("description").get<std::string>();
} catch (const nlohmann::detail::out_of_range&) {
manifest.error = "Some required fields are missing";
manifest.valid = false;
return;
}
manifest.website = GetOptional<std::string>(j, manifest, "website");
manifest.authors = GetOptional<std::string>(j, manifest, "authors");
const auto compressed = GetOptional<bool>(j, manifest, "compressed");
if (compressed.has_value()) {
manifest.compressed = compressed.value();
}
}
} // namespace Common::ResourcePack

View File

@ -0,0 +1,28 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <optional>
#include <string>
#include <json.hpp>
namespace Common::ResourcePack {
struct Manifest {
bool valid = true;
bool compressed = false;
std::string name;
std::string version;
std::string id;
std::string error;
std::string description;
std::optional<std::string> authors;
std::optional<std::string> website;
};
void to_json(nlohmann::json& j, const Manifest& manifest);
void from_json(const nlohmann::json& j, Manifest& manifest);
} // namespace Common::ResourcePack

View File

@ -0,0 +1,255 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <algorithm>
#include <limits>
#include <memory>
#include <json.hpp>
#include <mz_compat.h>
#include <mz_os.h>
#include "common/common_paths.h"
#include "common/file_util.h"
#include "common/minizip_util.h"
#include "common/resource_pack/manager.h"
#include "common/resource_pack/manifest.h"
#include "common/resource_pack/resource_pack.h"
#include "common/string_util.h"
namespace Common::ResourcePack {
constexpr char TEXTURE_PATH[] = LOAD_DIR DIR_SEP;
ResourcePack::ResourcePack(const std::string& path) : m_path(path) {
unzFile file = unzOpen(path.c_str());
SCOPE_EXIT({ unzClose(file); });
if (!file) {
m_valid = false;
m_error = "Failed to open resource pack";
return;
}
if (unzLocateFile(file, "manifest.json", 0) == UNZ_END_OF_LIST_OF_FILE) {
m_valid = false;
m_error = "Resource pack is missing a manifest.";
return;
}
unz_file_info64 manifest_info{};
unzGetCurrentFileInfo64(file, &manifest_info, nullptr, 0, nullptr, 0, nullptr, 0);
std::string manifest_contents(manifest_info.uncompressed_size, '\0');
if (!Common::ReadFileFromZip(file, &manifest_contents)) {
m_valid = false;
m_error = "Failed to read manifest.json";
return;
}
unzCloseCurrentFile(file);
auto manifest_json = nlohmann::json::parse(manifest_contents);
m_manifest = manifest_json.get<Manifest>();
if (!m_manifest.valid) {
m_valid = false;
m_error = "Manifest error: " + m_manifest.error;
return;
}
if (unzLocateFile(file, "logo.png", 0) != UNZ_END_OF_LIST_OF_FILE) {
unz_file_info64 logo_info{};
unzGetCurrentFileInfo64(file, &logo_info, nullptr, 0, nullptr, 0, nullptr, 0);
m_logo_data.resize(logo_info.uncompressed_size);
if (!Common::ReadFileFromZip(file, &m_logo_data)) {
m_valid = false;
m_error = "Failed to read logo.png";
return;
}
}
unzGoToFirstFile(file);
do {
std::string filename(256, '\0');
unz_file_info64 texture_info{};
unzGetCurrentFileInfo64(file, &texture_info, filename.data(),
static_cast<u16>(filename.size()), nullptr, 0, nullptr, 0);
if (filename.compare(0, 9, "textures/") != 0 || texture_info.uncompressed_size == 0)
continue;
// If a texture is compressed and the manifest doesn't state that, abort.
if (!m_manifest.compressed && texture_info.compression_method != 0) {
m_valid = false;
m_error = "Texture " + filename + " is compressed!";
return;
}
m_textures.push_back(filename.substr(9));
} while (unzGoToNextFile(file) != UNZ_END_OF_LIST_OF_FILE);
}
bool ResourcePack::Install(const std::string& path) {
if (!IsValid()) {
m_error = "Invalid pack";
return false;
}
unzFile file = unzOpen(m_path.c_str());
if (!file) {
m_valid = false;
m_error = "Failed to open resource pack";
return false;
}
SCOPE_EXIT({ unzClose(file); });
if (unzGoToFirstFile(file) != MZ_OK) {
return false;
}
std::string texture_zip_path;
do {
texture_zip_path.resize(std::numeric_limits<u16>::max() + 1, '\0');
unz_file_info64 texture_info{};
if (unzGetCurrentFileInfo64(file, &texture_info, texture_zip_path.data(), UINT16_MAX,
nullptr, 0, nullptr, 0) != MZ_OK) {
return false;
}
TruncateToCString(&texture_zip_path);
const std::string texture_zip_path_prefix = "textures/";
if (!texture_zip_path.starts_with(texture_zip_path_prefix)) {
continue;
}
const std::string texture_name = texture_zip_path.substr(texture_zip_path_prefix.size());
auto texture_it = std::find_if(
m_textures.cbegin(), m_textures.cend(), [&texture_name](const std::string& texture) {
return mz_path_compare_wc(texture.c_str(), texture_name.c_str(), 1) == MZ_OK;
});
if (texture_it == m_textures.cend())
continue;
const auto texture = *texture_it;
// Check if a higher priority pack already provides a given texture, don't overwrite it
bool provided_by_other_pack = false;
for (const auto& pack : GetHigherPriorityPacks(*this)) {
if (std::find(pack->GetTextures().begin(), pack->GetTextures().end(), texture) !=
pack->GetTextures().end()) {
provided_by_other_pack = true;
break;
}
}
if (provided_by_other_pack) {
continue;
}
const std::string texture_path = path + TEXTURE_PATH + texture;
std::string texture_full_dir;
if (!SplitPath(texture_path, &texture_full_dir, nullptr, nullptr)) {
continue;
}
if (!FileUtil::CreateFullPath(texture_full_dir)) {
m_error = "Failed to create full path " + texture_full_dir;
return false;
}
const size_t data_size = static_cast<size_t>(texture_info.uncompressed_size);
auto data = std::make_unique<u8[]>(data_size);
if (!Common::ReadFileFromZip(file, data.get(), data_size)) {
m_error = "Failed to read texture " + texture;
return false;
}
FileUtil::IOFile out(texture_path, "wb");
if (!out) {
m_error = "Failed to open " + texture;
return false;
}
if (!out.WriteBytes(data.get(), data_size)) {
m_error = "Failed to write " + texture;
return false;
}
} while (unzGoToNextFile(file) == MZ_OK);
SetInstalled(*this, true);
return true;
}
bool ResourcePack::Uninstall(const std::string& path) {
if (!IsValid()) {
m_error = "Invalid pack";
return false;
}
auto lower = GetLowerPriorityPacks(*this);
SetInstalled(*this, false);
for (const auto& texture : m_textures) {
bool provided_by_other_pack = false;
// Check if a higher priority pack already provides a given texture, don't delete it
for (const auto& pack : GetHigherPriorityPacks(*this)) {
const std::vector<std::string>& textures = pack->GetTextures();
if (IsInstalled(*pack) &&
std::find(textures.begin(), textures.end(), texture) != textures.end()) {
provided_by_other_pack = true;
break;
}
}
if (provided_by_other_pack)
continue;
// Check if a lower priority pack provides a given texture - if so, install it.
for (auto& pack : lower) {
const std::vector<std::string>& textures = pack->GetTextures();
if (IsInstalled(*pack) &&
std::find(textures.rbegin(), textures.rend(), texture) != textures.rend()) {
pack->Install(path);
provided_by_other_pack = true;
break;
}
}
if (provided_by_other_pack)
continue;
const std::string texture_path = path + TEXTURE_PATH + texture;
if (FileUtil::Exists(texture_path) && !FileUtil::Delete(texture_path)) {
m_error = "Failed to delete texture " + texture;
return false;
}
// Recursively delete empty directories
std::string dir;
SplitPath(texture_path, &dir, nullptr, nullptr);
while (dir.length() > (path + TEXTURE_PATH).length()) {
auto is_empty = FileUtil::DoFileSearch({dir}).empty();
if (is_empty) {
FileUtil::DeleteDir(dir);
}
SplitPath(dir.substr(0, dir.size() - 2), &dir, nullptr, nullptr);
}
}
return true;
}
bool ResourcePack::operator==(const ResourcePack& pack) const {
return pack.GetPath() == m_path;
}
bool ResourcePack::operator!=(const ResourcePack& pack) const {
return !operator==(pack);
}
} // namespace Common::ResourcePack

View File

@ -0,0 +1,58 @@
// Copyright 2018 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include <string>
#include <vector>
#include "common/resource_pack/manifest.h"
namespace Common::ResourcePack {
class ResourcePack {
public:
explicit ResourcePack(const std::string& path);
bool IsValid() const {
return m_valid;
}
const std::vector<char>& GetLogo() const {
return m_logo_data;
}
const std::string& GetPath() const {
return m_path;
}
const std::string& GetError() const {
return m_error;
}
const Manifest& GetManifest() const {
return m_manifest;
}
const std::vector<std::string>& GetTextures() const {
return m_textures;
}
bool Install(const std::string& path);
bool Uninstall(const std::string& path);
bool operator==(const ResourcePack& pack) const;
bool operator!=(const ResourcePack& pack) const;
private:
bool m_valid = true;
std::string m_path;
std::string m_error;
Manifest m_manifest;
std::vector<std::string> m_textures;
std::vector<char> m_logo_data;
};
} // namespace Common::ResourcePack

View File

@ -0,0 +1,47 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <memory>
#include <span>
#include <type_traits>
namespace Common {
/**
* A ScratchBuffer is a simple heap allocated array without member initialization.
* Main usage is for temporary buffers passed to threads for example
*/
template <typename T>
class ScratchBuffer {
static_assert(std::is_trivial_v<T>, "Must use a POD type");
public:
ScratchBuffer(std::size_t size_) : size{size_} {
buffer = std::unique_ptr<T>(new typename std::remove_extent<T>::type[size]);
}
[[nodiscard]] std::size_t Size() const noexcept {
return size;
}
[[nodiscard]] T* Data() const noexcept {
return buffer.get();
}
[[nodiscard]] std::span<const T> Span(u32 index = 0) const noexcept {
return std::span<const T>{buffer.get() + index, size - index};
}
[[nodiscard]] std::span<T> Span(u32 index = 0) noexcept {
return std::span<T>{buffer.get() + index, size - index};
}
private:
std::unique_ptr<T> buffer;
std::size_t size;
};
} // namespace Common

View File

@ -123,6 +123,13 @@ std::string TabsToSpaces(int tab_size, std::string in) {
return in;
}
void TruncateToCString(std::string* s) {
const size_t terminator = s->find_first_of('\0');
if (terminator != s->npos) {
s->resize(terminator);
}
}
std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest) {
std::size_t pos = 0;

View File

@ -27,6 +27,8 @@ namespace Common {
[[nodiscard]] std::string TabsToSpaces(int tab_size, std::string in);
void TruncateToCString(std::string* s);
void SplitString(const std::string& str, char delim, std::vector<std::string>& output);
// "C:/Windows/winhelp.exe" to "C:/Windows/", "winhelp", ".exe"

View File

@ -36,8 +36,6 @@ add_library(core STATIC
core.h
core_timing.cpp
core_timing.h
custom_tex_cache.cpp
custom_tex_cache.h
dumping/backend.cpp
dumping/backend.h
file_sys/archive_backend.cpp

View File

@ -12,7 +12,6 @@
#include "audio_core/lle/lle.h"
#include "common/arch.h"
#include "common/logging/log.h"
#include "common/texture.h"
#include "core/arm/arm_interface.h"
#include "core/arm/exclusive_monitor.h"
#if CITRA_ARCH(x86_64) || CITRA_ARCH(arm64)
@ -27,7 +26,6 @@
#include "core/dumping/ffmpeg_backend.h"
#endif
#include "common/settings.h"
#include "core/custom_tex_cache.h"
#include "core/gdbstub/gdbstub.h"
#include "core/global.h"
#include "core/hle/kernel/client_port.h"
@ -48,6 +46,7 @@
#include "core/movie.h"
#include "core/rpc/rpc_server.h"
#include "network/network.h"
#include "video_core/rasterizer_cache/custom_tex_manager.h"
#include "video_core/renderer_base.h"
#include "video_core/video_core.h"
@ -317,16 +316,9 @@ System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::st
static_cast<u32>(load_result));
}
perf_stats = std::make_unique<PerfStats>(title_id);
custom_tex_cache = std::make_unique<Core::CustomTexCache>();
if (Settings::values.custom_textures) {
const u64 program_id = Kernel().GetCurrentProcess()->codeset->program_id;
FileUtil::CreateFullPath(fmt::format(
"{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), program_id));
custom_tex_cache->FindCustomTextures(program_id);
}
if (Settings::values.preload_textures) {
custom_tex_cache->PreloadTextures(*GetImageInterface());
custom_tex_manager->FindCustomTextures();
}
status = ResultStatus::Success;
@ -431,7 +423,9 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window,
video_dumper = std::make_unique<VideoDumper::NullBackend>();
#endif
VideoCore::ResultStatus result = VideoCore::Init(emu_window, secondary_window, *memory);
custom_tex_manager = std::make_unique<VideoCore::CustomTexManager>(*this);
VideoCore::ResultStatus result = VideoCore::Init(emu_window, secondary_window, *this);
if (result != VideoCore::ResultStatus::Success) {
switch (result) {
case VideoCore::ResultStatus::ErrorGenericDrivers:
@ -512,12 +506,12 @@ const VideoDumper::Backend& System::VideoDumper() const {
return *video_dumper;
}
Core::CustomTexCache& System::CustomTexCache() {
return *custom_tex_cache;
VideoCore::CustomTexManager& System::CustomTexManager() {
return *custom_tex_manager;
}
const Core::CustomTexCache& System::CustomTexCache() const {
return *custom_tex_cache;
const VideoCore::CustomTexManager& System::CustomTexManager() const {
return *custom_tex_manager;
}
void System::RegisterMiiSelector(std::shared_ptr<Frontend::MiiSelector> mii_selector) {
@ -528,10 +522,6 @@ void System::RegisterSoftwareKeyboard(std::shared_ptr<Frontend::SoftwareKeyboard
registered_swkbd = std::move(swkbd);
}
void System::RegisterImageInterface(std::shared_ptr<Frontend::ImageInterface> image_interface) {
registered_image_interface = std::move(image_interface);
}
void System::Shutdown(bool is_deserializing) {
// Log last frame performance stats
const auto perf_results = GetAndResetPerfStats();

View File

@ -9,10 +9,8 @@
#include <string>
#include <boost/serialization/version.hpp>
#include "common/common_types.h"
#include "core/custom_tex_cache.h"
#include "core/frontend/applets/mii_selector.h"
#include "core/frontend/applets/swkbd.h"
#include "core/frontend/image_interface.h"
#include "core/loader/loader.h"
#include "core/memory.h"
#include "core/perf_stats.h"
@ -58,8 +56,9 @@ class Backend;
}
namespace VideoCore {
class CustomTexManager;
class RendererBase;
}
} // namespace VideoCore
namespace Core {
@ -257,11 +256,11 @@ public:
/// Gets a const reference to the cheat engine
[[nodiscard]] const Cheats::CheatEngine& CheatEngine() const;
/// Gets a reference to the custom texture cache system
[[nodiscard]] Core::CustomTexCache& CustomTexCache();
/// Gets a reference to the custom texture management system
[[nodiscard]] VideoCore::CustomTexManager& CustomTexManager();
/// Gets a const reference to the custom texture cache system
[[nodiscard]] const Core::CustomTexCache& CustomTexCache() const;
/// Gets a const reference to the custom texture management system
[[nodiscard]] const VideoCore::CustomTexManager& CustomTexManager() const;
/// Gets a reference to the video dumper backend
[[nodiscard]] VideoDumper::Backend& VideoDumper();
@ -301,14 +300,6 @@ public:
return registered_swkbd;
}
/// Image interface
void RegisterImageInterface(std::shared_ptr<Frontend::ImageInterface> image_interface);
[[nodiscard]] std::shared_ptr<Frontend::ImageInterface> GetImageInterface() const {
return registered_image_interface;
}
void SaveState(u32 slot) const;
void LoadState(u32 slot);
@ -367,10 +358,7 @@ private:
std::unique_ptr<VideoDumper::Backend> video_dumper;
/// Custom texture cache system
std::unique_ptr<Core::CustomTexCache> custom_tex_cache;
/// Image interface
std::shared_ptr<Frontend::ImageInterface> registered_image_interface;
std::unique_ptr<VideoCore::CustomTexManager> custom_tex_manager;
/// RPC Server for scripting support
std::unique_ptr<RPC::RPCServer> rpc_server;

View File

@ -1,109 +0,0 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include <fmt/format.h>
#include "common/file_util.h"
#include "common/texture.h"
#include "core.h"
#include "core/custom_tex_cache.h"
namespace Core {
CustomTexCache::CustomTexCache() = default;
CustomTexCache::~CustomTexCache() = default;
bool CustomTexCache::IsTextureDumped(u64 hash) const {
return dumped_textures.count(hash);
}
void CustomTexCache::SetTextureDumped(const u64 hash) {
dumped_textures.insert(hash);
}
bool CustomTexCache::IsTextureCached(u64 hash) const {
return custom_textures.count(hash);
}
const CustomTexInfo& CustomTexCache::LookupTexture(u64 hash) const {
return custom_textures.at(hash);
}
void CustomTexCache::CacheTexture(u64 hash, const std::vector<u8>& tex, u32 width, u32 height) {
custom_textures[hash] = {width, height, tex};
}
void CustomTexCache::AddTexturePath(u64 hash, const std::string& path) {
if (custom_texture_paths.count(hash))
LOG_ERROR(Core, "Textures {} and {} conflict!", custom_texture_paths[hash].path, path);
else
custom_texture_paths[hash] = {path, hash};
}
void CustomTexCache::FindCustomTextures(u64 program_id) {
// Custom textures are currently stored as
// [TitleID]/tex1_[width]x[height]_[64-bit hash]_[format].png
const std::string load_path = fmt::format(
"{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), program_id);
if (FileUtil::Exists(load_path)) {
FileUtil::FSTEntry texture_dir;
std::vector<FileUtil::FSTEntry> textures;
// 64 nested folders should be plenty for most cases
FileUtil::ScanDirectoryTree(load_path, texture_dir, 64);
FileUtil::GetAllFilesFromNestedEntries(texture_dir, textures);
for (const auto& file : textures) {
if (file.isDirectory)
continue;
if (file.virtualName.substr(0, 5) != "tex1_")
continue;
u32 width;
u32 height;
u64 hash;
u32 format; // unused
// TODO: more modern way of doing this
if (std::sscanf(file.virtualName.c_str(), "tex1_%ux%u_%llX_%u.png", &width, &height,
&hash, &format) == 4) {
AddTexturePath(hash, file.physicalName);
}
}
}
}
void CustomTexCache::PreloadTextures(Frontend::ImageInterface& image_interface) {
for (const auto& path : custom_texture_paths) {
const auto& path_info = path.second;
Core::CustomTexInfo tex_info;
if (image_interface.DecodePNG(tex_info.tex, tex_info.width, tex_info.height,
path_info.path)) {
// Make sure the texture size is a power of 2
std::bitset<32> width_bits(tex_info.width);
std::bitset<32> height_bits(tex_info.height);
if (width_bits.count() == 1 && height_bits.count() == 1) {
LOG_DEBUG(Render_OpenGL, "Loaded custom texture from {}", path_info.path);
Common::FlipRGBA8Texture(tex_info.tex, tex_info.width, tex_info.height);
CacheTexture(path_info.hash, tex_info.tex, tex_info.width, tex_info.height);
} else {
LOG_ERROR(Render_OpenGL, "Texture {} size is not a power of 2", path_info.path);
}
} else {
LOG_ERROR(Render_OpenGL, "Failed to load custom texture {}", path_info.path);
}
}
}
bool CustomTexCache::CustomTextureExists(u64 hash) const {
return custom_texture_paths.count(hash);
}
const CustomTexPathInfo& CustomTexCache::LookupTexturePathInfo(u64 hash) const {
return custom_texture_paths.at(hash);
}
bool CustomTexCache::IsTexturePathMapEmpty() const {
return custom_texture_paths.size() == 0;
}
} // namespace Core

View File

@ -1,55 +0,0 @@
// Copyright 2019 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include "common/common_types.h"
namespace Frontend {
class ImageInterface;
} // namespace Frontend
namespace Core {
struct CustomTexInfo {
u32 width;
u32 height;
std::vector<u8> tex;
};
// This is to avoid parsing the filename multiple times
struct CustomTexPathInfo {
std::string path;
u64 hash;
};
// TODO: think of a better name for this class...
class CustomTexCache {
public:
explicit CustomTexCache();
~CustomTexCache();
bool IsTextureDumped(u64 hash) const;
void SetTextureDumped(u64 hash);
bool IsTextureCached(u64 hash) const;
const CustomTexInfo& LookupTexture(u64 hash) const;
void CacheTexture(u64 hash, const std::vector<u8>& tex, u32 width, u32 height);
void AddTexturePath(u64 hash, const std::string& path);
void FindCustomTextures(u64 program_id);
void PreloadTextures(Frontend::ImageInterface& image_interface);
bool CustomTextureExists(u64 hash) const;
const CustomTexPathInfo& LookupTexturePathInfo(u64 hash) const;
bool IsTexturePathMapEmpty() const;
private:
std::unordered_set<u64> dumped_textures;
std::unordered_map<u64, CustomTexInfo> custom_textures;
std::unordered_map<u64, CustomTexPathInfo> custom_texture_paths;
};
} // namespace Core

View File

@ -28,13 +28,20 @@ add_library(video_core STATIC
regs_texturing.h
renderer_base.cpp
renderer_base.h
rasterizer_cache/texture_codec.h
rasterizer_cache/custom_tex_manager.cpp
rasterizer_cache/custom_tex_manager.h
rasterizer_cache/framebuffer_base.cpp
rasterizer_cache/framebuffer_base.h
rasterizer_cache/pixel_format.cpp
rasterizer_cache/pixel_format.h
rasterizer_cache/rasterizer_cache.cpp
rasterizer_cache/rasterizer_cache.h
rasterizer_cache/rasterizer_cache_base.h
rasterizer_cache/sampler_params.h
rasterizer_cache/slot_vector.h
rasterizer_cache/surface_base.cpp
rasterizer_cache/surface_base.h
rasterizer_cache/texture_codec.h
rasterizer_cache/utils.cpp
rasterizer_cache/utils.h
rasterizer_cache/surface_params.cpp

View File

@ -0,0 +1,251 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/bit_util.h"
#include "common/file_util.h"
#include "common/hash.h"
#include "common/image_util.h"
#include "common/scratch_buffer.h"
#include "core/core.h"
#include "video_core/rasterizer_cache/custom_tex_manager.h"
#include "video_core/rasterizer_cache/surface_params.h"
namespace VideoCore {
namespace {
using namespace Common;
CustomFileFormat MakeFileFormat(std::string_view ext) {
if (ext == "png") {
return CustomFileFormat::PNG;
} else if (ext == "dds") {
return CustomFileFormat::DDS;
} else if (ext == "ktx") {
return CustomFileFormat::KTX;
}
LOG_ERROR(Render, "Unknown file extension {}", ext);
return CustomFileFormat::PNG;
}
CustomPixelFormat ToCustomPixelFormat(ddsktx_format format) {
switch (format) {
case DDSKTX_FORMAT_RGBA8:
return CustomPixelFormat::RGBA8;
case DDSKTX_FORMAT_BC1:
return CustomPixelFormat::BC1;
case DDSKTX_FORMAT_BC3:
return CustomPixelFormat::BC3;
case DDSKTX_FORMAT_BC5:
return CustomPixelFormat::BC5;
case DDSKTX_FORMAT_BC7:
return CustomPixelFormat::BC7;
case DDSKTX_FORMAT_ASTC4x4:
return CustomPixelFormat::ASTC;
default:
LOG_ERROR(Common, "Unknown dds/ktx pixel format {}", format);
return CustomPixelFormat::RGBA8;
}
}
} // Anonymous namespace
CustomTexManager::CustomTexManager(Core::System& system_)
: system{system_}, workers{std::max(std::thread::hardware_concurrency(), 2U) - 1,
"Hires processing"} {}
CustomTexManager::~CustomTexManager() = default;
void CustomTexManager::FindCustomTextures() {
if (textures_loaded) {
return;
}
// Custom textures are currently stored as
// [TitleID]/tex1_[width]x[height]_[64-bit hash]_[format].png
using namespace FileUtil;
const u64 program_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
const std::string load_path =
fmt::format("{}textures/{:016X}/", GetUserPath(UserPath::LoadDir), program_id);
// Create the directory if it did not exist
if (!Exists(load_path)) {
CreateFullPath(load_path);
}
FSTEntry texture_dir;
std::vector<FSTEntry> textures;
// 64 nested folders should be plenty for most cases
ScanDirectoryTree(load_path, texture_dir, 64);
GetAllFilesFromNestedEntries(texture_dir, textures);
u32 width{};
u32 height{};
u64 hash{};
u32 format{};
std::string ext(3, ' ');
for (const FSTEntry& file : textures) {
const std::string& path = file.physicalName;
if (file.isDirectory || !file.virtualName.starts_with("tex1_")) {
continue;
}
// Parse the texture filename. We only really care about the hash,
// the rest should be queried from the file itself.
if (std::sscanf(file.virtualName.c_str(), "tex1_%ux%u_%lX_%u.%s", &width, &height, &hash,
&format, ext.data()) != 5) {
continue;
}
auto [it, new_texture] = custom_textures.try_emplace(hash);
if (!new_texture) {
LOG_ERROR(Render, "Textures {} and {} conflict, ignoring!", custom_textures[hash].path,
path);
continue;
}
auto& texture = it->second;
texture.file_format = MakeFileFormat(ext);
texture.path = path;
// Query the required information from the file and load it.
// Since this doesn't involve any decoding it shouldn't consume too much RAM.
LoadTexture(texture);
}
textures_loaded = true;
}
void CustomTexManager::DumpTexture(const SurfaceParams& params, std::span<const u8> data) {
const u64 data_hash = ComputeHash64(data.data(), data.size());
const u32 data_size = static_cast<u32>(data.size());
const u32 width = params.width;
const u32 height = params.height;
const PixelFormat format = params.pixel_format;
// Check if it's been dumped already
if (dumped_textures.contains(data_hash)) {
return;
}
// Make sure the texture size is a power of 2.
// If not, the surface is probably a framebuffer
if (!IsPow2(width) || !IsPow2(height)) {
LOG_WARNING(Render, "Not dumping {:016X} because size isn't a power of 2 ({}x{})",
data_hash, width, height);
return;
}
// Allocate a temporary buffer for the thread to use
const u32 decoded_size = width * height * 4;
ScratchBuffer<u8> pixels(data_size + decoded_size);
std::memcpy(pixels.Data(), data.data(), data_size);
// Proceed with the dump.
const u64 program_id = system.Kernel().GetCurrentProcess()->codeset->program_id;
auto dump = [width, height, params, data_hash, format, data_size, program_id,
pixels = std::move(pixels)]() mutable {
// Decode and convert to RGBA8
const std::span encoded = pixels.Span().first(data_size);
const std::span decoded = pixels.Span(data_size);
DecodeTexture(params, params.addr, params.end, encoded, decoded,
params.type == SurfaceType::Color);
std::string dump_path = fmt::format(
"{}textures/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), program_id);
if (!FileUtil::CreateFullPath(dump_path)) {
LOG_ERROR(Render, "Unable to create {}", dump_path);
return;
}
dump_path += fmt::format("tex1_{}x{}_{:016X}_{}.png", width, height, data_hash, format);
EncodePNG(dump_path, decoded, width, height);
};
workers.QueueWork(std::move(dump));
dumped_textures.insert(data_hash);
}
const Texture& CustomTexManager::GetTexture(const SurfaceParams& params, std::span<u8> data) {
u64 data_hash;
if (compatibility_mode) {
const u32 decoded_size =
params.width * params.height * GetBytesPerPixel(params.pixel_format);
ScratchBuffer<u8> decoded(decoded_size);
DecodeTexture(params, params.addr, params.end, data, decoded.Span());
data_hash = ComputeHash64(decoded.Data(), decoded_size);
} else {
data_hash = ComputeHash64(data.data(), data.size());
}
auto it = custom_textures.find(data_hash);
if (it == custom_textures.end()) {
LOG_WARNING(
Render, "Unable to find replacement for {}x{} {} surface upload with hash {:016X}",
params.width, params.height, PixelFormatAsString(params.pixel_format), data_hash);
return dummy_texture;
}
LOG_DEBUG(Render, "Assigning {} to {}x{} {} surface with address {:#x} and hash {:016X}",
it->second.path, params.width, params.height,
PixelFormatAsString(params.pixel_format), params.addr, data_hash);
return it->second;
}
void CustomTexManager::DecodeToStaging(const Texture& texture, const StagingData& staging) {
switch (texture.file_format) {
case CustomFileFormat::PNG:
if (!DecodePNG(texture.data, staging.mapped)) {
LOG_ERROR(Render, "Failed to decode png {}", texture.path);
}
if (compatibility_mode) {
const u32 stride = texture.width * 4;
// FlipTexture(staging.mapped, texture.width, texture.height, stride);
}
break;
case CustomFileFormat::DDS:
case CustomFileFormat::KTX:
// Compressed formats don't need CPU decoding
std::memcpy(staging.mapped.data(), texture.data.data(), texture.data.size());
break;
}
}
void CustomTexManager::LoadTexture(Texture& texture) {
std::vector<u8>& data = texture.data;
// Read the file
auto file = FileUtil::IOFile(texture.path, "rb");
data.resize(file.GetSize());
file.ReadBytes(data.data(), file.GetSize());
// Parse it based on the file extension
switch (texture.file_format) {
case CustomFileFormat::PNG:
texture.format = CustomPixelFormat::RGBA8; // Check for other formats too?
if (!ParsePNG(data, texture.staging_size, texture.width, texture.height)) {
LOG_ERROR(Render, "Failed to parse png file {}", texture.path);
return;
}
break;
case CustomFileFormat::DDS:
case CustomFileFormat::KTX:
ddsktx_format format{};
if (!ParseDDSKTX(data, texture.data, texture.width, texture.height, format)) {
LOG_ERROR(Render, "Failed to parse dds/ktx file {}", texture.path);
return;
}
texture.staging_size = texture.data.size();
texture.format = ToCustomPixelFormat(format);
break;
}
ASSERT_MSG(texture.width != 0 && texture.height != 0 && texture.staging_size != 0,
"Invalid parameters read from {}", texture.path);
}
} // namespace VideoCore

View File

@ -0,0 +1,79 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#pragma once
#include <span>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include "common/thread_worker.h"
#include "video_core/rasterizer_cache/pixel_format.h"
namespace Core {
class System;
}
namespace VideoCore {
struct StagingData;
class SurfaceParams;
enum class PixelFormat : u32;
enum class CustomFileFormat : u32 {
PNG = 0,
DDS = 1,
KTX = 2,
};
struct Texture {
u32 width;
u32 height;
CustomPixelFormat format;
CustomFileFormat file_format;
std::string path;
std::size_t staging_size;
std::vector<u8> data;
operator bool() const noexcept {
return !data.empty();
}
};
class CustomTexManager {
public:
CustomTexManager(Core::System& system);
~CustomTexManager();
/// Searches the load directory assigned to program_id for any custom textures and loads them
void FindCustomTextures();
/// Saves the provided pixel data described by params to disk as png
void DumpTexture(const SurfaceParams& params, std::span<const u8> data);
/// Returns the custom texture handle assigned to the provided data hash
const Texture& GetTexture(const SurfaceParams& params, std::span<u8> data);
/// Decodes the data in texture to a consumable format
void DecodeToStaging(const Texture& texture, const StagingData& staging);
bool CompatibilityMode() const noexcept {
return compatibility_mode;
}
private:
/// Fills the texture structure with information from the file in path
void LoadTexture(Texture& texture);
private:
Core::System& system;
Common::ThreadWorker workers;
std::unordered_set<u64> dumped_textures;
std::unordered_map<u64, Texture> custom_textures;
Texture dummy_texture{};
bool textures_loaded{};
bool compatibility_mode{true};
};
} // namespace VideoCore

View File

@ -0,0 +1,64 @@
// Copyright 2023 Citra Emulator Project
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "video_core/rasterizer_cache/framebuffer_base.h"
#include "video_core/rasterizer_cache/surface_base.h"
#include "video_core/regs.h"
namespace VideoCore {
FramebufferBase::FramebufferBase() = default;
FramebufferBase::FramebufferBase(const Pica::Regs& regs, SurfaceBase* const color_,
SurfaceBase* const depth_stencil_,
Common::Rectangle<u32> surfaces_rect)
: color{color_}, depth_stencil{depth_stencil_} {
res_scale = color ? color->res_scale : (depth_stencil ? depth_stencil->res_scale : 1u);
// Determine the draw rectangle (render area + scissor)
const Common::Rectangle viewport_rect = regs.rasterizer.GetViewportRect();
draw_rect.left =
std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.left * res_scale,
surfaces_rect.left, surfaces_rect.right);
draw_rect.top =
std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.top * res_scale,
surfaces_rect.bottom, surfaces_rect.top);
draw_rect.right =
std::clamp<s32>(static_cast<s32>(surfaces_rect.left) + viewport_rect.right * res_scale,
surfaces_rect.left, surfaces_rect.right);
draw_rect.bottom =
std::clamp<s32>(static_cast<s32>(surfaces_rect.bottom) + viewport_rect.bottom * res_scale,
surfaces_rect.bottom, surfaces_rect.top);
// Update viewport
viewport.x = surfaces_rect.left + viewport_rect.left * res_scale;
viewport.y = surfaces_rect.bottom + viewport_rect.bottom * res_scale;
viewport.width = viewport_rect.GetWidth() * res_scale;
viewport.height = viewport_rect.GetHeight() * res_scale;
// Scissor checks are window-, not viewport-relative, which means that if the cached texture
// sub-rect changes, the scissor bounds also need to be updated.
scissor_rect.left =
static_cast<s32>(surfaces_rect.left + regs.rasterizer.scissor_test.x1 * res_scale);
scissor_rect.bottom =
static_cast<s32>(surfaces_rect.bottom + regs.rasterizer.scissor_test.y1 * res_scale);
// x2, y2 have +1 added to cover the entire pixel area, otherwise you might get cracks when
// scaling or doing multisampling.
scissor_rect.right =
static_cast<s32>(surfaces_rect.left + (regs.rasterizer.scissor_test.x2 + 1) * res_scale);
scissor_rect.top =
static_cast<s32>(surfaces_rect.bottom + (regs.rasterizer.scissor_test.y2 + 1) * res_scale);
// Query surface invalidation intervals
const Common::Rectangle draw_rect_unscaled{draw_rect / res_scale};
if (color) {
intervals[0] = color->GetSubRectInterval(draw_rect_unscaled);
}
if (depth_stencil) {
intervals[1] = depth_stencil->GetSubRectInterval(draw_rect_unscaled);
}
}
} // namespace VideoCore

Some files were not shown because too many files have changed in this diff Show More