Objavljeno: 28.5.2024 | Avtor: Matej Huš | Monitor Junij 2024

Združljivost s preteklostjo

Da nova koda temelji na desetletja stari, ni zgolj oguljen stavek, temveč nujno potrebna značilnost. Novi in stari sistemi morajo biti sposobni komunicirati, za kar je često edina možnost, da pri gradnji novih sistemov namerno upoštevamo delovanje starih, vključno s hrošči in z nelogičnostmi. Združljivost za nazaj prežema vse pore razvoja računalniške opreme, občasno pa pokuka izpod pokrova do končnega uporabnika.

Excel vsebuje fiktivni datum 29. 2. 1900, da je bil ob izidu združljiv z Lotusom 1-2-3, ta pa z Visicalcom.

Da leto 1900 ni bilo prestopno, se danes učijo že v osnovni šoli in tudi sredi 80. let prejšnjega stoletja je bilo to splošno znano dejstvo. Ko so leta 45 pred našim štetjem uvedli julijanski koledar, je imelo vsako četrto leto dan več, s čimer so upoštevali, da Zemlja okrog Sonca potuje nekoliko dlje kot 365 dni. Sončno leto traja 365,2422 dneva, zato se je zdel četrtinski približek dovolj dober za dogledno prihodnost. Tako je bilo tudi poldrugo tisočletje, vse do leta 1582, ko se je nabralo za 10 dni napake. Tedaj je 4. oktobru 1582 sledil 15. oktober, hkrati pa so koledar malce spremenili. Okrogla leta, ki se končajo z dvema ničlama (1700, 1800, 1900) ne bodo več prestopna, razen če so deljiva tudi s 400 (1600, 2000). S tem so v 400 letih odstranili tri prestopne dni in takšen koledar bo verno sledil plesu Zemlje še tisočletja.

Excel in prestopna leta

Hkrati na večini računalnikov domuje program, ki tega ne ve. Microsoft Excel v vseh različicah, od 2.0 iz leta 1987 – na Windows je začel izhajati z oznako 2.0, prva pa je bila za Macintosh – do čisto novega Excela 365 verjame, da je 29. februar 1900 obstajal. Ker Excel začenja šteti datume s 1. 1. 1900, ki ima oznako 1, je torej številčna vrednost 60 pripisana dnevu, ki ne obstaja. Še bolj zanimivo je, da prihodnost Excel pozna, saj 29. februar 2100 ne obstaja in tako pravilno naprej vse do leta 9999, ko se njegova epoha konča. Posledic v praksi skorajda ni. Karkoli izračunavamo po 1. marcu 1900, bo v Excelu pravilno, medtem ko bodo dnevi pred tem zamaknjeni za en dan. To je hrošč, ki je dobro znan, zato veliko težav ne povzroča. A zakaj vztraja?

Odgovor na vprašanje se glasi združljivost za nazaj (backwards compatibility), ki ji Microsoft posveča veliko pozornosti, in je v resnici dvoplasten. Microsoft hrošča v novejših izdajah ne popravi, ker bi s tem pokvaril to združljivost. Tudi v najnovejših različicah Excela lahko odpremo zelo stare delovne zvezke, pa bodo formule delovale pravilno, ker so ostale enake. Seveda so se vmes pojavile nove, a stare ostajajo nespremenjene. Če v kateri od formul odkrijejo resnega hrošča, bo Microsoft napisal novo in jo poimenoval drugače, stare pa bodo ostale enake in delujoče (razen v zelo redkih primerih, ko jih bodo odstranili). Takih primerov ni tako malo.

Če so novi izdelki preveč podobni starim, so nezanimivi. Če so preveč drugačni, so strašljivi in nepriljubljeni. Ravno pravo kombinacijo novega in starega pa omogoča združljivost za nazaj.

Za vajo lahko pomislimo, kako bi Microsoft lahko odpravil datumskega hrošča in kaj bi to povzročilo. Bodisi bi začetek epohe (torej dan 1) prestavil na 2. 1. 1900 bodisi bi se zaporedna številka vseh datumov po 28. 2. 1900 zmanjšala za 1. Nobena možnost ni elegantna in obe prinašata zelo resne posledice, da bi se datumi in z njimi povezane operacije v novi inačici izračunavali drugače kakor v stari. Slabost vztrajanja pri hrošču pa je samo ena in dobro znana: delo z datumi pred 1. marcem 1900.

