/* * Transfer the contents of the text into a blob * The caller must free the returned blob if b is NULL */ blob * textToBlob(text *t, blob *b, int destroy) { size_t s; blob *bin; if(t == NULL) return NULL; s = 0; (void)textIterate(t, getLength, &s, 0); if(s == 0) return b; /* * copy b. If b is NULL and an error occurs we know we need to free * before returning */ bin = b; if(b == NULL) { b = blobCreate(); if(b == NULL) return NULL; } if(blobGrow(b, s) != CL_SUCCESS) { cli_warnmsg("Couldn't grow the blob: we may be low on memory\n"); #if 0 if(!destroy) { if(bin == NULL) blobDestroy(b); return NULL; } /* * We may be able to recover enough memory as we destroy to * create the blob */ #else if(bin == NULL) blobDestroy(b); return NULL; #endif } (void)textIterate(t, addToBlob, b, destroy); if(destroy && t->t_next) { textDestroy(t->t_next); t->t_next = NULL; } blobClose(b); return b; }
void blobArrayDestroy(blob *blobList[], int n) { assert(blobList != NULL); while(--n >= 0) { cli_dbgmsg("blobArrayDestroy: %d\n", n); if(blobList[n]) { blobDestroy(blobList[n]); blobList[n] = NULL; } } }
unsigned char * cli_vba_inflate(int fd, off_t offset, int *size) { unsigned int pos, shift, mask, distance, clean; uint8_t flag; uint16_t token; blob *b; unsigned char buffer[VBA_COMPRESSION_WINDOW]; if(fd < 0) return NULL; b = blobCreate(); if(b == NULL) return NULL; lseek(fd, offset+3, SEEK_SET); /* 1byte ?? , 2byte length ?? */ clean = TRUE; pos = 0; while (cli_readn(fd, &flag, 1) == 1) { for(mask = 1; mask < 0x100; mask<<=1) { unsigned int winpos = pos % VBA_COMPRESSION_WINDOW; if (flag & mask) { uint16_t len; unsigned int srcpos; if(!read_uint16(fd, &token, FALSE)) { blobDestroy(b); if(size) *size = 0; return NULL; } shift = 12 - (winpos > 0x10) - (winpos > 0x20) - (winpos > 0x40) - (winpos > 0x80) - (winpos > 0x100) - (winpos > 0x200) - (winpos > 0x400) - (winpos > 0x800); len = (uint16_t)((token & ((1 << shift) - 1)) + 3); distance = token >> shift; srcpos = pos - distance - 1; if((((srcpos + len) % VBA_COMPRESSION_WINDOW) < winpos) && ((winpos + len) < VBA_COMPRESSION_WINDOW) && (((srcpos % VBA_COMPRESSION_WINDOW) + len) < VBA_COMPRESSION_WINDOW) && (len <= VBA_COMPRESSION_WINDOW)) { srcpos %= VBA_COMPRESSION_WINDOW; memcpy(&buffer[winpos], &buffer[srcpos], len); pos += len; } else while(len-- > 0) { srcpos = (pos - distance - 1) % VBA_COMPRESSION_WINDOW; buffer[pos++ % VBA_COMPRESSION_WINDOW] = buffer[srcpos]; } } else { if((pos != 0) && (winpos == 0) && clean) { if (cli_readn(fd, &token, 2) != 2) { blobDestroy(b); if(size) *size = 0; return NULL; } (void)blobAddData(b, buffer, VBA_COMPRESSION_WINDOW); clean = FALSE; break; } if(cli_readn(fd, &buffer[winpos], 1) == 1) pos++; } clean = TRUE; }