Egy Excel munkafüzet hordozhat EMF és WMF képeket, és a hagyományos mód annak kirajzolására az, hogy a bájtfolyamot az operációs rendszer metafájl-lejátszójára bízzák. Ez egy döntés, amelyet érdemes közvetlenül megnézni: egy metafájl egy grafikai API szerializált parancsfolyama, és egy visszajátszása azt jelenti, hogy egy e-mailen érkező fájl hajtja a grafikusillesztőt. A HotXLS a másik utat választja. A XLSDecodeVectorScene maga elemzi a metafájlt, szigorúan ellenőrzi a fejlécet, minden rekordméretet, a deklarált rekordösszesítést és a fájlvégi rekord pontos helyét, laposan elutasítja az escape rekordokat, és egy TXLSVectorScene primitív rajzolási parancsokat ad vissza, amelyeket a Canvas és SVG backendek a saját kódjukon keresztül játszanak vissza. Illesztővisszajátszás egyetlen ponton sem fordul elő
Az alku a lefedettség a befoglalásért. Egy téglalap-orientált parancsfehérlista nem reprodukál minden metafájlt, amelyet egy tervező előállíthat, tehát a jelenet megmondja, hány rajzolási rekordot nem tudott ábrázolni, és a hívó dönt arról, mit tesz. Egy kiszolgálói folyamat számára, amely olyan dokumentumokat renderel, amelyeket nem ő hozott létre, az az alku a helyes irányú
Miért rosszul illik a metafájl-visszajátszás a nem megbízható bemenethez?
Mert a formátum nem kép, hanem program. Egy EMF rekordfolyam eszközkontextus állapotveremet manipulál, objektumokat foglal le és választ ki egy handletáblából, és hordozhat olyan escape rekordokat, amelyek hasznos terhe az eszközillesztőhöz továbbítódik. A visszajátszása olyan utakat gyakorol a platform grafikai veremében, amelyeket azzal a feltételezéssel írtak, hogy a metafájl együttműködő alkalmazástól származik ugyanazon a gépen. Amikor a bemenet egy táblázatmelléklet, az a feltételezés elvész, és a táblázatfüggvénytáron belüli gondosság semmilyen mennyisége sem segít, mert a függvénytár nem az a komponens, amely az elemzést végzi
Ez ugyanaz az érvelés, amely a tárolóréteget kormányozza. Egy munkafüzet ZIP archívum, és a HotXLS a központi könyvtárát ellenőrzi, nem a deklarált offsetekbe bízva, ahogyan azt a ZIP end-of-central-directory ellenőrzési cikk leírja. A metafájlhasznos terhek ugyanazon probléma következő rétege
Mit ellenőriz a dekódoló, mielőtt bármit rajzolna
Az ellenőrzés strukturális, és előre megtörténik, mert egy olyan elemző, amely elkezdi a rajzolást, és menet közben ellenőriz, már cselekedett olyan adatokon, amelyeket nem erősített meg. A fejlécnek szigorúan, nem hihetően kell egyeznie. Minden rekordnak olyan méretet kell deklarálnia, amely a maradék pufferbe belefér, és elég nagy a saját rögzített mezőihez. A fejléc által deklarált rekordszámnak egyeznie kell a ténylegesen jelen lévő rekordokkal. A fájlvégi rekordnak pontosan ott kell ülnie, ahol a folyam ér véget, nem csupán valahol a közelében, ami bezárja a záró szemét csínát, amely egy érvényes kép mögé rejt egy második hasznos terhet
A struktúrán túl a dekódoló a szemantika terén zártan hibázik. Az escape rekordok elutasításra kerülnek, nem kihagyásra. Egy állapotot változtató rekord, amelyet a dekódoló nem modellez, a dekódolás megbukását okozza, nem figyelmen kívül hagyásra kerül, mert egy állapotváltozás figyelmen kívül hagyása azt jelenti, hogy minden későbbi rajzolási parancs olyan állapotban hajtódik végre, amelyet a fájl nem kért, és az eredmény olyan kép, amely senki által előre nem látható módon rossz. A támogatott parancskészleten kívüli rajzolási rekordok más kérdés: azokat megszámolják és kihagyják, mert egy hiányzó alak látható, jelenthető rés, nem csendes rongálás
A korlátok a formátumszerződés részei
A vektorformátumoknak megvan a kitömörítési bombának a saját változata. Néhány kilobájt rekord százzmilliós pontszámú vonalláncokat deklarálhat, vagy olyan képet, amelynek deklarált méretei terabájtokká szorzódnak. A határoknak ezért explicit konstansoknak kell lenniük, nem pedig annak, amivel a gép éppen túléli
// Az lxVectorScene-ből: a dekódolási korlát, kimondva, nem sugallva
XL_VECTOR_MAX_RECORDS = 1000000;
XL_VECTOR_MAX_HANDLES = 4096;
XL_VECTOR_MAX_DC_DEPTH = 32;
XL_VECTOR_MAX_COMMANDS = 100000;
XL_VECTOR_MAX_POINTS_PER_RECORD = 100000;
XL_VECTOR_MAX_TOTAL_POINTS = 2000000;
XL_VECTOR_MAX_TEXT_CHARS = 4096;
XL_VECTOR_MAX_TOTAL_TEXT_CHARS = 1000000;
XL_VECTOR_MAX_IMAGE_SIDE = 8192;
XL_VECTOR_MAX_IMAGE_PIXELS = 32 * 1024 * 1024;
XL_VECTOR_MAX_IMAGE_BYTES = 64 * 1024 * 1024;
XL_VECTOR_MAX_COORD = 1000000000;
Kettő közülük megjegyzést érdemel. Az eszközkontextus 32-es mélységi korlátja azért létezik, mert a SaveDC és RestoreDC rekordok egymásba ágyazódnak, és egy kiegyensúlyozatlan folyam örökké tolhat; 32 nagylelkű a valós metafájlokra és olcsó érvényesíteni. A koordinátakorlát azért létezik, mert a koordináták transzformációt táplálnak, és az egész tartomány határaihoz közeli érték végtelenné vagy körbefordulóvá vált transzformált eredményt ad, amely után minden lefelé irányuló befoglaló doboz számítás értelmetlen. A koordináták elemzéskori szorítása sokkal könnyebben átgondolható, mint a geometria minden fogyasztójának megvédése
A jelenet használata
A dekódoló egy Ön birtokába kerülő objektumot ad vissza, parancsszámot, névleges méretet, és azoknak a rajzolási rekordoknak a számát, amelyeket nem választott ábrázolásra
uses
lxVectorScene;
var
Scene: TXLSVectorScene;
Error: WideString;
I: Integer;
begin
// A Data hordozza a munkafüzetből vett nyers képhasznos terhet
if not XLSDecodeVectorScene(Data, xlsvfEmf, Scene, Error) then
begin
// Elutasítva: fejléc, határok, összesítések, EOF hely vagy korlát
LogReject('metafile rejected: ' + Error);
Exit;
end;
try
if Scene.SkippedDrawRecords > 0 then
LogWarning(Format('%d drawing records outside the safe subset',
[Scene.SkippedDrawRecords]));
for I := 0 to Scene.Count - 1 do
case Scene.Commands[I].Kind of
xlsvcRectangle: DrawRect(Scene.Commands[I]);
xlsvcEllipse: DrawEllipse(Scene.Commands[I]);
xlsvcPolyline,
xlsvcPolygon,
xlsvcBezier: DrawPath(Scene.Commands[I]);
xlsvcText: DrawText(Scene.Commands[I]);
xlsvcImage: DrawImage(Scene.Commands[I]);
end;
finally
Scene.Free;
end;
end;
A parancsrekord mindent hordoz, amire egy backendnek szüksége van, és semmit, ami eszközt igényelne: toll jelenlétét, színét, szélességét és stílusát; ecset jelenlétét és színét; a geometriát; és szövegre a karakterláncot, a betűnevet, a méretet, a stílusokat és az igazítást. Az teszi ugyanazt a jelenetet használhatóvá a képernyővászon-renderelő és az SVG író számára egyaránt, és ez az ok, amiért a vektorút nem ágazik szét előnézet és export között. A munkalaptartalom képernyőrenderelését általában a egyéni VCL rács renderelési cikk tárgyalja
Egy kép elutasítása nem rongálja a munkafüzetet
Ennek a tervnek fontos tulajdonsága az, hogy egy elutasított dekódolás csak a renderelést érinti. Az eredeti hasznos teher a modellben marad, tehát egy megnyitott és újból mentett munkafüzet a metafájlképeit bájtonként viszi ki, akár tudta őket rajzolni a biztonságos dekódoló, akár nem. A meglévő határolt raszteres út is elérhető marad tartalékként. Más szóval a szigorú elemző azt kapuzza, ami végrehajtódik, nem azt, ami megőrződik, és ez az a megkülönböztetés, amely lehetővé teszi, hogy egy biztonsági motivációjú változtatás adatvesztéssé válás nélkül kerüljön kiadásra
A rajzobjektumok kezelése általában, beleértve az objektummodell azon részeit, amelyek érintetlenül élik túl az oda-vissza utakat, a diagramok, képek és rajzok cikkben van tárgyalva
Hol hagyja ezt egy kiszolgálói telepítést
Ha felhasználók által feltöltött munkafüzeteket renderel szolgáltatásban, a gyakorlati álláspont most védhető: a metafájlképeket olyan kód elemzi, amelyet auditálhat, olyan konstansok határolnak, amelyeket elolvashat, és soha nem kerül grafikusillesztőre bízásra. Az őszinte megjegyzés a lefedettség. A rajzeszközök által előállított összetett metafájlok a kihagyott rekord számlálójának fognak nekimenni, és arra a válasz az, hogy a számlálót hozza felszínre, nem pedig csendben szélesítse a fehérlistát. Egy kép, amely részben renderel és ezt elmondja, támogatási beszélgetés; egy kép, amely rosszul renderel és nem szól, ügyfél hibajelentés
A HotXLS natívan kezeli az XLS, XLSX, ODS és CSV formátumokat Delphi és C++Builder alatt Excel telepítése nélkül, és ugyanaz a határolt elemzési filozófia fut át a tároló-, képlet- és rajzrétegein. A formátum- és biztonsági részletek a HotXLS Delphi spreadsheet component terméklapon találhatók