Naivno bi pomislili, da Microsoft leta 1987 tega pač ni vedel oziroma na izjemo ni bil pozoren, a to ne drži. V Redmondu so že tedaj zelo dobro razumeli koledarje. Že takrat so želeli združljivost za nazaj, in sicer s programom Lotus 1-2-3, ki je bil zelo priljubljen in s katerim je Excel tekmoval. Leta 1983 je izšla njegova prva izdaja, ki je že imela tega hrošča.

A tudi pri Lotusu niso bili nevedni, temveč so se ozirali še dlje v preteklost. Lotus 1-2-3 je tega istega hrošča prav tako uvedel namerno, in sicer da je zagotovil združljivost s programom VisiCalc iz leta 1979. Tega je podjetje VisiCorp izdalo za Apple II in je ključno prispeval k razširjenosti platforme, dokler ga leta 1983 ni zasenčil prav Lotus 1-2-3. Zakaj je VisiCalc pred 45 leti napačno vključil 29. februar 1900, je izgubljeno v zgodovini. Ena izmed razlag je, da so na to posebnost gregorijanskega koledarja preprosto pozabili, ker ni bila aktualna že 79 let. Apple II je imel 4 kB pomnilnika, celoten VisiCalc pa je meril 20 kB. Algoritem, ki je za prestopna leta preprosto pogledal deljivost s 4, je bil manjši in v očeh takratnih programerjev posledice niso bile velike. Najsi drži prva ali druga razlaga, je odgovor povedno preprost.

Združljivost za naprej

Znameniti dovtip pravi, da je težko napovedovati, še zlasti prihodnost, a vseeno lahko poskusimo. Pri načrtovanju programske opreme je razmišljanje o prihodnosti dandanes že standard. Tiste bolj napredne in premišljene pristope pa vendarle označimo kot združljivost za naprej (forward compatibility), če so načrtovani kot taki.

Primer je standard HTML, ki je načrtovan tako, da tolerira neznane oznake brez javljanja napak, saj jih preprosto ignorira. To olajša vgrajevanje novih oznak v nove različice standarda, saj bodo strani tudi na starejših brskalnikih normalno delovale, le upoštevane ne bodo.

Ločnica med hrošči (bugs) in funkcionalnostmi (feature) je torej tanka. Isto vedênje je v VisiCalcu hrošč, v Excelu pa funkcionalnost, ker je tja prenesena natanko enako in namenoma. Temu pravimo združljivost s hrošči (bug compatibility). In ne, Google Sheets tega hrošča nima.

Prepovedana imena datotek

V nekih zelo drugačnih časih smo bili v Microsoftovih operacijskih sistemih (DOS, Windows) pri poimenovanju datotek obsojeni na osem znakov za ime in tri za končnico. Zloglasni format 8.3 je presegel šele datotečni sistem VFAT, ki je omogočil dolga imena v Windows 95 in seveda NTFS v Windows NT (3.1). Leta 2024 je v Windows 11 seveda precej drugače, saj so lahko imena datotek (skupaj z drevesno strukturo!) zelo dolga – vse do 256 znakov z osnovnim nastavitvami, kar je mogoče podaljšati do 32.767 znakov. Tudi Windows 11 uporablja (med drugim) NTFS.

Prepovedana imena datotek so posledica odločitev iz 80. let prejšnjega stoletja.

Toliko bolj nenavadno je zato, da niti v Windows 11 ne morete ustvariti datotek z imeni CON, AUX, PRN, LST, COM0 do COM9 in LPT0 do LPT9. Enako velja tudi za ista imena s poljubnimi končnicami, denimo CON.txt ali LPT0.docx. Razlog se skriva v združljivosti s prvimi različicami operacijskega sistema DOS izpred štirih desetletij, ki se nikoli ni prekinila. Ta rezervirana imena so se uporabljala za posebne namene. Če je program shranil vsebino v »datoteko« LPT1, jo je v resnici pobral gonilnik (device driver) za izhod LPT1, kjer je bil ponavadi tiskalnik, in jo torej natisnil. Na ta način se programerjem aplikacij ni bilo treba ukvarjati s podrobnostmi, za katere so skrbeli gonilniki. CON je omogočal neposredno komuniciranje s tipkovnico (console), AUX s pomožnimi napravami (auxiliary) in podobno. Da je tak pristop deloval, pa je bilo treba ta imena rezervirati in tako še danes ne moremo ustvariti datotek, ki se tako imenujejo. Ker so bile končnice včasih shranjene ločeno, veljajo iste omejitve še za CON.txt. Microsoft bi seveda lahko to omejitev tudi odpravil, a verjetno je nekje na svetu kakšen zelo star program, ki še vedno bere podatke iz naprave CON in bi s tem nehal delovati. Microsoft za zdaj tega ne želi.

Mimogrede, datotečni sistem dovoljuje takšna imena, le programi jih načelno nočejo ustvarjati. Če v kakšnem drugem operacijskem sistemu ustvarite datoteke s prepovedanimi imeni, nato pa nosilec podatkov prenesete pod Windows, jih zato ne boste mogli enostavno izbrisati. Le z nekaterimi triki je tudi v Windows mogoče ustvariti (in brisati) prepovedane datoteke. Vse to zato, ker so pred pol stoletja na tak način programerjem poenostavili dostop do vhodno-izhodnih naprav.

Duhovi preteklosti

Če se potrudimo, lahko tudi v najnovejši izdaji Windows 11 najdemo okno za iskanje datotek, ki je bilo oblikovano za Windows 3.11 in se ni spremenilo. Če odpremo program ODBC Data Source Administrator (32 bit), kliknemo Add … in izberemo Driver do Microsoft Access (*.mdb) ter Select …, se prikaže »starinsko« okno, kot smo ga poznali pred desetletji.

Razlog je delovanje funkcij GetOpenFileName() in GetSaveFileName(), ki odpreta staro okno izpred Windows 95, če ne nastavimo zastavice OFN_EXPLORER. V konkretnem primeru želimo pri izbiri datoteke še možnosti Read Only in Exclusive, zato je potrebno staro okno. Microsoft bi ga seveda lahko posodobil, a to bi bila slabša možnost: bodisi bi podrl združljivost funkcije GetOpenFileName() bodisi vmesnika za ODBC Driver. V vsakem primeru bi nekaj obstoječe programske opreme nehalo delovati.

Tovrstnih reliktov preteklosti je v operacijskih sistemih precej, še največ pa jih najdemo v Windows, ker je ena izmed glavnih prednosti sistema prav združljivost. Mnogokrat napak menimo, da se s tem zagotavlja delovanje starih aplikacij, a pogosto je to nujno potrebno tudi za delovanje aktualnih v novih različicah. To staro okno iz Windows 3.11 je dosegljivo kateremukoli programu, ki ga prek OFN_EXPLORER zahteva, le da večina tega ne potrebuje in ne počne.

Hyrumov zakon

Hyrum Wright je inženir pri Googlu, po katerem se ena izmed občih resnic programiranja imenuje kar Hyrumov zakon. Pred 12 leti je zapisal, ko ima knjižnica (API) dovolj uporabnikov, postanejo obljube v pogodbah in dokumentacija irelevantne: vsako dejansko obnašanje postane pomembno, ker nekdo ali nekaj temelji na njem.

V praksi to pomeni, da nejavnih implementacij praktično ne more biti. Vsaka funkcionalnost, četudi je nedokumentirana, bo imela uporabo. To omejuje prihodnje spremembe v implementaciji, saj morajo upoštevati tako dokumentirane funkcije kot nedokumentirano, a v praksi uporabljeno obnašanje. Enako velja tudi implementaciji vmesnikov (interface).

Pisci programov pogosto ubirajo bližnjice, ki Microsoft skorajda prisilijo v nenavadne odločitve in vztrajanje pri združljivosti. Zgodovinski primer je bila datoteka systray.exe, ki je v Windows 95 skrbela za izris ikone zvočnika poleg ure v desnem spodnjem kotu in podobno. Ko je Microsoft v liniji Windows NT to rešil drugače, je postal systray.exe nepotreben, a to je nepričakovano pokvarilo cel kup aplikacij. Izkazalo se je, da so številne aplikacije preprosto preverile, ali obstaja datoteka systray.exe, namesto da bi uporabile namenske sistemske klice za določitev različice operacijskega sistema. Na koncu je Microsoft moral vrniti datoteko systray.exe, ki je več kot desetletje ždela v mapi Windows, čeprav ni imela popolnoma nobene funkcije, sicer bi cel kup programov nehal delovati.

