public static bool UnmarshalPmglHeader(ref byte[] pData, ref uint pDataPos, ref uint pDataLen, ref chmPmglHeader dest) { /* we only know how to deal with a 0x14 byte structures */ if (pDataLen != CHM_PMGL_LEN) { return(false); } InitialisePmglHeader(ref dest); /* unmarshal fields */ Unmarshal.ToCharArray(ref pData, ref pDataPos, ref pDataLen, ref dest.signature, 4); Unmarshal.ToUInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.free_space); Unmarshal.ToUInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.unknown_0008); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.block_prev); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.block_next); /* check structure */ if (new String(dest.signature, 0, 4).CompareTo(CHM_PMGL_MARKER) != 0) { return(false); } return(true); }
/* find an exact entry in PMGL; return NULL if we fail */ public static long FindInPmgl(byte[] page_buf, UInt32 block_len, string objPath) { /* XXX: modify this to do a binary search using the nice index structure * that is provided for us. */ chmPmglHeader header = new chmPmglHeader(); uint hremain; uint end; uint cur; uint temp; UInt64 strLen; char[] buffer = new char[Storage.CHM_MAX_PATHLEN]; /* figure out where to start and end */ cur = 0; hremain = CHM_PMGL_LEN; if (!UnmarshalPmglHeader(ref page_buf, ref cur, ref hremain, ref header)) { return(-1); } end = block_len - (header.free_space); /* now, scan progressively */ while (cur < end) { /* grab the name */ temp = cur; strLen = Storage.ParseCWord(page_buf, ref cur); if (strLen > Storage.CHM_MAX_PATHLEN) { return(-1); } if (!Storage.ParseUTF8(page_buf, ref cur, strLen, ref buffer)) { return(-1); } /* check if it is the right name */ if (Pmgi.strcasecmp(new String(buffer), objPath) == 0) { return((long)temp); } SkipPmglEntryData(page_buf, ref cur); } return(-1); }
/* find an exact entry in PMGL; return NULL if we fail */ public static long FindInPmgl(byte[] page_buf, UInt32 block_len, string objPath) { /* XXX: modify this to do a binary search using the nice index structure * that is provided for us. */ chmPmglHeader header = new chmPmglHeader(); uint hremain; uint end; uint cur; uint temp; UInt64 strLen; char[] buffer = new char[Storage.CHM_MAX_PATHLEN]; /* figure out where to start and end */ cur = 0; hremain = CHM_PMGL_LEN; if (!UnmarshalPmglHeader(ref page_buf, ref cur, ref hremain, ref header)) return -1; end = block_len - (header.free_space); /* now, scan progressively */ while (cur < end) { /* grab the name */ temp = cur; strLen = Storage.ParseCWord(page_buf, ref cur); if (strLen > Storage.CHM_MAX_PATHLEN) return -1; if (!Storage.ParseUTF8(page_buf, ref cur, strLen, ref buffer)) return -1; /* check if it is the right name */ if (Pmgi.strcasecmp(new String(buffer), objPath) == 0) return (long)temp; SkipPmglEntryData(page_buf, ref cur); } return -1; }
/* 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; }
/* 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); }
public static void InitialisePmglHeader(ref chmPmglHeader dest) { dest.signature = new char[4]; }
public static bool UnmarshalPmglHeader(ref byte[] pData, ref uint pDataPos, ref uint pDataLen, ref chmPmglHeader dest) { /* we only know how to deal with a 0x14 byte structures */ if (pDataLen != CHM_PMGL_LEN) return false; InitialisePmglHeader(ref dest); /* unmarshal fields */ Unmarshal.ToCharArray(ref pData, ref pDataPos, ref pDataLen, ref dest.signature, 4); Unmarshal.ToUInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.free_space); Unmarshal.ToUInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.unknown_0008); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.block_prev); Unmarshal.ToInt32(ref pData, ref pDataPos, ref pDataLen, ref dest.block_next); /* check structure */ if (new String(dest.signature, 0, 4).CompareTo(CHM_PMGL_MARKER) != 0) return false; return true; }