/* resolve a particular object from the archive */ public bool ResolveObject(string objPath, ref ChmUnitInfo ui) { /* * XXX: implement caching scheme for dir pages */ Int32 curPage; /* buffer to hold whatever page we're looking at */ /* RWE 6/12/2003 */ byte[] page_buf = new byte[_h.block_len]; /* starting page */ curPage = _h.index_root; /* until we have either returned or given up */ while (curPage != -1) { /* try to fetch the index page */ if (Storage.FetchBytes(ref _h, ref page_buf, (UInt64)_h.dir_offset + (UInt64)curPage * _h.block_len, _h.block_len) != _h.block_len) { return(false); } /* now, if it is a leaf node: */ if (ASCIIEncoding.UTF8.GetString(page_buf, 0, 4).CompareTo(Pmgl.CHM_PMGL_MARKER) == 0) { /* scan block */ long pEntry = Pmgl.FindInPmgl(page_buf, _h.block_len, objPath); if (pEntry < 0) { return(false); } /* parse entry and return */ uint os = (uint)pEntry; Pmgl.ParsePgmlEntry(page_buf, ref os, ref ui); return(true); } /* else, if it is a branch node: */ else if (ASCIIEncoding.UTF8.GetString(page_buf, 0, 4).CompareTo(Pmgi.CHM_PMGI_MARKER) == 0) { curPage = Pmgi.FindInPmgi(page_buf, _h.block_len, objPath); } /* else, we are confused. give up. */ else { return(false); } } /* didn't find anything. fail. */ return(false); }
/* enumerate the objects in the .chm archive */ public bool Enumerate(EnumerateLevel what, ChmEnumerator e, object context) { Int32 curPage; /* buffer to hold whatever page we're looking at */ /* RWE 6/12/2003 */ byte[] page_buf = new byte[_h.block_len]; chmPmglHeader header = new chmPmglHeader(); uint end; uint cur; uint lenRemain; UInt64 ui_path_len; /* the current ui */ ChmUnitInfo ui = new ChmUnitInfo(); int type_bits = ((int)what & 0x7); int filter_bits = ((int)what & 0xF8); /* starting page */ curPage = _h.index_head; /* until we have either returned or given up */ while (curPage != -1) { /* try to fetch the index page */ if (Storage.FetchBytes(ref _h, ref page_buf, (UInt64)_h.dir_offset + (UInt64)curPage * _h.block_len, _h.block_len) != _h.block_len) { return(false); } /* figure out start and end for this page */ cur = 0; lenRemain = Pmgl.CHM_PMGL_LEN; if (!Pmgl.UnmarshalPmglHeader(ref page_buf, ref cur, ref lenRemain, ref header)) { return(false); } end = _h.block_len - (header.free_space); /* loop over this page */ while (cur < end) { ui.flags = 0; if (!Pmgl.ParsePgmlEntry(page_buf, ref cur, ref ui)) { return(false); } /* get the length of the path */ ui_path_len = (ulong)ui.path.Length; /* check for DIRS */ if (ui.path.EndsWith("/")) { ui.flags |= (int)EnumerateLevel.Directories; } /* check for FILES */ if (!ui.path.EndsWith("/")) { ui.flags |= (int)EnumerateLevel.Files; } /* check for NORMAL vs. META */ if (ui.path.StartsWith("/")) { /* check for NORMAL vs. SPECIAL */ if (ui.path.Length > 1 && (ui.path[1] == '#' || ui.path[1] == '$')) { ui.flags |= (int)EnumerateLevel.Special; } else { ui.flags |= (int)EnumerateLevel.Normal; } } else { ui.flags |= (int)EnumerateLevel.Meta; } if (!Convert.ToBoolean(type_bits & ui.flags)) { continue; } if (filter_bits != 0 && (filter_bits & ui.flags) == 0) { continue; } /* call the enumerator */ EnumerateStatus status = e(this, ui, context); switch (status) { case EnumerateStatus.Failure: return(false); case EnumerateStatus.Continue: break; case EnumerateStatus.Success: return(true); default: break; } } /* advance to next page */ curPage = header.block_next; } return(true); }