| 72 | }; |
| 73 | |
| 74 | static bool findzipdirectory(stream *f, zipdirectoryheader &hdr) |
| 75 | { |
| 76 | if(!f->seek(0, SEEK_END)) return false; |
| 77 | |
| 78 | uchar buf[1024], *src = NULL; |
| 79 | int len = 0, offset = f->tell(), end = max(offset - 0xFFFF - ZIP_DIRECTORY_SIZE, 0); |
| 80 | const uint signature = lilswap<uint>(ZIP_DIRECTORY_SIGNATURE); |
| 81 | |
| 82 | while(offset > end) |
| 83 | { |
| 84 | int carry = min(len, ZIP_DIRECTORY_SIZE-1), next = min((int)sizeof(buf) - carry, offset - end); |
| 85 | offset -= next; |
| 86 | memmove(&buf[next], buf, carry); |
| 87 | if(next + carry < ZIP_DIRECTORY_SIZE || !f->seek(offset, SEEK_SET) || (int)f->read(buf, next) != next) return false; |
| 88 | len = next + carry; |
| 89 | uchar *search = &buf[next-1]; |
| 90 | for(; search >= buf; search--) if(*(uint *)search == signature) break; |
| 91 | if(search >= buf) { src = search; break; } |
| 92 | } |
| 93 | |
| 94 | if(!src || &buf[len] - src < ZIP_DIRECTORY_SIZE) return false; |
| 95 | |
| 96 | hdr.signature = lilswap(*(uint *)src); src += 4; |
| 97 | hdr.disknumber = lilswap(*(ushort *)src); src += 2; |
| 98 | hdr.directorydisk = lilswap(*(ushort *)src); src += 2; |
| 99 | hdr.diskentries = lilswap(*(ushort *)src); src += 2; |
| 100 | hdr.entries = lilswap(*(ushort *)src); src += 2; |
| 101 | hdr.size = lilswap(*(uint *)src); src += 4; |
| 102 | hdr.offset = lilswap(*(uint *)src); src += 4; |
| 103 | hdr.commentlength = lilswap(*(ushort *)src); src += 2; |
| 104 | |
| 105 | if(hdr.signature != ZIP_DIRECTORY_SIGNATURE || hdr.disknumber != hdr.directorydisk || hdr.diskentries != hdr.entries) return false; |
| 106 | |
| 107 | return true; |
| 108 | } |
| 109 | |
| 110 | #ifndef STANDALONE |
| 111 | VAR(dbgzip, 0, 0, 1); |