Excel darbo knyga gali nešti EMF ir WMF paveikslėlius, ir įprastas būdas vieną piešti yra perduoti baitų srautą operacinės sistemos metafailų grotuvui. Tas sprendimas verta žiūrėti tiesiai: metafailas yra serijizuota grafikos API komandų srautas, o jo atkūrimas reiškia, kad el. paštu atkeliavęs failas valdo grafikos tvarkyklę. HotXLS eina kitu keliu. XLSDecodeVectorScene pati analizuoja metafailą, tikrina antraštę, kiekvieną įrašo dydį, deklaruotą įrašų visumą ir tikslų failo pabaigos įrašo išdėstymą, kategoriškai atmeta escape įrašus ir grąžina TXLSVectorScene su pirminėmis braižymo komandomis, kurias Canvas ir SVG posistemiai atkuria per savą kodą. Jokio tvarkyklės atkūrimo nėra nė viename taške
Sandauga yra dengimas už izoliaciją. Stačiakampių orientuota komandų baltoji sąrašo dalis neatkurs kiekvieno dizainerio sukuriamo metafailo, todėl scena praneša, kiek braižymo įrašų ji negalėjo atvaizduoti, o iškviečiantysis nusprendžia, ką dėl to daryti. Serverio procesui, atvaizduojančiam dokumentus, kurių jis pats nesukūrė, ta sandauga yra teisinga kryptimi
Kodėl metafailų atkūrimas netinka nepatikimai įvečiai?
Nes formatas nėra paveikslas — jis yra programa. EMF įrašų srautas valdo įrenginio konteksto būsenų krūvą, išskiria ir pasirenka objektus iš rankenėlių lentelės ir gali nešti escape įrašus, kurių turinys perduodamas įrenginio tvarkyklei. Jo atkūrimas pratina kelius platformos grafikos krūvoje, parašytus manydami, kad metafailas atkeliavo iš bendradarbiaujančios tos pačios mašinos programos. Kai įvestis yra skaičiuoklės priedas, ta prielaida dingsta, ir jokios atsargybės skaičiuoklės bibliotekoje nepadeda, nes biblioteka nėra komponentė, atliekanti analizavimą
Tas pats samprotavimas valdo konteinerio sluoksnį. Darbo knyga yra ZIP archyvas, ir HotXLS tikrina jos centrinį katalogą, o ne pasitiki deklaruotais poslinkiais, kaip aprašyta ZIP centrinio katalogo pabaigos tikrinimo straipsnyje. Metafailų turiniai yra kita tos pačios problemos sluoksnis
Ką dekoderis patikrina prieš piešdamas bet ką
Patikra yra struktūrinė ir vyksta iš anksto, nes analizatorius, pradedantis piešti ir tikrinantis einant, jau yra veikęs pagal duomenis, kurių nepatvirtino. Antraštė privalo atitikti griežtai, o ne tikėtinai. Kiekvienas įrašas privalo deklaruoti dydį, telpantį likusiame buferyje ir pakankamai didelį savo fiksuotiems laukams. Įrašų skaičius, kurį deklaruoja antraštė, privalo atitikti faktiškai esančius įrašus. Failo pabaigos įrašas privalo sėdėti tiksliai ten, kur baigiasi srautas, o ne tik kažkur netoli — tai uždaro galinio šiukšlių gudrybę, slepiančią antrą turinį už teisėto paveikslo
Už struktūros dekoderis yra saugiai nepavykstantis semantikoje. Escape įrašai atmetami, o ne praleidžiami. Būseną keičiantis įrašas, kurio dekoderis nemodeliuoja, priverčia dekodavimą nepavykti, o ne būti ignoruotam, nes būsenos pokyčio ignoravimas reiškia, kad kiekviena tolesnė braižymo komanda vykdoma būsenoje, kurios failas neprašė, o rezultatas yra paveikslas, neteisingas taip, kaip niekas negali nuspėti. Braižymo įrašai už palaikomų komandų rinkinio ribų yra kitas reikalas: tie skaičiuojami ir praleidžiami, nes dingusi forma yra matoma, pranešama spraga, o ne tyli sugadinimas
Biudžetai yra formato sutarties dalis
Vektoriniai formatai turi savo išglaudinimo bombos versiją. Keli kilobaitai įrašų gali deklaruoti polilinijas su šimtais milijonų taškų arba atvaizdą, kurio deklaruoti matmenys sudaugėja į terabaitus. Ribos todėl turi būti aiškios konstantos, o ne tai, ką mašina atsitiktinai išgyvena
// Iš lxVectorScene: dekodavimo biudžetas, išsakyta, o ne numanyta
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;
Dvi iš jų nusipelno pastabos. Įrenginio konteksto gylio riba 32 egzistuoja todėl, kad SaveDC ir RestoreDC įrašai vidiniai, o nesubalansuotas srautas gali stumti amžinai; 32 yra dosnu tikriems metafailams ir pigu priverstinai taikyti. Koordinačių riba egzistuoja todėl, kad koordinatės maitina transformaciją, o reikšmė prie sveikųjų intervalo ribų duoda transformuotą rezultatą, kuris arba begalinis, arba apsiverčia, po ko kiekvienas tolesnis ribinio langelio skaičiavimas yra beprasmis. Koordinačių ribojimas analizės metu daug lengviau suvokiamas nei kiekvieno geometrijos vartotojo gynyba
Scenos naudojimas
Dekoderis grąžina objektą, kuris priklausys jums, komandų skaičių, vardinį dydį ir braižymo įrašų, kurių nusprendė neatvaizduoti, skaičių
uses
lxVectorScene;
var
Scene: TXLSVectorScene;
Error: WideString;
I: Integer;
begin
// Data laiko žalią paveikslo turinį, paimtą iš darbo knygos
if not XLSDecodeVectorScene(Data, xlsvfEmf, Scene, Error) then
begin
// Atmesta: antraštė, ribos, visumos, EOF išdėstymas arba biudžetas
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;
Komandų įrašas neša viską, ko reikia posistemiui, ir nieko, kas reikalautų įrenginio: pieštuko buvimą, spalvą, storį ir stilių; teptuko buvimą ir spalvą; geometriją; o tekstui — eilutę, šrifto vardą, dydį, stilius ir lygiavimą. Būtent todėl ta pati scena naudotina ir ekrano drobės atvaizduotojo, ir SVG rašyklio, ir todėl vektorinis kelias nesiskiria tarp peržiūros ir eksporto. Darbalapio turinio atvaizdavimas ekrane apskritai dengiamas pasirinktinio VCL tinklelio atvaizdavimo straipsnyje
Paveikslo atmetimas nesugadina darbo knygos
Svarbi šio projekto savybė yra ta, kad atmestas dekodavimas veikia tik atvaizdavimą. Pradinis turinys lieka modelyje, todėl darbo knyga, atidaryta ir vėl įrašyta, išneša savo metafailo paveikslėlius baitas po baito, ar saugus dekoderis galėjo juos piešti, ar ne. Esamas ribotas rastrinis kelias taip pat lieka prieinamas kaip atsarga. Kitaip tariant, griežtas analizatorius užtveria tai, kas vykdoma, o ne tai, kas išsaugoma — ta išskirtis leidžia saugumo motyvuotam pakeitimui išvykti nesivertus duomenų praradimo pakeitimu
Braižymo objektų tvarkymas apskritai, įskaitant objektų modelio dalis, išgyvenančias abipusius perėjimus nepaliestas, dengiamas diagramų, atvaizdų ir braižinių straipsnyje
Kur tai palieka serverio diegimą
Jeigu atvaizduojate vartotojų įkeliamas darbo knygas tarnyboje, praktinė padėtis dabar ginama: metafailo paveikslėliai analizuojami kodo, kurį galite audituoti, ribojami konstantų, kurias galite skaityti, ir niekada neperduodami grafikos tvarkyklei. Sąžininga išlyga yra dengimas. Kompleksiški braižymo įrankių pagaminti metafailai pasieks praleistų įrašų skaitiklį, o atsakymas į tai — iškelti skaitiklį į viršų, o ne tyliai platinti baltąjį sąrašą. Paveikslas, atvaizduotas iš dalies ir tai pasakantis, yra palaikymo pokalbis; paveikslas, atvaizduotas neteisingai ir nieko nesakantis, yra kliento klaidos pranešimas
HotXLS tvarko XLS, XLSX, ODS ir CSV savai Delphi ir C++Builder aplinkose be įdiegto Excel, ir ta pati ribotos analizės filosofia eina per jo konteinerio, formulių ir braižymo sluoksnius. Formato ir saugumo detalės išvardytos HotXLS Delphi spreadsheet component produkto puslapyje