Podobnih primerov je nič koliko, ko programi uporabljajo nedokumentirane funkcije in različne bližnjice. Seveda se lahko upravičeno vprašamo, zakaj bi Microsoft takšno lenobo podpiral, a pragmatični odgovor je – ker mu drugega ne preostane. Založnik je svoje že zaslužil (logika se sicer s prihodom naročniške programske opreme počasi spreminja), ko je program prodal uporabnikom, in ta trenutno deluje. Če Microsoft odstrani nedokumentirano funkcijo v novi različici Windows in zaradi tega program neha delovati, bo tarča pritožb seveda Microsoft, četudi je objektivno kriv pisec programa. Združljivost za nazaj ni le ključna prednost operacijskega sistema, je tudi nuja.

16, 32 ali 64 bitov

V časih Windows 95 in 98 s poganjanjem 16-bitnih programov za DOS nismo imeli težav, ker je bila podstat teh sistemov tako in tako DOS. Ko pa je prispela linija NT, je bila ta v celoti 32-bitna. V Windows 2000 in naslednikih ni bilo več 16-bitne kode, kar bi lahko predstavljalo težavo pri poganjanju starejših programov. Ti so večinoma dveh vrst: bodisi gre za specializirano programsko opremo v poslovnih procesih, kjer je proizvajalec morda že zdavnaj propadel, bodisi gre za igre. Ne da bi sodili o pomembnosti podpiranja teh, je Microsoft v linijo NT vnesel dvoje komponent.

Celo novi Windows 11 še vedno vsebujejo legendarno starinsko okno iz časov Windows 3.11, če bi ga programi zahtevali.

NTVDM (NT Virtual DOS Machine) je 32-bitna aplikacija za Windows, ki emulira procesor Intel 486 z nameščenim operacijskim sistemom DOS 5.0. Vsak program za DOS, ki ga poženemo, teče v svoji kopiji NTVDM in vidi svoj računalnik. Z vidika Windows NT pa gre za običajno za aplikacijo, ki je ločena od ostalih in jo je mogoče po potrebi tudi »ubiti«, če se začne »čudno obnašati«. Druga komponenta se imenuje WOW (Windows on Windows) in emulira 16-bitno okolje Windows 3.1 ter ponuja dodatne klice in funkcije, ki zgolj v NTVDM niso na voljo. Aplikacije v WOW so izolirane od sistema, niso pa ločene druga od druge. Če jih poženemo več hkrati in se ena sesuje, lahko to podre tudi ostale – podobno kot se zares zgodi v starejših sistemih s kooperativno večopravilnostjo (npr. Windows 95).

Stari način

Soroden koncept je tudi stari način (legacy mode), kar pa ni enako kot združljivost za nazaj. Zadnje pomeni, da sistem pri delovanju podpira tudi starejše različice. Kadar naprava teče v starem načinu, običajno ne nudi vseh svojih zmožnosti, njeno delovanje pa je okrnjeno. Vsi 64-bitni procesorji poleg dolgega načina podpirajo stari način, kjer lahko delujejo v 16- ali 32-bitnem načinu. Podobno grafične kartice omogočajo stari način, običajno ločljivost VGA ali SVGA, ki se uporabi, ko niso naloženi ustrezni gonilniki zanje. Tudi številna vodila lahko emuliramo v starih načinih, denimo PS/2 prek USB ali PCI prek PCIe.

Danes pa so procesorji in operacijski sistemi 64-bitni. V 64-bitni inačici Windows ni več mogoče poganjati 16-bitnih programov, ker v njej ni več NTVDM. Če želimo uporabiti 16-bitni program, moramo sami poskrbeti za virtualizacijo oziroma navidezni stroj. DOS lahko emuliramo s programom DOSBox, ki je začel nastajati v časih Windows 2000. Že tedaj v NTVDM niso delovali vsi programi, ker niso imeli dostopa do realnega načina (neposredni dostop do strojne opreme), kar je reševal emulator. V časih 64-bitnih sistemov pa je to edini način za njihovo poganjanje. 32-bitne programe pa lahko v 64-bitnih operacijskih sistemih večinoma poganjamo brez težav.

Procesorji

Čeprav v 64-bitnem Windows ne moremo poganjati 16-bitnih aplikacij, lahko na najnovejše 64-bitne procesorje (x86-64) namestimo celo dobri stari DOS. Procesorji iz družine x86 (Intel in AMD) jemljejo združljivost za nazaj zelo resno, in čeprav z vsako novo generacijo postajajo hitrejši in dobivajo nove ukaze, še vedno podpirajo vse tisto, kar je znal procesor Intel 8086/8088 davnega leta 1978.

Moderni procesorji večinoma tečejo v dolgem načinu (long mode), kjer uporabljajo 64 bitov, ni pa to edini način. Ko se zaženejo, tečejo v realnem načinu in šele jedro 64-bitnega operacijskega sistema zahteva prehod v dolgi način. Če pa jim tega ne ukaže, lahko tečejo tudi v realnem načinu, zaščitenem načinu (protected mode) ali mešanem načinu (unreal mode). A ko procesor enkrat preklopi v dolgi način, ne more preiti nazaj v zaščiteni ali realni način brez ponovnega zagona. To je del razloga, da nativno poganjanje 16-bitnih aplikacij v 64-bitnih operacijskih sistemih ni mogoče. Šele virtualizacija (VT-x in AMD-V) je omogočila, da procesor, ki deluje v dolgem načinu, ustvari virtualni (logični) procesor, ki emulira arhitekturo 8086.

Po drugi strani pa 64-bitni procesorji brez večjih težav sprejemajo 32-bitne ukaze. Danes je to redkeje, v preteklosti pa je na novih 64-bitnih procesorjih pogosto tekel kar 32-bitni operacijski sistem, saj za številne kose strojne opreme 64-bitnih gonilnikov še ni bilo. Ti so eden redkih kosov programske opreme, ki mora ustrezati »bitnosti« sistema.

Igre in konzole

Poseben svet so konzole in igre zanje. Ko je pred štirimi leti izšel novi Xbox serij X in S, so se posebej pohvalili, da podpira tudi igre za starejše Xbox 360 in Xbox One. Ta združljivost je bila ena ključnih značilnosti, ki so jih izpostavili v oglasih. Pri konzolah namreč to ni samoumevno, saj je vrsto let veljalo, da nova različica konzole zahteva tudi nakup novih iger. S tem so proizvajalci konzol in pisci iger živeli v simbiozi, ki je povečevala povpraševanje in prodajo.

Prve konzole, denimo Atari 5200 ali Nintendo NES, niso marale za starejše izdaje. Prvi je pomembnost združljivosti dojel Sony. PlayStation 2 je podpiral igre za enico, PlayStation 3 pa igre za dvojko. Četudi se je vmes strojna oprema spreminjala in PlayStation 4 ni mogel fizično brati diskov iz trojke ali dvojke, so vsaj za privid združljivosti poskrbeli z izdajo številnih iger v posodobljeni obliki, ki jo je bilo moč pretočiti in igrati na PlayStationu 4. Podobno tudi PlayStation 5 podpira igre za štirico, starejše pa prek PlayStation Plusa.

Knjižnice in odvisnosti

Pri sorazmerno preprostem nameščanju programov dandanes bi skoraj pozabili, da smo še pred desetletjem živeli v zelo drugačnem svetu, kjer so imeli različni programi zelo različne ideje o tem, katere skupne knjižnice potrebujejo.

V okolju Windows so programi uporabljali skupne knjižnice, ki so zagotavljale standardizirani dostop do višjih funkcij. Poznali smo jih pod imenom DLL (dynamic link library), sistem pa jih je v pomnilnik naložil le enkrat, četudi jih je uporabljalo več programov. Ko so se DLL nadgrajevali, je bil kaos pričakovani rezultat. Neredko se je zgodilo, da je program naletel na novejšo inačico DLL, ki ni več delovala povsem enako, zato se je zrušil. Obratne probleme pa so povzročali programi, ki so med namestitvijo prepisali kakšno obstoječo datoteko DLL s starejšo različico. Večne težave z DLL so se imenovale pekel (DLL hell).

Najenostavnejša, a tudi manj učinkovita rešitev je bila uporaba statičnih knjižnic, ki so bile v programe vgrajene ob prevajanju. Za programe, ki so vztrajali pri DLL, pa se je razvilo več rešitev, ki so poskušale zagotoviti soobstoj več različic DLL in varovanje sistemskih DLL. Šele z izidom Windows XP in naslednjih izdaj se je stanje začelo urejati.

