Mi az a bináris szerkesztő?

A bináris szerkesztő olyan eszköz, amellyel egy fájl 16-os számrendszerű vagy ASCII nézetben, közvetlenül szerkeszthető. Míg egy hagyományos szövegszerkesztő a „karakterláncokat” kezeli, addig a bináris szerkesztő a fájl „nyers bájtsorozatához” fér hozzá, és bármely pozícióban bitet vagy bájtot módosíthatunk.

Szoftveranalízishez, adatmentéshez vagy protokollvizsgálathoz megkerülhetetlen eszköz. Grafikus alkalmazások közül a HxD vagy a Binary Ninja a legismertebb, de a célom most az volt, hogy egyetlen HTML-fájlban, csupán böngészőben futó bináris szerkesztőt készítsek.


Megvalósítási irányelvek

  • Teljesen kliensoldali működés (nincs külső adatküldés)
  • A FileReader API-val olvassa be a helyi fájlokat
  • Bal oldalon a hexadecimális (hex), jobb oldalon az ASCII nézet jelenik meg
  • Kattintás után szerkesztő módba lép, és közvetlenül átírható az érték
  • A módosított cellákat piros színnel emeli ki
  • Hex és ASCII szerkesztő mód között válthatunk
  • A módosított tartalom fájlként letölthető

Elakadások és javítások

1. Elcsúszó szerkesztési keret

Az első verzióban a kijelölt cella köré húzott sárga keret enyhén félrecsúszott, emiatt furcsán nézett ki. A gond az volt, hogy a CSS line-height és a flex elrendezés miatt a megjelenített karakter és a keret referencia pontja nem esett egybe. Monospace betűtípusra támaszkodom, de a böngészők eltérő alapvonalat használhatnak, így a keret fel- vagy lecsúszott.

A megoldás az lett, hogy vertical-align: middle stílust adtam, és display: inline-block-ra váltottam, így a magasság szépen illeszkedett.

.hex-cell.editing {
  outline: 2px solid yellow;
  vertical-align: middle;
}

2. Az ESC billentyű karaktert ír be

Kezdetben, ha szerkesztés közben megnyomtam az ESC-et, olyan karakterek kerültek be a cellába, mint „EE”.

Ennek az volt az oka, hogy nem kezeltem külön a keydown eseményt, így a böngésző a lenyomott billentyű kódját az inputfeldolgozásnak adta át. A normál bevitelnél csak 0–9 és A–F karakterekre számítottam, de az Escape billentyűnek is van kódja (keyCode=27, az újabb szabvány szerint key="Escape"), ami „E”-ként értelmeződött, így dupla E került a cellába.

A megoldás: a keydown eseménynél külön ellenőrzöm, ha Escape a lenyomott gomb, megszakítom a szerkesztést, és letiltom, hogy a billentyű az eredeti inputútvonalra kerüljön.

document.addEventListener("keydown", e => {
  if (e.key === "Escape") {
    cancelEdit();
    e.preventDefault(); // ne fusson végig az alapértelmezett bevitel
  }
});

Így az ESC már kizárólag „szerkesztés megszakítása” funkciót lát el, nem ír be karaktert.

3. Új fájl betöltésekor megmaradó piros jelölések

Ha szerkesztés után új fájlt töltöttem be, a korábbi piros kiemelések ott maradtak.

A bibi az volt, hogy a módosított cellákat nyilvántartó tömböt és állapotot nem inicializáltam újra fájlbetöltéskor. Hiába töröltem a megjelenített rácsot, a belső „változott-e” jelzők megmaradtak, ezért az új fájlon is pirosan világítottak.

Megoldásként a fájlbeolvasás elején meghívtam a clearModifiedState() függvényt, amely mindent visszaállít alaphelyzetbe.

4. Hex/ASCII módváltás

Az első változatban egyszerre lehetett a hexet és az ASCII-t szerkeszteni, ami zavart okozott: ugyanazt a bájtot két külön útvonalon is át lehetett írni. ASCII bevitelkor azonnal frissült a hex nézet, de félig beírt karaktereknél átmenetileg inkonzisztens állapot jelent meg.

A rend kedvéért külön üzemmódot vezettem be, amelyet egy legördülő menüből lehet kiválasztani, és alapértelmezetten a hex szerkesztést hagytam meg. Így a felhasználó mindig tudja, épp milyen formátumban ír, a szinkronizáció pedig jóval egyszerűbb lett.


Kódrészlet

A tényleges szerkesztési logika valahogy így fest:

function applyEdit(offset, newValue) {
  if (mode === "hex") {
    buffer[offset] = parseInt(newValue, 16);
  } else {
    buffer[offset] = newValue.charCodeAt(0);
  }
  markModified(offset);
  render();
}

A markModified(offset) egyszerűen hozzárendeli a piros kiemeléshez szükséges osztályt, ha az új érték eltér az eredetitől.


Összegzés

Az elkészült böngészős bináris szerkesztő offline is működik, és a biztonság szempontjából is „teljesen kliensoldali” megoldás maradt.

  • Ha csak apró bináris módosítást kell végrehajtani
  • Ha olyan környezetben vizsgálódsz, ahol nem telepíthetsz dedikált alkalmazást
  • Ha oktatási célból szeretnéd intuitívan megérteni a bájtsorozatokat

Ilyen helyzetekben remélhetőleg jól használható lesz.