internal static BimilItem Parse(BimilDocument document, byte[] buffer, int offset, int count) { if (count < 4) { throw new FormatException("Invalid buffer size."); } var res = new BimilItem(document); var currOffset = offset; while (currOffset < (offset + count)) { var keyLength = GetInt32(buffer, currOffset); var valueLength = GetInt32(buffer, currOffset + 4); var type = (BimilRecordFormat)GetInt32(buffer, currOffset + 8); var key = BimilValue.Parse(document, buffer, currOffset + 12, keyLength); var value = BimilValue.Parse(document, buffer, currOffset + 12 + keyLength, valueLength); res.Records.Add(new BimilRecord(document, key.Text, value.Text, type)); currOffset += 12 + keyLength + valueLength; } if (currOffset != (offset + count)) { throw new FormatException("Invalid buffer content."); } return(res); }
/// <summary> /// Returns document. /// </summary> /// <param name="stream">Stream.</param> /// <param name="password">Password.</param> /// <exception cref="FormatException">Cannot parse document.</exception> public static BimilDocument Open(Stream stream, string password) { try { using (var timer = new Medo.Diagnostics.LifetimeWatch("Open")) { var doc = new BimilDocument(); var salt = new byte[16]; stream.Read(salt, 0, 16); doc.PasswordSalt = salt; var deriveBytes = new Rfc2898DeriveBytes(UTF8Encoding.UTF8.GetBytes(password), doc.PasswordSalt, 4096); doc.Crypto.Key = deriveBytes.GetBytes(16); doc.Crypto.IV = deriveBytes.GetBytes(16); var encBuffer = new byte[stream.Length - 16]; stream.Read(encBuffer, 0, encBuffer.Length); byte[] decBuffer; using (var dec = doc.Crypto.CreateDecryptor()) { decBuffer = dec.TransformFinalBlock(encBuffer, 0, encBuffer.Length); } if ((decBuffer[0] == 0x41) && (decBuffer[1] == 0x31) && (decBuffer[2] == 0x32) && (decBuffer[3] == 0x38)) { if ((decBuffer[decBuffer.Length - 4] != 0x41) || (decBuffer[decBuffer.Length - 3] != 0x31) || (decBuffer[decBuffer.Length - 2] != 0x32) || (decBuffer[decBuffer.Length - 1] != 0x38)) { throw new FormatException("Invalid secondary identifier."); } doc.Id = "A128"; } else { throw new FormatException("Invalid primary identifier."); } var currOffset = 4; while (currOffset < (decBuffer.Length - 4)) { var itemLen = GetInt32(decBuffer, currOffset); var item = BimilItem.Parse(doc, decBuffer, currOffset + 4, itemLen); doc.Items.Add(item); currOffset += 4 + itemLen; } return(doc); } } catch (CryptographicException ex) { throw new FormatException("Cannot parse document.", ex); } catch (OverflowException ex) { throw new FormatException("Cannot parse document.", ex); } catch (SecurityException ex) { throw new FormatException("Cannot parse document.", ex); } }
/// <summary> /// Adds new item. /// </summary> /// <param name="name">Title.</param> /// <param name="iconIndex">Icon index.</param> public BimilItem AddItem(string name, int iconIndex) { var item = new BimilItem(this) { IconIndex = iconIndex }; item.NameRecord.Value.Text = name; this.Items.Add(item); return(item); }