Diffstat (limited to 'noncore/apps/opie-reader/chm_lib.c') (more/less context) (show whitespace changes)
-rw-r--r-- | noncore/apps/opie-reader/chm_lib.c | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/noncore/apps/opie-reader/chm_lib.c b/noncore/apps/opie-reader/chm_lib.c index ecf8278..7acd1d2 100644 --- a/noncore/apps/opie-reader/chm_lib.c +++ b/noncore/apps/opie-reader/chm_lib.c @@ -1411,455 +1411,456 @@ static Int64 _chm_decompress_region(struct chmFile *h, h->lzx_state = LZXinit(window_size); } /* decompress some data */ gotLen = _chm_decompress_block(h, nBlock, &ubuffer); if (gotLen < nLen) nLen = gotLen; memcpy(buf, ubuffer+nOffset, (unsigned int)nLen); CHM_RELEASE_LOCK(h->lzx_mutex); return nLen; } /* retrieve (part of) an object */ LONGINT64 chm_retrieve_object(struct chmFile *h, struct chmUnitInfo *ui, unsigned char *buf, LONGUINT64 addr, LONGINT64 len) { /* must be valid file handle */ if (h == NULL) return (Int64)0; /* starting address must be in correct range */ if (addr < 0 || addr >= ui->length) return (Int64)0; /* clip length */ if (addr + len > ui->length) len = ui->length - addr; /* if the file is uncompressed, it's simple */ if (ui->space == CHM_UNCOMPRESSED) { /* read data */ return _chm_fetch_bytes(h, buf, (UInt64)h->data_offset + (UInt64)ui->start + (UInt64)addr, len); } /* else if the file is compressed, it's a little trickier */ else /* ui->space == CHM_COMPRESSED */ { Int64 swath=0, total=0; do { /* swill another mouthful */ swath = _chm_decompress_region(h, buf, ui->start + addr, len); /* if we didn't get any... */ if (swath == 0) return total; /* update stats */ total += swath; len -= swath; addr += swath; buf += swath; } while (len != 0); return total; } } /* enumerate the objects in the .chm archive */ int chm_enumerate(struct chmFile *h, int what, CHM_ENUMERATOR e, void *context) { Int32 curPage; /* buffer to hold whatever page we're looking at */ #ifdef WIN32 UChar *page_buf = alloca((unsigned int)h->block_len); #else UChar page_buf[h->block_len]; #endif struct chmPmglHeader header; UChar *end; UChar *cur; unsigned long lenRemain; /* the current ui */ struct chmUnitInfo ui; int flag; /* starting page */ curPage = h->index_head; /* until we have either returned or given up */ while (curPage != -1) { /* try to fetch the index page */ if (_chm_fetch_bytes(h, page_buf, (UInt64)h->dir_offset + (UInt64)curPage*h->block_len, h->block_len) != h->block_len) return 0; /* figure out start and end for this page */ cur = page_buf; lenRemain = _CHM_PMGL_LEN; if (! _unmarshal_pmgl_header(&cur, &lenRemain, &header)) return 0; end = page_buf + h->block_len - (header.free_space); /* loop over this page */ while (cur < end) { if (! _chm_parse_PMGL_entry(&cur, &ui)) return 0; /* check for DIRS */ if (ui.length == 0 && !(what & CHM_ENUMERATE_DIRS)) continue; /* check for FILES */ if (ui.length != 0 && !(what & CHM_ENUMERATE_FILES)) continue; /* check for NORMAL vs. META */ if (ui.path[0] == '/') { /* check for NORMAL vs. SPECIAL */ if (ui.path[1] == '#' || ui.path[1] == '$') flag = CHM_ENUMERATE_SPECIAL; else flag = CHM_ENUMERATE_NORMAL; } else flag = CHM_ENUMERATE_META; if (! (what & flag)) continue; /* call the enumerator */ { int status = (*e)(h, &ui, context); switch (status) { case CHM_ENUMERATOR_FAILURE: return 0; case CHM_ENUMERATOR_CONTINUE: break; case CHM_ENUMERATOR_SUCCESS: return 1; default: break; } } } /* advance to next page */ curPage = header.block_next; } return 1; } int chm_enumerate_dir(struct chmFile *h, const char *prefix, int what, CHM_ENUMERATOR e, void *context) { /* * XXX: do this efficiently (i.e. using the tree index) */ Int32 curPage; /* buffer to hold whatever page we're looking at */ #ifdef WIN32 UChar *page_buf = alloca((unsigned int)h->block_len); #else UChar page_buf[h->block_len]; #endif struct chmPmglHeader header; UChar *end; UChar *cur; unsigned long lenRemain; /* set to 1 once we've started */ int it_has_begun=0; /* the current ui */ struct chmUnitInfo ui; int flag; /* the length of the prefix */ char prefixRectified[CHM_MAX_PATHLEN+1]; int prefixLen; - char lastPath[CHM_MAX_PATHLEN]; + char lastPath[CHM_MAX_PATHLEN+1]; int lastPathLen; /* starting page */ curPage = h->index_head; /* initialize pathname state */ strncpy(prefixRectified, prefix, CHM_MAX_PATHLEN); prefixLen = strlen(prefixRectified); if (prefixLen != 0) { if (prefixRectified[prefixLen-1] != '/') { prefixRectified[prefixLen] = '/'; prefixRectified[prefixLen+1] = '\0'; ++prefixLen; } } lastPath[0] = '\0'; lastPathLen = -1; /* until we have either returned or given up */ while (curPage != -1) { /* try to fetch the index page */ if (_chm_fetch_bytes(h, page_buf, (UInt64)h->dir_offset + (UInt64)curPage*h->block_len, h->block_len) != h->block_len) return 0; /* figure out start and end for this page */ cur = page_buf; lenRemain = _CHM_PMGL_LEN; if (! _unmarshal_pmgl_header(&cur, &lenRemain, &header)) return 0; end = page_buf + h->block_len - (header.free_space); /* loop over this page */ while (cur < end) { if (! _chm_parse_PMGL_entry(&cur, &ui)) return 0; /* check if we should start */ if (! it_has_begun) { if (ui.length == 0 && strncmp(ui.path, prefixRectified, prefixLen) == 0) it_has_begun = 1; else continue; if (ui.path[prefixLen] == '\0') continue; } /* check if we should stop */ else { if (strncmp(ui.path, prefixRectified, prefixLen) != 0) return 1; } /* check if we should include this path */ if (lastPathLen != -1) { if (strncmp(ui.path, lastPath, lastPathLen) == 0) continue; } - strcpy(lastPath, ui.path); + strncpy(lastPath, ui.path, CHM_MAX_PATHLEN); + lastPath[CHM_MAX_PATHLEN] = '\0'; lastPathLen = strlen(lastPath); /* check for DIRS */ if (ui.length == 0 && !(what & CHM_ENUMERATE_DIRS)) continue; /* check for FILES */ if (ui.length != 0 && !(what & CHM_ENUMERATE_FILES)) continue; /* check for NORMAL vs. META */ if (ui.path[0] == '/') { /* check for NORMAL vs. SPECIAL */ if (ui.path[1] == '#' || ui.path[1] == '$') flag = CHM_ENUMERATE_SPECIAL; else flag = CHM_ENUMERATE_NORMAL; } else flag = CHM_ENUMERATE_META; if (! (what & flag)) continue; /* call the enumerator */ { int status = (*e)(h, &ui, context); switch (status) { case CHM_ENUMERATOR_FAILURE: return 0; case CHM_ENUMERATOR_CONTINUE: break; case CHM_ENUMERATOR_SUCCESS: return 1; default: break; } } } /* advance to next page */ curPage = header.block_next; } return 1; } /* resolve a particular object from the archive */ int chm_resolve_location(struct chmFile *h, unsigned long pos, struct chmUnitInfo *ui) { /* * XXX: implement caching scheme for dir pages */ Int32 curPage; /* buffer to hold whatever page we're looking at */ #ifdef WIN32 UChar *page_buf = alloca(h->block_len); #else UChar page_buf[h->block_len]; #endif /* starting page */ curPage = h->index_root; /* until we have either returned or given up */ while (curPage != -1) { /* try to fetch the index page */ if (_chm_fetch_bytes(h, page_buf, (UInt64)h->dir_offset + (UInt64)curPage*h->block_len, h->block_len) != h->block_len) return CHM_RESOLVE_FAILURE; /* now, if it is a leaf node: */ if (memcmp(page_buf, _chm_pmgl_marker, 4) == 0) { /* scan block */ /* UChar *pEntry = _chm_find_in_PMGL(page_buf, h->block_len, objPath);*/ { /* XXX: modify this to do a binary search using the nice index structure * that is provided for us. */ struct chmPmglHeader header; UInt32 hremain; UChar *end; UChar *cur; UChar *temp; /*
UInt64 strLen; char buffer[CHM_MAX_PATHLEN+1]; */ /* figure out where to start and end */ cur = page_buf; hremain = _CHM_PMGL_LEN; if (! _unmarshal_pmgl_header(&cur, &hremain, &header)) return CHM_RESOLVE_FAILURE; end = page_buf + h->block_len - (header.free_space); /* now, scan progressively */ while (cur < end) { UInt32 st = 0; UInt32 nd = 0; /* grab the name */ temp = cur; if (_chm_parse_PMGL_entry(&cur, ui) == 0) { return CHM_RESOLVE_FAILURE; } st = ui->start; nd = ui->start+ui->length; if ((st <= pos) && (pos < nd)) { printf("Resolve:[%u,%u,%u]\n", st, pos, nd); return CHM_RESOLVE_SUCCESS; } } return CHM_RESOLVE_FAILURE; } } /* else, if it is a branch node: */ else if (memcmp(page_buf, _chm_pmgi_marker, 4) == 0) { /* curPage = _chm_find_in_PMGI(page_buf, h->block_len, objPath);*/ return CHM_RESOLVE_FAILURE; if (0) { /* XXX: modify this to do a binary search using the nice index structure * that is provided for us */ struct chmPmgiHeader header; UInt32 hremain; int page=-1; UChar *end; UChar *cur; UInt64 strLen; char buffer[CHM_MAX_PATHLEN+1]; /* figure out where to start and end */ cur = page_buf; hremain = _CHM_PMGI_LEN; if (! _unmarshal_pmgi_header(&cur, &hremain, &header)) return -1; end = page_buf + h->block_len - (header.free_space); /* now, scan progressively */ while (cur < end) { if (_chm_parse_PMGL_entry(&cur, ui) == 0) { return CHM_RESOLVE_FAILURE; } if (ui->start <= pos && pos < ui->start + ui->length) { return CHM_RESOLVE_SUCCESS; } /* grab the name */ strLen = _chm_parse_cword(&cur); if (! _chm_parse_UTF8(&cur, strLen, buffer)) return -1; /* check if it is the right name */ /* #ifdef WIN32 if (stricmp(buffer, objPath) > 0) return page; #else if (strcasecmp(buffer, objPath) > 0) return page; #endif */ /* load next value for path */ page = (int)_chm_parse_cword(&cur); } curPage = page; |