mirror of
https://github.com/keymanapp/keyman.git
synced 2026-09-28 10:37:41 +00:00
parent
35799e2306
commit
ced4ed9099
1 changed files with 66 additions and 77 deletions
|
|
@ -9,10 +9,7 @@
|
|||
#include <kmx/kmx_plus.h>
|
||||
#include <kmx/kmx_xstring.h>
|
||||
|
||||
#if KMXPLUS_DEBUG
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include "kmx_processevent.h" // for debug functions
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
|
|
@ -20,14 +17,6 @@ namespace km {
|
|||
namespace kbp {
|
||||
namespace kmx {
|
||||
|
||||
#if KMXPLUS_DEBUG
|
||||
#define debug_println(x) std::cerr << __FILE__ << ":" << __LINE__ << ": " << (x) << std::endl;
|
||||
#define KMXPLUS_FPRINTF(x) fprintf x
|
||||
#else
|
||||
#define debug_println(x)
|
||||
#define KMXPLUS_FPRINTF(x)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Validate (and print out) a section name dword
|
||||
*
|
||||
|
|
@ -42,9 +31,9 @@ validate_section_name(KMX_DWORD ident) {
|
|||
unsigned char ch = ident & 0xFF;
|
||||
if (ch < 0x20 || ch > 0x7F) {
|
||||
valid = false;
|
||||
KMXPLUS_FPRINTF((stderr, "\\x%02X", ch));
|
||||
DebugLog("\\x%02X", ch);
|
||||
} else {
|
||||
KMXPLUS_FPRINTF((stderr, "%c", ch));
|
||||
DebugLog("%c", ch);
|
||||
}
|
||||
ident >>= 8;
|
||||
}
|
||||
|
|
@ -62,19 +51,19 @@ validate_section_name(KMX_DWORD ident) {
|
|||
static const kmx::COMP_KMXPLUS_HEADER *
|
||||
header_from_bytes(const uint8_t *data, KMX_DWORD length, uint32_t ident) {
|
||||
if (!data) {
|
||||
debug_println("!data");
|
||||
DebugLog("!data");
|
||||
return nullptr;
|
||||
}
|
||||
if (length < LDML_LENGTH_HEADER) {
|
||||
debug_println("length < LDML_LENGTH_HEADER");
|
||||
DebugLog("length < LDML_LENGTH_HEADER");
|
||||
}
|
||||
const COMP_KMXPLUS_HEADER *all = reinterpret_cast<const COMP_KMXPLUS_HEADER *>(data);
|
||||
if (!all->valid(length)) {
|
||||
debug_println("header failed validation");
|
||||
DebugLog("header failed validation");
|
||||
return nullptr;
|
||||
}
|
||||
if (all->ident != ident) {
|
||||
debug_println("header had wrong section id");
|
||||
DebugLog("header had wrong section id");
|
||||
return nullptr;
|
||||
}
|
||||
return all;
|
||||
|
|
@ -91,7 +80,7 @@ header_from_bytes(const uint8_t *data, KMX_DWORD length, uint32_t ident) {
|
|||
template <class T>
|
||||
const T *section_from_bytes(const uint8_t *data, KMX_DWORD length) {
|
||||
if (length < sizeof(T)) { // Does not include dynamic data. First check.
|
||||
debug_println("length < sizeof(section)");
|
||||
DebugLog("length < sizeof(section)");
|
||||
return nullptr;
|
||||
}
|
||||
const COMP_KMXPLUS_HEADER *header = header_from_bytes(data, length, T::IDENT);
|
||||
|
|
@ -105,17 +94,17 @@ const T *section_from_bytes(const uint8_t *data, KMX_DWORD length) {
|
|||
|
||||
template <class T>
|
||||
const T *section_from_sect(const COMP_KMXPLUS_SECT* sect) {
|
||||
KMXPLUS_FPRINTF((stderr, "----\n")); // separate a new section's validation
|
||||
DebugLog("----"); // separate a new section's validation
|
||||
const uint8_t *rawbytes = reinterpret_cast<const uint8_t *>(sect);
|
||||
if (rawbytes == nullptr) {
|
||||
debug_println("section_from_sect(nullptr) == nullptr");
|
||||
DebugLog("section_from_sect(nullptr) == nullptr");
|
||||
return nullptr;
|
||||
}
|
||||
KMX_DWORD offset = sect->find(T::IDENT);
|
||||
if (!offset) {
|
||||
debug_println("section_from_sect() - not found. section:");
|
||||
DebugLog("section_from_sect() - not found. section:");
|
||||
validate_section_name(T::IDENT);
|
||||
KMXPLUS_FPRINTF((stderr, "\n"));
|
||||
DebugLog("");
|
||||
return nullptr;
|
||||
}
|
||||
KMX_DWORD entrylength = sect->total - offset;
|
||||
|
|
@ -124,40 +113,40 @@ const T *section_from_sect(const COMP_KMXPLUS_SECT* sect) {
|
|||
|
||||
bool
|
||||
COMP_KMXPLUS_HEADER::valid(KMX_DWORD length) const {
|
||||
KMXPLUS_FPRINTF((stderr, ": (%X) size 0x%X\n", ident, size));
|
||||
DebugLog(": (%X) size 0x%X\n", ident, size);
|
||||
if (size < LDML_LENGTH_HEADER) {
|
||||
debug_println("size < LDML_LENGTH_HEADER");
|
||||
DebugLog("size < LDML_LENGTH_HEADER");
|
||||
return false;
|
||||
}
|
||||
if (size > length) {
|
||||
debug_println("size > length");
|
||||
DebugLog("size > length");
|
||||
return false;
|
||||
}
|
||||
if (!validate_section_name(ident)) {
|
||||
debug_println("invalid section name");
|
||||
DebugLog("invalid section name");
|
||||
return false;
|
||||
}
|
||||
KMXPLUS_FPRINTF((stderr, " (header OK)\n")); // newline after section name
|
||||
DebugLog(" (header OK)"); // newline after section name
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
COMP_KMXPLUS_KEYS::valid(KMX_DWORD _kmn_unused(length)) const {
|
||||
KMXPLUS_FPRINTF((stderr, " count: #0x%X\n", this->count));
|
||||
DebugLog(" count: #0x%X\n", this->count);
|
||||
if (header.size < sizeof(*this)+(sizeof(entries[0])*count)) {
|
||||
debug_println("header.size < expected size");
|
||||
DebugLog("header.size < expected size");
|
||||
return false;
|
||||
}
|
||||
for (KMX_DWORD i = 0; i<this->count; i++) {
|
||||
KMXPLUS_FPRINTF((stderr, " #0x%d\n", i));
|
||||
DebugLog(" #0x%d\n", i);
|
||||
const COMP_KMXPLUS_KEYS_ENTRY& entry = this->entries[i];
|
||||
KMXPLUS_FPRINTF((stderr, " vkey\t0x%X\n", entry.vkey));
|
||||
KMXPLUS_FPRINTF((stderr, " mod\t0x%X\n", entry.mod));
|
||||
KMXPLUS_FPRINTF((stderr, " flags\t0x%X\n", entry.flags));
|
||||
DebugLog(" vkey\t0x%X\n", entry.vkey);
|
||||
DebugLog(" mod\t0x%X\n", entry.mod);
|
||||
DebugLog(" flags\t0x%X\n", entry.flags);
|
||||
if (entry.flags & LDML_KEYS_FLAGS_EXTEND) {
|
||||
KMXPLUS_FPRINTF((stderr, " \t Extend: String #0x%X\n", entry.to));
|
||||
DebugLog(" \t Extend: String #0x%X\n", entry.to);
|
||||
} else {
|
||||
KMXPLUS_FPRINTF((stderr, " \t UTF-32:U+%04X\n", entry.to));
|
||||
DebugLog(" \t UTF-32:U+%04X\n", entry.to);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
|
@ -174,12 +163,12 @@ COMP_KMXPLUS_KEYS_ENTRY::get_string() const {
|
|||
bool
|
||||
COMP_KMXPLUS_LOCA::valid(KMX_DWORD _kmn_unused(length)) const {
|
||||
if (header.size < sizeof(*this)+(sizeof(entries[0])*count)) {
|
||||
debug_println("header.size < expected size");
|
||||
DebugLog("header.size < expected size");
|
||||
return false;
|
||||
}
|
||||
// TODO-LDML
|
||||
for(KMX_DWORD i=0; i<this->count; i++) {
|
||||
KMXPLUS_FPRINTF((stderr, " Locale #%d: #0x%X\n", i, this->entries[i].locale));
|
||||
DebugLog(" Locale #%d: #0x%X\n", i, this->entries[i].locale);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -187,49 +176,49 @@ COMP_KMXPLUS_LOCA::valid(KMX_DWORD _kmn_unused(length)) const {
|
|||
bool
|
||||
COMP_KMXPLUS_META::valid(KMX_DWORD _kmn_unused(length)) const {
|
||||
if (header.size < sizeof(*this)) {
|
||||
debug_println("header.size < expected size");
|
||||
DebugLog("header.size < expected size");
|
||||
return false;
|
||||
}
|
||||
KMXPLUS_FPRINTF((stderr, " author:\t#0x%X\n", this->author));
|
||||
KMXPLUS_FPRINTF((stderr, " conform:\t#0x%X\n", this->conform));
|
||||
KMXPLUS_FPRINTF((stderr, " layout:\t#0x%X\n", this->layout));
|
||||
KMXPLUS_FPRINTF((stderr, " normalization:\t#0x%X\n", this->normalization));
|
||||
KMXPLUS_FPRINTF((stderr, " indicator:\t#0x%X\n", this->indicator));
|
||||
KMXPLUS_FPRINTF((stderr, " settings:\t0x%X\n", this->settings));
|
||||
DebugLog(" author:\t#0x%X\n", this->author);
|
||||
DebugLog(" conform:\t#0x%X\n", this->conform);
|
||||
DebugLog(" layout:\t#0x%X\n", this->layout);
|
||||
DebugLog(" normalization:\t#0x%X\n", this->normalization);
|
||||
DebugLog(" indicator:\t#0x%X\n", this->indicator);
|
||||
DebugLog(" settings:\t0x%X\n", this->settings);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
COMP_KMXPLUS_VKEY::valid(KMX_DWORD _kmn_unused(length)) const {
|
||||
KMXPLUS_FPRINTF((stderr, "vkey: count 0x%X\n", this->count));
|
||||
DebugLog("vkey: count 0x%X\n", this->count);
|
||||
if (header.size < sizeof(*this)+(sizeof(entries[0])*count)) {
|
||||
debug_println("header.size < expected size");
|
||||
DebugLog("header.size < expected size");
|
||||
return false;
|
||||
}
|
||||
// TODO-LDML
|
||||
KMXPLUS_FPRINTF((stderr, "TODO: dump vkey"));
|
||||
DebugLog("TODO: dump vkey");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
COMP_KMXPLUS_STRS::valid(KMX_DWORD _kmn_unused(length)) const {
|
||||
KMXPLUS_FPRINTF((stderr, "strs: count 0x%X\n", this->count));
|
||||
DebugLog("strs: count 0x%X\n", this->count);
|
||||
if (header.size < sizeof(*this)+(sizeof(entries[0])*count)) {
|
||||
debug_println("header.size < expected size");
|
||||
DebugLog("header.size < expected size");
|
||||
return false;
|
||||
}
|
||||
for (KMX_DWORD i=0; i<this->count; i++) {
|
||||
KMXPLUS_FPRINTF((stderr, "#0x%X: ", i));
|
||||
DebugLog("#0x%X: ", i);
|
||||
KMX_DWORD offset = entries[i].offset;
|
||||
KMX_DWORD length = entries[i].length;
|
||||
if(offset+((length+1)*2) > header.size) {
|
||||
debug_println("expected end of string past header.size");
|
||||
DebugLog("expected end of string past header.size");
|
||||
return false;
|
||||
}
|
||||
const uint8_t* thisptr = reinterpret_cast<const uint8_t*>(this);
|
||||
const KMX_WCHAR* start = reinterpret_cast<const KMX_WCHAR*>(thisptr+offset);
|
||||
if(start[length] != 0) {
|
||||
debug_println("String not null terminated");
|
||||
DebugLog("String not null terminated");
|
||||
return false;
|
||||
}
|
||||
// TODO-LDML: validate valid UTF-16LE?
|
||||
|
|
@ -237,12 +226,12 @@ COMP_KMXPLUS_STRS::valid(KMX_DWORD _kmn_unused(length)) const {
|
|||
// first print it escaped
|
||||
for(KMX_DWORD j=0; start[j] && j<length; j++) {
|
||||
if (start[j] < 0x7F && start[j] > 0x20) {
|
||||
KMXPLUS_FPRINTF((stderr, "%c", start[j]));
|
||||
DebugLog("%c", start[j]);
|
||||
} else {
|
||||
KMXPLUS_FPRINTF((stderr, " U+%04X ", start[j]));
|
||||
DebugLog(" U+%04X ", start[j]);
|
||||
}
|
||||
}
|
||||
KMXPLUS_FPRINTF((stderr, "\n"));
|
||||
DebugLog("");
|
||||
|
||||
// // now print it as a string
|
||||
// TODO-LDML
|
||||
|
|
@ -255,10 +244,10 @@ COMP_KMXPLUS_STRS::valid(KMX_DWORD _kmn_unused(length)) const {
|
|||
|
||||
bool
|
||||
COMP_KMXPLUS_SECT::valid(KMX_DWORD length) const {
|
||||
KMXPLUS_FPRINTF((stderr, "sect: total 0x%X\n", this->total));
|
||||
KMXPLUS_FPRINTF((stderr, "sect: count 0x%X\n", this->count));
|
||||
DebugLog("sect: total 0x%X\n", this->total);
|
||||
DebugLog("sect: count 0x%X\n", this->count);
|
||||
if (header.size < sizeof(*this)+(sizeof(entries[0])*count)) {
|
||||
debug_println("header.size < expected size");
|
||||
DebugLog("header.size < expected size");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -266,14 +255,14 @@ COMP_KMXPLUS_SECT::valid(KMX_DWORD length) const {
|
|||
bool overall_valid = true;
|
||||
for (KMX_DWORD i = 0; i < this->count; i++) {
|
||||
const COMP_KMXPLUS_SECT_ENTRY& entry = this->entries[i];
|
||||
KMXPLUS_FPRINTF((stderr, "\n#%d: ", i));
|
||||
DebugLog("\n#%d: ", i);
|
||||
if(!validate_section_name(entry.sect)) {
|
||||
KMXPLUS_FPRINTF((stderr, " (invalid section name) \n"));
|
||||
DebugLog(" (invalid section name) ");
|
||||
return false;
|
||||
}
|
||||
KMXPLUS_FPRINTF((stderr, " %X @ %X\n", entry.sect, entry.offset));
|
||||
DebugLog(" %X @ %X\n", entry.sect, entry.offset);
|
||||
if (entry.sect == LDML_SECTIONID_SECT) {
|
||||
debug_println("Invalid nested 'sect'");
|
||||
DebugLog("Invalid nested 'sect'");
|
||||
overall_valid = false;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -282,7 +271,7 @@ COMP_KMXPLUS_SECT::valid(KMX_DWORD length) const {
|
|||
KMX_DWORD entrylength = length - entry.offset;
|
||||
// just validate header
|
||||
if(header_from_bytes(entrydata, entrylength, entry.sect) == nullptr) {
|
||||
KMXPLUS_FPRINTF((stderr, "Invalid header %X", entry.sect));
|
||||
DebugLog("Invalid header %X", entry.sect);
|
||||
overall_valid = false;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -294,18 +283,18 @@ COMP_KMXPLUS_SECT::valid(KMX_DWORD length) const {
|
|||
bool
|
||||
COMP_KMXPLUS_ELEM::valid(KMX_DWORD _kmn_unused(length)) const {
|
||||
if (header.size < sizeof(*this)+(sizeof(entries[0])*count)) {
|
||||
debug_println("header.size < expected size");
|
||||
DebugLog("header.size < expected size");
|
||||
return false;
|
||||
}
|
||||
const COMP_KMXPLUS_ELEM_ENTRY &firstEntry = entries[0];
|
||||
if (firstEntry.length != 0 ) {
|
||||
debug_println("ERROR: elem[0].length != 0");
|
||||
DebugLog("ERROR: elem[0].length != 0");
|
||||
return false;
|
||||
}
|
||||
if (firstEntry.offset + sizeof(COMP_KMXPLUS_ELEM_ELEMENT) > header.size) {
|
||||
// TODO-LDML: change to (firstEntry.offset != 0 )
|
||||
// Blocked by https://github.com/keymanapp/keyman/issues/7404
|
||||
debug_println("ERROR: preposterous elem[0].offset");
|
||||
DebugLog("ERROR: preposterous elem[0].offset");
|
||||
return false;
|
||||
}
|
||||
for (KMX_DWORD e = 1; e < count; e++) {
|
||||
|
|
@ -315,7 +304,7 @@ COMP_KMXPLUS_ELEM::valid(KMX_DWORD _kmn_unused(length)) const {
|
|||
return false;
|
||||
}
|
||||
if (listLength == 0) {
|
||||
debug_println("ERROR: elem[e>0].length == 0");
|
||||
DebugLog("ERROR: elem[e>0].length == 0");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -330,7 +319,7 @@ COMP_KMXPLUS_ELEM::getElementList(KMX_DWORD elementNumber, KMX_DWORD &length) co
|
|||
const COMP_KMXPLUS_ELEM_ENTRY &entry = entries[elementNumber];
|
||||
length = entry.length;
|
||||
if (entry.offset + (entry.length * sizeof(COMP_KMXPLUS_ELEM_ELEMENT)) > header.size) {
|
||||
debug_println("ERROR: !! COMP_KMXPLUS_ELEM::getElementList")
|
||||
DebugLog("ERROR: !! COMP_KMXPLUS_ELEM::getElementList");
|
||||
}
|
||||
// pointer to beginning of elem section
|
||||
const uint8_t *rawdata = reinterpret_cast<const uint8_t *>(this);
|
||||
|
|
@ -349,11 +338,11 @@ COMP_KMXPLUS_ELEM_ELEMENT::get_string() const {
|
|||
bool
|
||||
COMP_KMXPLUS_TRAN::valid(KMX_DWORD _kmn_unused(length)) const {
|
||||
if (header.size < sizeof(*this)+(sizeof(entries[0])*count)) {
|
||||
debug_println("header.size < expected size");
|
||||
DebugLog("header.size < expected size");
|
||||
return false;
|
||||
}
|
||||
// TODO-LDML
|
||||
debug_println("!! More to do here.");
|
||||
DebugLog("!! More to do here.");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -363,22 +352,22 @@ kmx_plus::kmx_plus(const COMP_KEYBOARD *keyboard, size_t length)
|
|||
: keys(nullptr), loca(nullptr), meta(nullptr),
|
||||
sect(nullptr), strs(nullptr), vkey(nullptr), valid(false) {
|
||||
|
||||
KMXPLUS_FPRINTF((stderr, "kmx_plus(): Got a COMP_KEYBOARD at %p\n", keyboard));
|
||||
DebugLog("kmx_plus(): Got a COMP_KEYBOARD at %p\n", keyboard);
|
||||
if (!(keyboard->dwFlags & KF_KMXPLUS)) {
|
||||
KMXPLUS_FPRINTF((stderr, "Err: flags COMP_KEYBOARD.dwFlags did not have KF_KMXPLUS set\n"));
|
||||
DebugLog("Err: flags COMP_KEYBOARD.dwFlags did not have KF_KMXPLUS set");
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
const COMP_KEYBOARD_EX* ex = reinterpret_cast<const COMP_KEYBOARD_EX*>(keyboard);
|
||||
|
||||
KMXPLUS_FPRINTF((stderr, "kmx_plus(): KMXPlus offset 0x%X, KMXPlus size 0x%X\n", ex->kmxplus.dpKMXPlus, ex->kmxplus.dwKMXPlusSize));
|
||||
DebugLog("kmx_plus(): KMXPlus offset 0x%X, KMXPlus size 0x%X\n", ex->kmxplus.dpKMXPlus, ex->kmxplus.dwKMXPlusSize);
|
||||
if (ex->kmxplus.dpKMXPlus < sizeof(kmx::COMP_KEYBOARD_EX)) {
|
||||
debug_println("dwKMXPlus is not past the end of COMP_KEYBOARD_EX");
|
||||
DebugLog("dwKMXPlus is not past the end of COMP_KEYBOARD_EX");
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
if ( ex->kmxplus.dpKMXPlus + ex->kmxplus.dwKMXPlusSize > length) {
|
||||
debug_println("dpKMXPlus + dwKMXPlusSize is past the end of the file");
|
||||
DebugLog("dpKMXPlus + dwKMXPlusSize is past the end of the file");
|
||||
valid = false;
|
||||
return;
|
||||
}
|
||||
|
|
@ -387,7 +376,7 @@ kmx_plus::kmx_plus(const COMP_KEYBOARD *keyboard, size_t length)
|
|||
|
||||
sect = section_from_bytes<COMP_KMXPLUS_SECT>(rawdata+ex->kmxplus.dpKMXPlus, ex->kmxplus.dwKMXPlusSize);
|
||||
if (sect == nullptr) {
|
||||
KMXPLUS_FPRINTF((stderr, "kmx_plus(): 'sect' did not validate\n"));
|
||||
DebugLog("kmx_plus(): 'sect' did not validate");
|
||||
valid = false;
|
||||
} else {
|
||||
valid = true;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue