Excel radna knjiga može nositi EMF i WMF slike, i uobičajeni način da se jedna nacrta jest predati tok bajtova metafile reproduktoru operativnog sustava. To je odluka vrijedna izravnog pogleda: metafile je serijalizirani tok naredbi za grafički API, i reproducirati jedan znači dopustiti da datoteka koja je stigla e-poštom upravlja grafičkim upravljačkim programom. HotXLS uzima drugi put. XLSDecodeVectorScene sama raščlanjuje metafile, provjerava zaglavlje, svaku veličinu zapisa, deklarirani ukupni broj zapisa i točan smještaj zapisa kraja datoteke, bez razmatranja odbija zapise escapovanja i vraća TXLSVectorScene primitivnih naredbi crtanja koje pozadine Canvas i SVG ponavljaju kroz vlastiti kôd. Reprodukcija upravljačkim programom ne uključuje se ni u jednom trenutku
Trgovina je pokrivenost za ograničavanje. Popis dopuštenog naredbi orijentiranih na pravokutnike neće reproducirati svaki metafile koji dizajner može stvoriti, pa scena javlja koliko crtajućih zapisa nije mogla predstaviti, a pozivatelj odlučuje što s tim. Za poslužiteljski proces koji prikazuje dokumente koje nije stvorio, ta trgovina ispravan je smjer
Zašto reprodukcija metafilea loša prilika za nepouzdani unos?
Zato što format nije slika, nego program. Tok zapisa EMF upravlja stogom stanja konteksta uređaja, dodjeljuje i odabire objekte iz tablice handlea, i može nositi zapise escapovanja čiji se teret prosljeđuje upravljačkom programu uređaja. Reprodukcija vježba putove u grafičkom stogu platforme napisane uz pretpostavku da je metafile došao od surađujuće aplikacije na istom stroju. Kada je unos prilog proračunske tablice, ta pretpostavka nestaje, i nimalo pažnje unutar biblioteke proračunske tablice ne pomaže jer biblioteka nije komponenta koja raščlanjuje
To je isto razmišljanje koje upravlja slojem spremnika. Radna knjiga je ZIP arhiv, i HotXLS provjerava njezin središnji direktorij umjesto da vjeruje deklariranim pomacima, kao što je opisano u članku o provjeri ZIP kraja središnjeg direktorija. Tereti metafilea sljedeći su sloj istog problema
Što dekoder provjerava prije nego što išta nacrta
Provjera je strukturna i događa se unaprijed, jer parser koji počne crtati i provjerava usput već je postupao po podacima koje nije provjerio. Zaglavlje se mora poklapati strogo, a ne uvjerljivo. Svaki zapis mora deklarirati veličinu koja stane unutar preostalog međuspremnika i dovoljno je velika za vlastita fiksna polja. Broj zapisa koji zaglavlje deklarira mora se poklapati sa zapisima koji stvarno postoje. Zapis kraja datoteke mora sjesti točno tamo gdje tok završava, ne samo negdje blizu, čime se zatvara trik pratećeg smeća koje skriva drugi teret iza valjane slike
Izvan strukture, dekoder je fail-closed na semantici. Zapisi escapovanja odbijaju se, ne preskaču. Zapis koji mijenja stanje, a koji dekoder ne modelira, uzrokuje pad dekodiranja umjesto da se ignorira, jer ignoriranje promjene stanja znači da se svaka sljedeća crtajuća naredba izvršava u stanju koje datoteka nije tražila, i rezultat je slika pogrešna na način koji nitko ne može predvidjeti. Crtajući zapisi izvan podržanog skupa naredbi drugo su pitanje: ti se broje i preskaču, jer je nedostajući oblik vidljiv i javljiv jaz, a ne tiho oštećenje
Proračuni dio su ugovora formata
Vektorski formati imaju vlastitu verziju bombe dekompresije. Nekoliko kilobajta zapisa može deklarirati polilinije sa stotinama milijuna točaka ili sliku čije se deklarirane dimenzije množe u terabajte. Granice dakle moraju biti izričite konstante umjesto onoga što stroj slučajno preživi
// Iz lxVectorScene: proračun dekodiranja, izrečen umjesto podrazumijevan
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;
Dvije od njih zaslužuju napomenu. Dubinska granica konteksta uređaja od 32 postoji jer se zapisi SaveDC i RestoreDC gnijezde, i neuravnotežen tok može gurati zauvijek; 32 je darežljivo za stvarne metafile i jeftino za provoditi. Granica koordinata postoji jer koordinate hrane transformaciju, i vrijednost blizu granica cjelobrojnog raspona proizvodi pretvoreni rezultat koji je ili beskonačan ili se omota, nakon čega je svaki izračun okvirnog okvira nizvodno besmislica. Stiskanje koordinata u trenutku raščlambe mnogo je lakše razumjeti nego braniti svakog potrošača geometrije
Uporaba scene
Dekoder predaje objekt koji je vaš, broj naredbi, nominalnu veličinu i broj crtajućih zapisa koje je odabrao ne predstaviti
uses
lxVectorScene;
var
Scene: TXLSVectorScene;
Error: WideString;
I: Integer;
begin
// Data drži sirovi teret slike uzet iz radne knjige
if not XLSDecodeVectorScene(Data, xlsvfEmf, Scene, Error) then
begin
// Odbijeno: zaglavlje, granice, ukupni brojevi, smještaj EOF-a ili proračun
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;
Zapis naredbe nosi sve što pozadina treba i ništa što zahtijeva uređaj: prisutnost pera, boju, širinu i stil; prisutnost kista i boju; geometriju; i za tekst niz, ime fonta, veličinu, stilove i poravnanje. To je ono što istu scenu čini upotrebljivom i za prikazivač canvasa na zaslonu i za pisca SVG-a, i razlog je što se vektorski put ne razdvaja između pretpregleda i izvoza. Prikazivanje sadržaja radnog lista na zaslonu općenito pokriveno je u članku o prikazivanju u prilagođenoj VCL mreži
Odbijanje slike ne oštećuje radnu knjigu
Važno svojstvo ovog dizajna jest da odbijeno dekodiranje pogađa samo prikazivanje. Izvorni teret ostaje u modelu, pa radna knjiga koja se otvori i ponovno spremi nosi svoje slike metafilea van bajt po bajt, bio li ili ne bio sigurni dekoder u stanju nacrtati ih. Postojeći ograničeni rastrovani put također ostaje dostupan kao povratak. Drugim riječima, strogi parser ograničava što se izvršava, ne što se čuva, a to je razlika koja dopušta promjenu motiviranu sigurnošću da se ispusti bez pretvaranja u promjenu koja gubi podatke
Rukovanje crtajućim objektima općenito, uključujući dijelove modela objekata koji prežive povratne putanje netaknutima, pokriveno je u članku o grafikonima, slikama i crtežima
Gdje ovo ostavlja poslužiteljsko raspoređivanje
Ako prikazujete radne knjige poslane od korisnika u servisu, praktičan je položaj sada obranjiv: slike metafilea raščlanjuje kôd koji možete pregledati, ograničen konstantama koje možete pročitati, i nikad se ne predaje grafičkom upravljačkom programu. Pošteno upozorenje jest pokrivenost. Složeni metafilei proizvedeni crtajućim alatima pogodit će brojač preskočenih zapisa, i odgovor na to jest izvesti brojač na površinu umjesto tiho širiti popis dopuštenog. Slika koja se prikaže djelomično i to kaže razgovor je podrške; slika koja se prikaže pogrešno i ništa ne kaže izvješće je o grešci od kupca
HotXLS rukuje XLS, XLSX, ODS i CSV izvorno u Delphiju i C++Builderu bez instaliranog Excela, i ista filozofija ograničene raščlambe prolazi kroz njegove slojeve spremnika, formula i crteža. Pojedinosti formata i sigurnosti navedene su na stranici proizvoda HotXLS Delphi spreadsheet component