📄 explode.cpp
字号:
mpq_pkzip->extra_bits = (mpq_pkzip->extra_bits - bits) + 8; return 0;}/* * Decompress the imploded data using coded literals. * Returns: 0x000 - 0x0FF : One byte from compressed file. * 0x100 - 0x305 : Copy previous block (0x100 = 1 byte) * 0x306 : Out of buffer (?) */static unsigned long libmpq_pkzip_explode_lit(pkzip_data_cmp *mpq_pkzip) { unsigned long bits; /* Number of bits to skip */ unsigned long value; /* Position in buffers */ /* Test the current bit in byte buffer. If is not set, simply return the next byte. */ if (mpq_pkzip->bit_buf & 1) { /* Skip current bit in the buffer. */ if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) { return 0x306; } /* The next bits are position in buffers. */ value = mpq_pkzip->pos2[(mpq_pkzip->bit_buf & 0xFF)]; /* Get number of bits to skip */ if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->slen_bits[value])) { return 0x306; } if ((bits = mpq_pkzip->clen_bits[value]) != 0) { unsigned long val2 = mpq_pkzip->bit_buf & ((1 << bits) - 1); if (libmpq_pkzip_skip_bits(mpq_pkzip, bits)) { if ((value + val2) != 0x10E) { return 0x306; } } value = mpq_pkzip->len_base[value] + val2; } return value + 0x100; /* Return number of bytes to repeat */ } /* Skip one bit */ if (libmpq_pkzip_skip_bits(mpq_pkzip, 1)) { return 0x306; } /* If the binary compression type, read 8 bits and return them as one byte. */ if (mpq_pkzip->cmp_type == LIBMPQ_PKZIP_CMP_BINARY) { value = mpq_pkzip->bit_buf & 0xFF; if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) { return 0x306; } return value; } /* When ASCII compression ... */ if (mpq_pkzip->bit_buf & 0xFF) { value = mpq_pkzip->offs_2c34[mpq_pkzip->bit_buf & 0xFF]; if (value == 0xFF) { if (mpq_pkzip->bit_buf & 0x3F) { if (libmpq_pkzip_skip_bits(mpq_pkzip, 4)) { return 0x306; } value = mpq_pkzip->offs_2d34[mpq_pkzip->bit_buf & 0xFF]; } else { if (libmpq_pkzip_skip_bits(mpq_pkzip, 6)) { return 0x306; } value = mpq_pkzip->offs_2e34[mpq_pkzip->bit_buf & 0x7F]; } } } else { if (libmpq_pkzip_skip_bits(mpq_pkzip, 8)) { return 0x306; } value = mpq_pkzip->offs_2eb4[mpq_pkzip->bit_buf & 0xFF]; } return libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->bits_asc[value]) ? 0x306 : value;}/* * Retrieves the number of bytes to move back. */static unsigned long libmpq_pkzip_explode_dist(pkzip_data_cmp *mpq_pkzip, unsigned long length) { unsigned long pos = mpq_pkzip->pos1[(mpq_pkzip->bit_buf & 0xFF)]; unsigned long skip = mpq_pkzip->dist_bits[pos]; /* Number of bits to skip */ /* Skip the appropriate number of bits */ if (libmpq_pkzip_skip_bits(mpq_pkzip, skip) == 1) { return 0; } if (length == 2) { pos = (pos << 2) | (mpq_pkzip->bit_buf & 0x03); if (libmpq_pkzip_skip_bits(mpq_pkzip, 2) == 1) { return 0; } } else { pos = (pos << mpq_pkzip->dsize_bits) | (mpq_pkzip->bit_buf & mpq_pkzip->dsize_mask); /* Skip the bits */ if (libmpq_pkzip_skip_bits(mpq_pkzip, mpq_pkzip->dsize_bits) == 1) { return 0; } } return pos + 1;}static unsigned long libmpq_pkzip_expand(pkzip_data_cmp *mpq_pkzip) { unsigned int copy_bytes; /* Number of bytes to copy */ unsigned long one_byte; /* One byte from compressed file */ unsigned long result; mpq_pkzip->out_pos = 0x1000; /* Initialize output buffer position */ /* If end of data or error, terminate decompress */ while ((result = one_byte = libmpq_pkzip_explode_lit(mpq_pkzip)) < 0x305) { /* If one byte is greater than 0x100, means "Repeat n - 0xFE bytes" */ if (one_byte >= 0x100) { unsigned char *source; /* ECX */ unsigned char *target; /* EDX */ unsigned long copy_length = one_byte - 0xFE; unsigned long move_back; /* Get length of data to copy */ if ((move_back = libmpq_pkzip_explode_dist(mpq_pkzip, copy_length)) == 0) { result = 0x306; break; } /* Target and source pointer */ target = &mpq_pkzip->out_buf[mpq_pkzip->out_pos]; source = target - move_back; mpq_pkzip->out_pos += copy_length; while (copy_length-- > 0) { *target++ = *source++; } } else { mpq_pkzip->out_buf[mpq_pkzip->out_pos++] = (unsigned char)one_byte; } /* * If number of extracted bytes has reached 1/2 of output buffer, * flush output buffer. */ if (mpq_pkzip->out_pos >= 0x2000) { /* Copy decompressed data into user buffer. */ copy_bytes = 0x1000; mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], ©_bytes, mpq_pkzip->param); /* If there are some data left, keep them alive */ memcpy(mpq_pkzip->out_buf, &mpq_pkzip->out_buf[0x1000], mpq_pkzip->out_pos - 0x1000); mpq_pkzip->out_pos -= 0x1000; } } copy_bytes = mpq_pkzip->out_pos - 0x1000; mpq_pkzip->write_buf((char *)&mpq_pkzip->out_buf[0x1000], ©_bytes, mpq_pkzip->param); return result;}/* * Main exploding function. */unsigned int libmpq_pkzip_explode( unsigned int (*read_buf)(char *buf, unsigned int *size, void *param), void (*write_buf)(char *buf, unsigned int *size, void *param), char *work_buf, void *param) { pkzip_data_cmp *mpq_pkzip = (pkzip_data_cmp *)work_buf; /* Set the whole work buffer to zeros */ memset(mpq_pkzip, 0, sizeof(pkzip_data_cmp)); /* Initialize work struct and load compressed data */ mpq_pkzip->read_buf = read_buf; mpq_pkzip->write_buf = write_buf; mpq_pkzip->param = param; mpq_pkzip->in_pos = sizeof(mpq_pkzip->in_buf); mpq_pkzip->in_bytes = mpq_pkzip->read_buf((char *)mpq_pkzip->in_buf, &mpq_pkzip->in_pos, mpq_pkzip->param); if (mpq_pkzip->in_bytes <= 4) { return LIBMPQ_PKZIP_CMP_BAD_DATA; } mpq_pkzip->cmp_type = mpq_pkzip->in_buf[0]; /* Get the compression type */ mpq_pkzip->dsize_bits = mpq_pkzip->in_buf[1]; /* Get the dictionary size */ mpq_pkzip->bit_buf = mpq_pkzip->in_buf[2]; /* Initialize 16-bit bit buffer */ mpq_pkzip->extra_bits = 0; /* Extra (over 8) bits */ mpq_pkzip->in_pos = 3; /* Position in input buffer */ /* Test for the valid dictionary size */ if (4 > mpq_pkzip->dsize_bits || mpq_pkzip->dsize_bits > 6) { return LIBMPQ_PKZIP_CMP_INV_DICTSIZE; } mpq_pkzip->dsize_mask = 0xFFFF >> (0x10 - mpq_pkzip->dsize_bits); /* Shifted by 'sar' instruction */ if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_BINARY) { if (mpq_pkzip->cmp_type != LIBMPQ_PKZIP_CMP_ASCII) { return LIBMPQ_PKZIP_CMP_INV_MODE; } memcpy(mpq_pkzip->bits_asc, pkzip_bits_asc, sizeof(mpq_pkzip->bits_asc)); libmpq_pkzip_gen_asc_tabs(mpq_pkzip); } memcpy(mpq_pkzip->slen_bits, pkzip_slen_bits, sizeof(mpq_pkzip->slen_bits)); libmpq_pkzip_gen_decode_tabs(0x10, mpq_pkzip->slen_bits, pkzip_len_code, mpq_pkzip->pos2); memcpy(mpq_pkzip->clen_bits, pkzip_clen_bits, sizeof(mpq_pkzip->clen_bits)); memcpy(mpq_pkzip->len_base, pkzip_len_base, sizeof(mpq_pkzip->len_base)); memcpy(mpq_pkzip->dist_bits, pkzip_dist_bits, sizeof(mpq_pkzip->dist_bits)); libmpq_pkzip_gen_decode_tabs(0x40, mpq_pkzip->dist_bits, pkzip_dist_code, mpq_pkzip->pos1); if (libmpq_pkzip_expand(mpq_pkzip) != 0x306) { return LIBMPQ_PKZIP_CMP_NO_ERROR; } return LIBMPQ_PKZIP_CMP_ABORT;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -