1use thiserror::Error;
2
3use crate::{
4 config::DatabaseVersion,
5 db::Database,
6 format::{
7 kdb::parse_kdb,
8 kdbx3::{decrypt_kdbx3, parse_kdbx3},
9 kdbx4::{decrypt_kdbx4, parse_kdbx4},
10 DatabaseVersionParseError,
11 },
12 DatabaseKey,
13};
14
15impl Database {
16 pub fn open(source: &mut dyn std::io::Read, key: DatabaseKey) -> Result<Database, DatabaseOpenError> {
18 let mut data = Vec::new();
19 source.read_to_end(&mut data)?;
20
21 Database::parse(data.as_ref(), key)
22 }
23
24 pub fn parse(data: &[u8], key: DatabaseKey) -> Result<Database, DatabaseOpenError> {
26 let database_version = DatabaseVersion::parse(data)?;
27
28 match database_version {
29 DatabaseVersion::KDB(_) => parse_kdb(data, &key),
30 DatabaseVersion::KDB2(_) => Err(DatabaseOpenError::UnsupportedVersion),
31 DatabaseVersion::KDB3(_) => parse_kdbx3(data, &key),
32 DatabaseVersion::KDB4(_) => parse_kdbx4(data, &key),
33 }
34 }
35
36 pub fn get_xml(source: &mut dyn std::io::Read, key: DatabaseKey) -> Result<Vec<u8>, DatabaseOpenError> {
38 let mut data = Vec::new();
39 source.read_to_end(&mut data)?;
40
41 let database_version = DatabaseVersion::parse(data.as_ref())?;
42
43 let data = match database_version {
44 DatabaseVersion::KDB(_) => return Err(DatabaseOpenError::UnsupportedVersion),
45 DatabaseVersion::KDB2(_) => return Err(DatabaseOpenError::UnsupportedVersion),
46 DatabaseVersion::KDB3(_) => decrypt_kdbx3(data.as_ref(), &key)?.2,
47 DatabaseVersion::KDB4(_) => decrypt_kdbx4(data.as_ref(), &key)?.3,
48 };
49
50 Ok(data)
51 }
52
53 pub fn get_version(source: &mut dyn std::io::Read) -> Result<DatabaseVersion, DatabaseOpenError> {
55 let mut data = vec![0; DatabaseVersion::get_version_header_size()];
56 source.read_exact(&mut data)?;
57 let version = DatabaseVersion::parse(data.as_ref())?;
58 Ok(version)
59 }
60}
61
62#[derive(Debug, Error)]
64#[non_exhaustive]
65pub enum DatabaseOpenError {
66 #[error(transparent)]
68 Io(#[from] std::io::Error),
69
70 #[error("Unexpected end of file")]
72 UnexpectedEof,
73
74 #[error(transparent)]
76 VersionParse(#[from] DatabaseVersionParseError),
77
78 #[error("Unsupported database version")]
80 UnsupportedVersion,
81
82 #[error(transparent)]
84 Key(#[from] crate::key::DatabaseKeyError),
85
86 #[error(transparent)]
88 Cryptography(#[from] crate::crypt::CryptographyError),
89
90 #[error(transparent)]
92 Format(#[from] DatabaseFormatError),
93}
94
95#[derive(Debug, Error)]
97#[non_exhaustive]
98pub enum DatabaseFormatError {
99 #[error(transparent)]
101 Kdb(#[from] crate::format::kdb::KdbOpenError),
102
103 #[error(transparent)]
105 Kdbx3(#[from] crate::format::kdbx3::Kdbx3OpenError),
106
107 #[error(transparent)]
109 Kdbx4(#[from] crate::format::kdbx4::Kdbx4OpenError),
110}