keeweb/app/scripts/comp/format/kdbx-to-html.js

120 lines
3.5 KiB
JavaScript

/* eslint-disable import/no-commonjs */
import kdbxweb from 'kdbxweb';
import { RuntimeInfo } from 'const/runtime-info';
import { Links } from 'const/links';
import { DateFormat } from 'util/formatting/date-format';
import { StringFormat } from 'util/formatting/string-format';
import { Locale } from 'util/locale';
const Templates = {
db: require('templates/export/db.hbs'),
entry: require('templates/export/entry.hbs')
};
const FieldMapping = [
{ name: 'UserName', locStr: 'user' },
{ name: 'Password', locStr: 'password', protect: true },
{ name: 'URL', locStr: 'website' },
{ name: 'Notes', locStr: 'notes' }
];
const KnownFields = { 'Title': true };
for (const { name } of FieldMapping) {
KnownFields[name] = true;
}
function walkGroup(db, group, parents) {
parents = [...parents, group];
if (
group.uuid.equals(db.meta.recycleBinUuid) ||
group.uuid.equals(db.meta.entryTemplatesGroup)
) {
return '';
}
const self = group.entries.map((entry) => walkEntry(db, entry, parents)).join('\n');
const children = group.groups
.map((childGroup) => walkGroup(db, childGroup, parents))
.join('\n');
return self + children;
}
function walkEntry(db, entry, parents) {
const path = parents.map((group) => group.name).join(' / ');
const fields = [];
for (const field of FieldMapping) {
const value = entryField(entry, field.name);
if (value) {
fields.push({
title: StringFormat.capFirst(Locale[field.locStr]),
value,
protect: field.protect
});
}
}
for (const fieldName of Object.keys(entry.fields)) {
if (!KnownFields[fieldName]) {
const value = entryField(entry, fieldName);
if (value) {
fields.push({
title: fieldName,
value,
protect: entry.fields[fieldName].isProtected
});
}
}
}
const title = entryField(entry, 'Title');
let expires;
if (entry.times.expires && entry.times.expiryTime) {
expires = DateFormat.dtStr(entry.times.expiryTime);
}
const attachments = Object.entries(entry.binaries)
.map(([name, data]) => {
if (data && data.ref) {
data = data.value;
}
if (data) {
const base64 = kdbxweb.ByteUtils.bytesToBase64(data);
data = 'data:application/octet-stream;base64,' + base64;
}
return { name, data };
})
.filter((att) => att.name && att.data);
return Templates.entry({
path,
title,
fields,
tags: entry.tags.join(', '),
created: DateFormat.dtStr(entry.times.creationTime),
modified: DateFormat.dtStr(entry.times.lastModTime),
expires,
attachments
});
}
function entryField(entry, fieldName) {
const value = entry.fields[fieldName];
return (value && value.isProtected && value.getText()) || value || '';
}
const KdbxToHtml = {
convert(db, options) {
const content = db.groups.map((group) => walkGroup(db, group, [])).join('\n');
return Templates.db({
name: options.name,
date: DateFormat.dtStr(Date.now()),
appLink: Links.Homepage,
appVersion: RuntimeInfo.version,
contentHtml: content
});
},
entryToHtml(db, entry) {
return walkEntry(db, entry, []);
}
};
export { KdbxToHtml };