Podobne težave so obstajale v Linuxu, kjer večina programov potrebuje zunanje knjižnice in druge kose programov, skupno poimenovane odvisnosti (dependency). Te so se lahko sklicevale še na druge knjižnice, ki so zahtevale točno določene različice in podobno. Pri nameščanju večjega števila programov se je hitro zgodilo, da smo naleteli na protislovne zahteve o nameščenih knjižnicah. Tudi Linux je z leti te težave prerasel, v pretežni meri pa so jih odpravili upravljalniki paketkov (packet manager). Rešitev so deljene knjižnice in upoštevanje različic. Rigorozno rešitev pa predstavljajo upravljalni paketki, ki uporabljajo strogo upoštevanje različic (strong versioning), denimo Nix ali Guix.

Pri konzolah je sicer zagotovilo o združljivosti vedno pospremljeno s kakšno opombo in nikoli ni zares enoznačno. Četudi PlayStation 5 načelno podpira igre predhodnika, se vedno najde kakšen naslov, ki ne bo deloval. Podobno velja za starejše igre iz časov PlayStationa 2 in 3, ki jih fizično ne moremo vstaviti v napravo, lahko pa ji pretekamo s spleta – kot na nekakšnem Netflixu za igre. V drugo smer seveda ne gre. Nove igre na starih konzolah ne delujejo.

Še danes je v Windows nameščen cel kup različnih inačic knjižnic. Zavoljo združljivosti.

Prav tako je pri konzolah pojem združljivosti za nazaj zelo raztegljiv. Ne govorimo namreč o pravi združljivosti, ki bo omogočala poganjanje iste kode, temveč se zadovoljimo z isto igro. Če to proizvajalec doseže tako, da se igra prenese s pretočne storitve PlayStation Plus ali Xbox Live, morda z rahlo prilagojeno kodo, uporabniška izkušnja pa je enaka – ali je to prava združljivost za nazaj? V strogo tehničnem pomenu besede morda ni, za uporabnika pa razlike ni, vsaj dokler nekdo ne ugasne spletnih strežnikov. Tedaj bo postalo pomembno, katere igre so sploh še na fizičnih medijih in kam jih lahko vtaknemo.

Kdaj je dovolj

Microsoft velja za podjetje, ki je skorajda obsedeno z združljivostjo za nazaj, za kar ima dobre razloge. To je ena izmed konkurenčnih prednosti, a po drugi strani je to tudi nujnost. Če ob nadgradnji operacijskega sistema polovica nameščenih programov neha delovati, se bodo uporabniki hudovali nad Microsoftom, najsi bo to upravičeno ali ne.

Združljivost za nazaj je nujno potrebna za sproten in postopen razvoj. V svetu danes teče preveč kode, da bi bile revolucije še mogoče, ker bi bili stroški previsoki. Pomemben dejavnik je tudi psihologija, saj imamo ljudje najraje zmerno količino novosti. Če so novi izdelki preveč podobni starim, so nezanimivi. Če so preveč drugačni, so strašljivi in nepriljubljeni. Ravno pravo kombinacijo novega in starega pa omogoča prav – združljivost za nazaj.

Na drugi strani spektra je načrtovana zastarelost (planned obsolescence), ko so izdelki namenoma načrtovani tako, da po določenem času niso več uporabni, čeprav za to ni nobenega tehničnega razloga, je pa finančni oziroma ekonomski interes, ki se mu mora ukloniti tudi združljivost za nazaj. V izdelkih bo prisotna, dokler bo to tehnično in ekonomsko smiselno. Različna podjetja pri različnih izdelkih to črto potegnejo vsako po svoje. Wi-Fi je standard, kjer je združljivost med različicami ključna in prav nič ne vpliva na prodajo naprav. Microsoft Word že dobro desetletje uporablja zapis XML (datoteke DOCX), a še vedno podpira tudi 35 let stari format DOC, kar bi njegova odsotnost negativno vplivala na prodajo pisarniškega paketa. Po drugi strani umanjkanje te združljivosti pri igrah igralce motivira v nakup novih konzol.

Naroči se na redna tedenska ali mesečna obvestila o novih prispevkih na naši spletni strani!

Komentirajo lahko le prijavljeni uporabniki

 
  • Polja označena z * je potrebno obvezno izpolniti
  • Pošlji