public static IBObject GetInstance(IDictionary<String, String> attributes) { IBObject obj; switch (attributes["class"]) { case "NSArray": case "NSMutableArray": obj = new IBArray(attributes); break; case "NSDictionary": case "NSMutableDictionary": obj = new IBDictionary(attributes); break; case "IBClassDescriber": obj = new IBClassDescriber(attributes); break; case "IBPartialClassDescription": obj = new IBPartialClassDescription(attributes); break; case "NSSet": case "NSMutableSet": obj = new IBSet(attributes); break; default: obj = new IBObject(attributes); break; } return obj; }
private static void SetupBencodeParser(IBencodeParser bparser, string bencode, BString key, IBObject value, bool hasEndChar) { bparser.Parse<BString>(Arg.Any<BencodeStream>()) .Returns(key); bparser.Parse(Arg.Any<BencodeStream>()) .Returns(value) .AndDoes(x => { // Set stream position to end of list, skipping all "parsed" content var stream = x.Arg<BencodeStream>(); stream.Position += Math.Max(1, bencode.Length - 1); if (hasEndChar) stream.Position--; }); }
public void WriteObject(int indentLevel, IBObject obj) { switch(obj.BType) { case BObjectType.Integer: WriteInteger(indentLevel, (BInteger)obj); break; case BObjectType.ByteString: WriteByteString(indentLevel, (BByteString)obj); break; case BObjectType.List: WriteList(indentLevel, (BList)obj); break; case BObjectType.Dictionary: WriteDictionary(indentLevel, (BDictionary)obj); break; } }
internal TrackerResponse(BDictionary dictionary) { FailureReason = ((BString)dictionary["failure reason"])?.ToString(); WarningMessage = ((BString)dictionary["warning message"])?.ToString(); Interval = (int?)((BNumber)dictionary["interval"])?.Value; MinInterval = (int?)((BNumber)dictionary["min interval"])?.Value; TrackerId = ((BString)dictionary["tracker id"])?.ToString(); Complete = (int?)((BNumber)dictionary["complete"])?.Value; InComplete = (int?)((BNumber)dictionary["incomplete"])?.Value; IBObject peersObject = dictionary["peers"]; if (peersObject == null) { return; } List <PeerInfo> peers = new List <PeerInfo>(); Peers = peers; if (peersObject is BString) { IReadOnlyList <byte> data = ((BString)peersObject).Value; for (int i = 0; i < data.Count; i += 6) { string ip = $"{data[i]}.{data[i + 1]}.{data[i + 2]}.{data[i + 3]}"; int port = (data[i + 5] << 8) + data[i + 4]; peers.Add(new PeerInfo(null, ip, port)); } } else { BList <BDictionary> data = (BList <BDictionary>)peersObject; foreach (BDictionary obj in data) { string id = ((BString)obj["peer id"]).ToString(); string ip = ((BString)obj["ip"]).ToString(); int port = (int)((BNumber)obj["port"]).Value; peers.Add(new PeerInfo(id, ip, port)); } } }
public void Test_BencodeParser_class() { BencodeParser parser = new BencodeParser(); Assert.IsNotNull(parser); IBObject bObj = parser.Parse("i12345e"); Assert.IsInstanceOf <BNumber>(bObj); Assert.AreEqual(12345, ((BNumber)bObj).Value); bObj = parser.Parse("4:test"); Assert.IsInstanceOf <BString>(bObj); Assert.AreEqual("test", ((BString)bObj).ToString()); bObj = parser.Parse("l4:testi1234ee"); Assert.IsInstanceOf <BList>(bObj); bObj = parser.Parse("d6:numberi1234e3:str4:teste"); Assert.IsInstanceOf <BDictionary>(bObj); }
// TODO: Unit tests private void FixEncoding(IBObject bobject, Encoding encoding) { var dictionary = bobject as BDictionary; if (dictionary != null) { FixEncodingInDictionary(dictionary, encoding); } var list = bobject as BList; if (list != null) { FixEncodingInList(list, encoding); } var value = bobject as BString; if (value != null) { value.Encoding = encoding; } }
static string GetTypeName(Dictionary <int, string> customTypeNames, IBObject obj) { string name = null; // First resolve custom classes. Seems Apple also uses these for some framework classes, // maybe for classes without direct desktop equivalents? if (obj != null && obj.Id.HasValue && customTypeNames != null) { customTypeNames.TryGetValue(obj.Id.Value, out name); } //else, try to handle the interface builder built-in types if (name == null && obj is UnknownIBObject) { string ibType = ((UnknownIBObject)obj).Class; if (ibType.StartsWith("NS")) { name = ibType; } else if (ibType.StartsWith("IB") && ibType.Length > 2 && ibType != "IBUICustomObject") { name = ibType.Substring(2); } } //now try to resolve the obj-c name to a fully qualified class if (name != null) { string resolvedName; if (typeNameMap.TryGetValue(name, out resolvedName)) { return(resolvedName); } } return(name); }
public void EncodeObject(IBObject obj, Stream outputStream) { if (obj.BType == BObjectType.Integer) { integerTransform.Encode((BInteger)obj, outputStream); } else if (obj.BType == BObjectType.ByteString) { byteStringTransform.Encode((BByteString)obj, outputStream); } else if (obj.BType == BObjectType.List) { listTransform.Encode((BList)obj, outputStream); } else if (obj.BType == BObjectType.Dictionary) { dictionaryTransform.Encode((BDictionary)obj, outputStream); } }
public void MissingEndChar_ThrowsInvalidBencodeExceptionAsync(string bencode, IBencodeParser bparser, IBObject something) { // Arrange bparser.ParseAsync(Arg.Any <PipeBencodeReader>()) .Returns(something) .AndSkipsAheadAsync(bencode.Length - 1); // Act var parser = new BListParser(bparser); Func <Task> action = async() => await parser.ParseStringAsync(bencode); // Assert action.Should().Throw <InvalidBencodeException <BList> >().WithMessage("*Missing end character of object*"); }
public void MissingEndChar_ThrowsInvalidBencodeException(string bencode, IBencodeParser bparser, BString someKey, IBObject someValue) { // Arrange bparser.Parse <BString>(Arg.Any <BencodeReader>()) .Returns(someKey); bparser.Parse(Arg.Any <BencodeReader>()) .Returns(someValue) .AndSkipsAhead(bencode.Length - 1); // Act var parser = new BDictionaryParser(bparser); Action action = () => parser.ParseString(bencode); // Assert action.Should().Throw <InvalidBencodeException <BDictionary> >().WithMessage("*Missing end character of object*"); }
/// <summary> /// Visits the specified item. /// </summary> /// <param Name = "item">The item.</param> public void Visit(IBObject item) { }
private static void ExtractInfo(IBObject obj, TorrentMetadata file) { var dict = (BDictionary)obj; bool?singleFile = null; foreach (var item in dict) { var key = item.Key.ToString(); switch (key) { case "length": if (singleFile == false) { throw new DataMisalignedException("Torrent already have key \"files\" key"); } singleFile = true; var fname = string.Empty; if (dict.TryGetValue("name", out IBObject nameVal)) { fname = ((BString)nameVal).ToString(); } file.Files.Add(fname, (BNumber)item.Value); break; case "name": break; case "files": if (singleFile == true) { throw new DataMisalignedException("Torrent already have \"length\" key"); } singleFile = false; var dicLst = (BList)item.Value; foreach (var dicListItem in dicLst) { var sdic = (BDictionary)dicListItem; file.Files.Add(((BString)sdic["path"]).ToString(), (BNumber)sdic["length"]); } break; case "piece length": file.PieceLength = (BNumber)item.Value; break; case "pieces": var shas = (BString)item.Value; if (shas.Value.Count % 20 > 0) { throw new DataMisalignedException("SHA1 hash section is invalid"); } var arr = shas.Value.ToArray(); for (var i = 0; i < shas.Value.Count / 20; i++) { var chunk = new byte[20]; Array.Copy(arr, i * 20, chunk, 0, 20); file.SHAs.Add(chunk); } break; default: file.Extensions.Add($"info.{item.Key}", item.Value); break; } } if (singleFile == null) { throw new DataMisalignedException("Information about torrent contents was not found"); } }
public static bool TryParse(ReadOnlySpan <byte> data, out IBObject bObject, bool strictDictionaryOrder = true) { var reader = new Utf8BEncodingReader(data); List <IBObject> stack = null; bObject = null; BString key = null; while (reader.Read()) { IBObject value; switch (reader.TokenType) { case BEncodingTokenType.String: value = new BString(reader.ValueSpan); break; case BEncodingTokenType.Integer: if (!reader.TryGet(out BigInteger integer)) { return(false); } value = new BInteger(integer); break; case BEncodingTokenType.End: if (stack is null || !(key is null)) { return(false); } stack[stack.Count - 1].SpanEnd = reader.Consumed; if (stack.Count == 1) { return(reader.IsEmpty); } Debug.Assert(stack.Count != 0); stack.RemoveAt(stack.Count - 1); continue; default: Debug.Assert(reader.TokenType == BEncodingTokenType.StartDictionary || reader.TokenType == BEncodingTokenType.StartList); value = reader.TokenType == BEncodingTokenType.StartDictionary ? (IBObject) new BDictionary() : (IBObject) new BList(); if (stack is null) { Debug.Assert(key is null); stack = new List <IBObject>(4); bObject = value; stack.Add(bObject); continue; } else { if (stack.Count == BEncodingConstants.DepthMax) { return(false); } break; } } if (stack is null) { Debug.Assert(bObject is null && key is null); Debug.Assert(reader.TokenType != BEncodingTokenType.StartDictionary); Debug.Assert(reader.TokenType != BEncodingTokenType.StartList); bObject = value; return(reader.IsEmpty); } if (stack.Count == 0) { return(false); } var top = stack[^ 1];
public static bool TryParse(string data, out IBObject bObject, bool strictDictionaryOrder = true) => TryParse(BEncodingHelpers.UTF8.GetBytes(data), out bObject, strictDictionaryOrder);
/// <summary> /// Encodes the object and returns the result as a string using <see cref="Encoding.UTF8"/>. /// </summary> /// <returns>The object bencoded and converted to a string using <see cref="Encoding.UTF8"/>.</returns> public static string EncodeAsString(this IBObject bobject) => EncodeAsString(bobject, Encoding.UTF8);
/// <summary> /// Visits the specified item. /// </summary> /// <param Name = "item">The item.</param> public void Visit(IBObject item) { Console.WriteLine(item.ToString()); }
private static void SetupBencodeParser(IBencodeParser bparser, string bencode, BString key, IBObject value, bool hasEndChar) { bparser.Parse <BString>(Arg.Any <BencodeStream>()) .Returns(key); bparser.Parse(Arg.Any <BencodeStream>()) .Returns(value) .AndDoes(x => { // Set stream position to end of list, skipping all "parsed" content var stream = x.Arg <BencodeStream>(); stream.Position += Math.Max(1, bencode.Length - 1); if (hasEndChar) { stream.Position--; } }); }