| 1162 | }; |
| 1163 | |
| 1164 | static cc_result Zip_ReadLocalFileHeader(struct ZipState* state, struct ZipEntry* entry) { |
| 1165 | struct Stream* stream = state->source; |
| 1166 | cc_uint8 header[26]; |
| 1167 | cc_string path; char pathBuffer[ZIP_MAXNAMELEN]; |
| 1168 | cc_uint32 compressedSize, uncompressedSize; |
| 1169 | int method, pathLen, extraLen; |
| 1170 | struct Stream portion, compStream; |
| 1171 | #if CC_BUILD_MAXSTACK <= (64 * 1024) |
| 1172 | struct InflateState* inflate; |
| 1173 | #else |
| 1174 | struct InflateState inflate; |
| 1175 | #endif |
| 1176 | cc_result res; |
| 1177 | |
| 1178 | if ((res = Stream_Read(stream, header, sizeof(header)))) return res; |
| 1179 | pathLen = Stream_GetU16_LE(&header[22]); |
| 1180 | if (pathLen > ZIP_MAXNAMELEN) return ZIP_ERR_FILENAME_LEN; |
| 1181 | |
| 1182 | /* NOTE: ZIP spec says path uses code page 437 for encoding */ |
| 1183 | path = String_Init(pathBuffer, pathLen, pathLen); |
| 1184 | if ((res = Stream_Read(stream, (cc_uint8*)pathBuffer, pathLen))) return res; |
| 1185 | if (!state->SelectEntry(&path)) return 0; |
| 1186 | |
| 1187 | extraLen = Stream_GetU16_LE(&header[24]); |
| 1188 | /* local file may have extra data before actual data (e.g. ZIP64) */ |
| 1189 | if ((res = stream->Skip(stream, extraLen))) return res; |
| 1190 | |
| 1191 | method = Stream_GetU16_LE(&header[4]); |
| 1192 | compressedSize = Stream_GetU32_LE(&header[14]); |
| 1193 | uncompressedSize = Stream_GetU32_LE(&header[18]); |
| 1194 | |
| 1195 | /* Some .zip files don't set these in local file header */ |
| 1196 | if (!compressedSize) compressedSize = entry->CompressedSize; |
| 1197 | if (!uncompressedSize) uncompressedSize = entry->UncompressedSize; |
| 1198 | |
| 1199 | if (method == 0) { |
| 1200 | Stream_ReadonlyPortion(&portion, stream, uncompressedSize); |
| 1201 | res = state->ProcessEntry(&path, &portion, entry); |
| 1202 | } else if (method == 8) { |
| 1203 | Stream_ReadonlyPortion(&portion, stream, compressedSize); |
| 1204 | |
| 1205 | #if CC_BUILD_MAXSTACK <= (64 * 1024) |
| 1206 | inflate = (struct InflateState*)Mem_TryAlloc(1, sizeof(struct InflateState)); |
| 1207 | if (!inflate) return ERR_OUT_OF_MEMORY; |
| 1208 | |
| 1209 | Inflate_MakeStream2(&compStream, inflate, &portion); |
| 1210 | res = state->ProcessEntry(&path, &compStream, entry); |
| 1211 | Mem_Free(inflate); |
| 1212 | #else |
| 1213 | Inflate_MakeStream2(&compStream, &inflate, &portion); |
| 1214 | res = state->ProcessEntry(&path, &compStream, entry); |
| 1215 | #endif |
| 1216 | } else { |
| 1217 | Platform_Log1("Unsupported.zip entry compression method: %i", &method); |
| 1218 | /* TODO: Should this be an error */ |
| 1219 | res = 0; |
| 1220 | } |
| 1221 | return res; |
no test coverage detected