/// /// @brief Add cookie record to searchable memory tree. /// /// @param domain A pointer to an O4Domain struct (parent node). /// @param b The file bytes to parse. /// @param idx The address of an integer with the current index position. /// /// @return void. /// private void AddCookie(ref O4Domain domain, byte[] b, ref int idx) { ushort wTagLen; byte cbTagID; O4Cookie cookie = new O4Cookie(); // Load the cookie tag size wTagLen = Endian.SwapUInt16(BitConverter.ToUInt16(b, idx)); idx += 2; // Tag indicates how many bytes we should read. We don't go by this, // because then we lose context of who the record belongs to. // Keep reading tags in while (idx < b.Length) { cbTagID = b[idx++]; // Handle the tag switch (cbTagID) { case O4_ID_COOKIE_NAME:// Cookie name cookie.Name = this.ReadString(b, ref idx); break; case O4_ID_COOKIE_VALUE:// Cookie value cookie.Value = this.ReadString(b, ref idx); break; case O4_ID_COOKIE_EXPIRES:// Cookie expires cookie.Expires = this.ReadLong(b, ref idx); break; case O4_ID_COOKIE_USED:// Cookie last used cookie.LastUsed = this.ReadLong(b, ref idx); break; case O4_ID_COOKIE_DESC:// Cookie2 comment cookie.Comment = this.ReadString(b, ref idx); break; case O4_ID_COOKIE_DESCURL:// Cookie2 Comment URL cookie.CommentURL = this.ReadString(b, ref idx); break; case O4_ID_COOKIE_RXDMN:// Cookie2 Received Domain cookie.RecvDomain = this.ReadString(b, ref idx); break; case O4_ID_COOKIE_RXPATH:// Cookie2 Received Path cookie.RecvPath = this.ReadString(b, ref idx); break; case O4_ID_COOKIE_PORT:// Cookie2 Portlist cookie.PortList = this.ReadString(b, ref idx); break; case O4_ID_COOKIE_SECURE:// Cookie secure flag cookie.Secure = true; break; case O4_ID_COOKIE_VER:// Cookie Version cookie.Version = this.ReadByte(b, ref idx); break; case O4_ID_COOKIE_SERVER:// Cookie sent back to server that sent it cookie.Server = true; break; case O4_ID_COOKIE_PROTECT:// Cookie protected flag cookie.Protected = true; break; case O4_ID_COOKIE_PREFIX:// Cookie Path prefix flag cookie.Prefixed = true; break; case O4_ID_COOKIE_PWD:// Cookie Password Flag cookie.Password = true; break; case O4_ID_COOKIE_AUTH:// Cookie Authenticate Flag cookie.Authenticate = true; break; case O4_ID_COOKIE_3RD:// Cookie Third party flag cookie.ThirdParty = true; break; case O4_ID_COOKIE_END: goto EXIT_WHILE; default:// Handle undocumented flags and field tags if (!(0 < (cbTagID & 0x80))) // this is a field tag { // Increment to next field idx += (2 + Endian.SwapUInt16(BitConverter.ToUInt16(b, idx))); } // Ignore undocumented flags (already incremented one byte) break; } } EXIT_WHILE: domain.FCookies.Add(cookie); }
/// /// @brief Recursive search function employed by GetCookies. /// /// @param Domain The current domain to search. /// @param Names The array of domain names to find. /// @param iName The index of the name to reference in the search. /// /// @return A list of O4Cookie objects if successfull, otherwise null. /// private List<O4Cookie> GetCookieRecurse(O4Domain Domain, string[] Names, int iName) { List<O4Cookie> ret = null; if (iName < Names.Length) { foreach (O4Domain d in Domain.FDomains) { if (d.FName.ToUpper().Equals(Names[iName].ToUpper())) //Match, search for next domain { ret = GetCookieRecurse(d, Names, iName + 1); } else //Search the next level down for this domain { ret = GetCookieRecurse(d, Names, iName); } if (ret != null) return ret; } } else //We incremented to the end of the domain get the cookies { if (0 < Domain.FCookies.Count) { return Domain.FCookies; } } return null; // If we get here we couldn't find it }
/// /// @brief Parse file bytes into searchable memory tree. /// /// @param domain A pointer to an O4Domain struct. /// @param b The file bytes to parse. /// @param idx The address of an integer with the current index position. /// /// @return void. /// private void ParseCookieBytes(ref O4Domain domain, byte[] b, ref int idx) { ushort wTagLen; byte cbTagID; // Keep reading tags in while (idx < b.Length) { cbTagID = b[idx++]; // Handle the tag switch (cbTagID) { case O4_ID_DMN: // Sub-domain // Load the domain tag size wTagLen = Endian.SwapUInt16(BitConverter.ToUInt16(b, idx)); idx += 2; // Tag indicates how many bytes we should read. We don"t go by this, // because then we lose context of who the record belongs to. For( example, // there may be sub-domains, cookies, etc below this domain. Due to this, // we can't really break when we have read the content bytes of the domain. O4Domain d = new O4Domain(); d.initialize(); ParseCookieBytes(ref d, b, ref idx); domain.FDomains.Add(d); break; case O4_ID_DMN_NAME: // Domain name string domain.FName = this.ReadString(b, ref idx); break; case O4_ID_DMN_FILTER: // Domain filter value domain.FFilter = this.ReadByte(b, ref idx); break; case O4_ID_DMN_MATCH: // Domain match value domain.FMatch = this.ReadByte(b, ref idx); break; case O4_ID_DMN_ACCEPT: // Domain accept value domain.FAccept = this.ReadByte(b, ref idx); break; case O4_ID_DMN_END: // End of domain record return; case O4_ID_PATH: // Start of path break; case O4_ID_PATH_NAME: // Path name string domain.FPaths.Add(this.ReadString(b, ref idx), string.Empty); break; case O4_ID_PATH_END: // Path end break; //Sub domain end case O4_ID_COOKIE: // Cookie AddCookie(ref domain, b, ref idx); break; default: if (!(0 < (cbTagID & 0x80))) // this is a field tag { // Increment to next field idx += (2 + Endian.SwapUInt16(BitConverter.ToUInt16(b, idx))); } // Ignore undocumented flags (already incremented one byte) break; } } }