Cookies op Tweakers

Tweakers maakt gebruik van cookies, onder andere om de website te analyseren, het gebruiksgemak te vergroten en advertenties te tonen. Door gebruik te maken van deze website, of door op 'Ga verder' te klikken, geef je toestemming voor het gebruik van cookies. Wil je meer informatie over cookies en hoe ze worden gebruikt, bekijk dan ons cookiebeleid.

Meer informatie

Door Tino Zijdel

[HQ] Developer

Tweakers stapt over op utf-8

14-01-2019 • 11:57

91 Linkedin Google+

In november brachten we jullie al op de hoogte van het feit dat we druk bezig waren met het omzetten van onze standaardtekencodering van latin-9 (ISO-8859-15) naar utf-8. In de afgelopen week al hebben we daarvoor onze database geconverteerd, waarvan jullie als het goed is niets gemerkt hebben. Zojuist is ook onze aangepaste codebase online gegaan en is onze site dus volledig unicode-compliant.

De grootste uitdaging van dit project zat hem in die databaseconversie. Aangezien we natuurlijk liever geen downtime hebben, is hiervoor de pt-online-schema-change tool van percona gebruikt. Deze tool hebben we al eerder met succes gebruikt voor grotere databasewijzigingen en maakt het mogelijk tabelwijzigingen door te voeren terwijl lees- en schrijfoperaties gewoon kunnen blijven worden uitgevoerd.

Daarnaast moest uiteraard onze codebase zelf worden geconverteerd, en moesten in de code zelf alle plekken waar content wordt geoutput en van of naar utf-8 geconverteerd (bijvoorbeeld interfaces met externe systemen), worden aangepast. Over het algemeen bleek dat redelijk eenvoudig door gebruik te maken van PHP's mb_string-functies waar nodig, maar ook waren er een paar lastigere problemen te tackelen; zo moest bijvoorbeeld onze wachtwoordopslag aangepast worden en moest een tussenstap worden toegevoegd om wachtwoorden die nog gehasht zijn, met latin-9 input te kunnen valideren.

We zijn er echter nog niet helemaal. Omdat MySql feitelijk nooit support heeft gehad voor de door ons gebruikte latin-9 codering, is een extra conversie nodig om de verschillen tussen latin-1 en latin-9 nog op te lossen. Dat betreft vooral de weergave van het euroteken, dat door de conversie nu feitelijk in de database een currency symbol (¤) is geworden. Op dit moment wordt dat verschil nog rechtgezet met een stukje code dat al onze output checkt en aanpast, maar ondertussen draait hiervoor een extra conversie op de database om dat allemaal recht te zetten.

Als het goed is merken jullie als bezoeker hier verder weinig van. Het grootste verschil is dat je nu niet meer geconfronteerd wordt met numerieke entiteiten als je bijvoorbeeld je reactie of post aanpast waarin je een 'speciaal teken' had gebruikt. Een 🍺 blijft dus een 🍺 en wordt geen 🍺 😀

Reacties (91)

Wijzig sortering
Ik vraag me af wat de reden was om te kiezen voor latin-9 codering in faveure van het meer universele utf-8, weet iemand van voordelen?
Deze grafiek ga je wel interessant vinden: https://en.wikipedia.org/...ia/File:Utf8webgrowth.svg
Tweakers stamt uit 1998 en toen was utf-8 verre van universeel. Er zal in de tussentijd veel software herschreven zijn, maar zelfs nu wordt het nog niet overal gebruikt ;)

Bron: https://en.wikipedia.org/wiki/UTF-8

[Reactie gewijzigd door job_h op 14 januari 2019 12:06]

Leuke grafiek!

Mijn online magazine is "from scratch" gebouwd in 2005. Die is toen ook op iso gebouwd, was toen heel gebruikelijk - hadden we het 2 jaar later gedaan dan was dat misschien niet zo geweest. :)

Verleden jaar omgezet na een MySQL upgrade.
Note that the ASCII-only figure includes web pages with any declared header if they are restricted to ASCII characters.
Het is gewoon legacy, er is nooit een bewuste keuze gemaakt om geen UTF-8 te ondersteunen (wat in de tijd dat tweakers ontstond nog helemaal niet zo gemeengoed was). Wel is er geloof ik destijds expliciet voor latin-9 gekozen ipv latin-1 vanwege de aanwezigheid van een paar specifieke tekens.

Maar om een voordeel te noemen, elk teken is gewoon 1 byte. Dat maakt dat je een string bijvoorbeeld makkelijk kan limiteren op N karakters, of makkelijk het Ne karakter kan opzoeken zonder vanaf het begin van de string te lopen en te tellen. Bij UTF-8 kunnen karakters 1 tot 4 bytes zijn.

[Reactie gewijzigd door .oisyn op 14 januari 2019 12:08]

Als latin-9 gekozen is voor onder andere het euro-teken dan lijkt het me dat dit dus al ergens in deze eeuw gebeurd en niet al in 1994 lijkt me. En dat zou dan al rond de introductie van UTF-8 zijn gebeurd.

Al waren natuurlijk veel systemen en libraries nog niet over, dus kan ik me voorstellen dat dit een reden was. Maar natuurlijk geen excuus om het vervolgens 18 jaar te laten liggen :P
Het heeft even geduurd voor MySQL utf-8 ondersteunde. En in werkelijkheid ondersteunt php nu nog steeds utf-8 niet echt (zoals native in Java)... Het voelt in ieder geval nog als een hack om bijvoorbeeld andere string-functies te moeten gebruiken.
De "normale" string functies zullen het dan ook nooit gaan ondersteunen. Allerlei code die rekent op waardes gebaseerd op bytes ipv characters zou dan omvallen. Daarom kun je denk ik beter de mb functies zien als de "native" functies en die andere vergeten.
Als latin-9 gekozen is voor onder andere het euro-teken dan lijkt het me dat dit dus al ergens in deze eeuw gebeurd en niet al in 1994 lijkt me.
Nogal wiedes, Tweakers bestond in 1994 nog niet ;)
Sterker nog; UTF-8 in MySQL is utf8mb4, niet gewoon utf8, omdat daar tekens geloof ik missen. utf8mb4 is dus de correcte UTF-8. Het heeft dus ook wel even geduurd vooraleer UTF-8 correct ondersteund werd door MySQL.
Overstappen op UTF-32 zodat alle karakters 4 bytes zijn :+
Dat is ook in UTF-32 niet het geval. ;)
Zover ik zo snel kan vinden is UTF-32, in tegenstelling tot UTF-8 en UTF-16, een fixed-width format; het gebruikt dus altijd 32 bits (dus 4 bytes) per codepoint (karakter). :)
Nee, olaf heeft een punt. ä kan één of twee codepoints zijn. Dat hangt er van of of de umlaut een los codepoint is.
Ik snap de neiging niet om dat ding een umlaut te noemen, terwijl we het in NL vooral als trema (zelfde glyph, andere functie) gebruiken :). De umlaut kan trouwens ook geschreven worden als ◌ͤ.

.edit: oh, in dat opzicht kan de ä ook als 3 codepoints worden geschreven. Combining Grapheme Joiner (U+034F) + Combining Diaeresis (U+0308) + a. Dat is een ISO/IEC JTC 1/SC 2/WG 2 recommendation voor als je het verschil tussen de umlaut en het trema wilt encoderen.

[Reactie gewijzigd door .oisyn op 14 januari 2019 14:06]

@.oisyn een umlaut en een trema zijn niet het zelfde en hebben ook aan andere vorm.
Dat door de beperking van een typemachine / computer / tekenset er voor en ë ipv e̋ is gekozen maakt van een ë nog geen umlaut, Zoals @MSalters aangeeft voor een e̋ heb je twee codeponts nodig een e en een ̋ ( U+030B | ̋ | cc 8b | COMBINING DOUBLE ACUTE ACCENT) bron: utf8-zeichentabelle

Oorspronkelijk had dat teken de vorm van een Sütterlin-e, een tekentje, dat eruitziet als twee schuine streepjes naar rechts wijzend die boven de klinker werd geschreven.

De umlaut is in de loop van de tijd via twee schuine streepjes vereenvoudigd tot twee puntjes. Daarmee ziet de moderne umlaut er in druk uit als een trema, maar in een handgeschreven tekst kan hij nog steeds de vorm van twee korte schuine streepjes hebben.

Bron: wikipedia.org | Umlaut_teken

Nu het technisch weer mogelijk is zie je dat er weer terug gegrepen wordt naar de oorspronkelijke typografie / loodzet werk. Bijvoorbeeld: uithangende cijfers, ook mediaeval cijfers genoemd.
Lees verder op: Wikipedia |Uithangende cijfers

OEPS [15:05]: er is geen e̋ in het het Duits als umlaut had een a̋, ő of ű moeten gebruiken in het voorbeeld

VERDUIDELIJKING [15:17]: De insteek van deze reactie is dat het nu met de huidige kennis en techniek weer mogelijk is de oorspronkelijk typografie te gebruiken die met de komst van o.a de computer vervangen is door alternatieven omdat het technisch niet mogelijk wat het op de "juiste" manier te doen. En daar dus UTF-8 en de umlaut als kapstok voor gebruikt.

AANVULLING [15:28]: German.stackexchange.com | How should an umlaut be written

[Reactie gewijzigd door hans3702 op 14 januari 2019 15:28]

een umlaut en een trema zijn niet het zelfde en hebben ook aan andere vorm.
De umlaut is er in vele vormen en maten en het is idd niet eenduidig. Ik had het over de glyph in unicode. De puntjes zijn vandaag de dag wel vrij standaard, zowel in geschreven als gedrukte vorm.
Zoals @MSalters aangeeft voor een e̋ heb je twee codeponts nodig een e en een ̋ ( U+030B ̋ cc 8b COMBINING DOUBLE ACUTE ACCENT) bron: utf8-zeichentabelle
Dat is een mogelijkheid, maar dat is niet wat MSalters zei. Hij zei dat een a met umlaut met 1 of 2 codepoints geschreven kan worden, dus ook als enkele U+00E4, oftewel ä. De ̋a bestaat niet in een enkele codepoint. [.edit: grappig dat ik die ̋a niet kan pasten in chrome]

Deze bron zegt dat het unicode consortium (ISO/IEC JTC 1/SC 2/WG 2) zelf aanraadt om het verschil te encoderen als Combining Diaeresis (U+0308) voor de umlaut en Combining Grapheme Joiner (U+034F) + Combining Diaeresis (U+0308) voor de trema.

Verder is te lezen op de door jou gelinkte pagina:
Tegen de 16e eeuw waren die streepjes vervangen door stipjes, vooral in handgeschreven teksten, en later gradueel ook in gedrukte teksten. In de twintigste eeuw werden nog steeds streepjes ook gebruikt, zo werd op de middelbare school in Nederland nog steeds zo aangeleerd.
De stipjes bestaan dus al een tijdje, en zijn niet echt recent. Wat je schrijft in je verduidelijking is dus quatsch, om maar een Duits woord te gebruiken ;). Er bestaat niet een algemeen juiste manier om de umlaut te schrijven.

Ook interessant, de genaamde html entities voor ä, ë, etc zijn dus ook ä, ë, etc. En dat terwijl de e helemaal geen umlaut kent :P.

[Reactie gewijzigd door .oisyn op 14 januari 2019 18:01]

ë, etc. En dat terwijl de e helemaal geen umlaut kent .

Ik denk dat dat komt omdat de umlaut oorspronkelijk een extra 'e' achter een ue of oe was.

Ik wist dat je schön / Düsseldorf (maar dan met streepjes) ook als schoen / Duesseldorf mocht schrijven.
Maar ik was verbaasd dat dat juist de oorspronkelijk manier van schrijven was! (denk ooit gelezen in wiki?)
Bij de oe/ue werd de e er steeds vaker rechtsboven geschreven: ue.
Later werd die e vervangen door 2 streepjes.

Ik denk omdat die e de klank bepaald en niet uitgesproken wordt.
En daarom zal er dus geen e met umlaut zijn, omdat ee nooit ë is geworden.

[Reactie gewijzigd door SCS2 op 14 januari 2019 19:16]

Maar dan is het wel raar om de ë een e-met-umlaut te noemen :)
En ik heb begrepen dat de å in de skandinavische talen een ooit aa was.
Als je ISO8859-15 zegt in plaats van latin-9 weten veel windows-gebruikers opeens waar het over gaat. ISO8859-1 is degene met een $ en ISO8859-15 die met een €. (op de plek van het currency symbol)

[Reactie gewijzigd door burne op 14 januari 2019 12:26]

Nu zet je in je uitleg wel een serieuze fout :P

In beide zit de $ op dezelfde plek. ISO-8859-1 en 15 hebben in totaal iets van 6 karakters die anders zijn in 15 en het "currency" teken (deze dus: ¤) is daar een van. En op die plek is het euro-teken gekomen.

[Reactie gewijzigd door ACM op 14 januari 2019 12:26]

Als aanvulling wat ACM hierboven zegt, $ zit in ASCII en aangezien UTF-8, latin-1 en latin-9 allemaal een superset zijn van ASCII hebben ze allemaal dezelfde codering voor $, namelijk 36, en dat is dan ook het codepoint in de unicode standaard.

[Reactie gewijzigd door .oisyn op 14 januari 2019 12:41]

Ik vraag me af wat de reden was om te kiezen
Ik denk dat er nooit bewust gekozen is.. er is gewoon gebruikt wat beschikbaar / standaard was.
UTF-8 support in MySQL en PHP was er destijds vrijwel zeker niet.
Pas met de release van MySQL 8 (2018) is UTF-8 de standaard geworden.
In MariaDB is het, helaas, nog steeds niet de standaard tekenset.

[Reactie gewijzigd door Olaf van der Spek op 14 januari 2019 12:08]

De overstap van een oudere (meestal meer compacte) character set codering naar een nieuwere (meestal meer uitgebreide) character set klinkt als een logische open deur om met te tijd mee te gaan.

Het is echter zoals hier in alle reacties te zien is absoluut geen simpele conversie operatie. Omdat deze character sets in de uitwisseling tussen veel systemen van verschillende aard, taal en leeftijd onderling gebruikt worden, en er dus veel compatibiliteit die ondersteund moet worden. Ondanks de benoemingen ISO en Universal, is er veel ver van standaard.

Heb zelf wel meegemaakt dat het bij conversie noodzakelijk was ook de originele character set te bewaren als meta-data, om terugconversie mogelijk te maken (GSM en shift alphabets anyone?). Zonder deze extra info bij te houden was exacte terugconversie voor compatibiliteit niet mogelijk richting een gekoppeld systeem.

Vind eigenlijk gezien de potentiele complexiteit, dat de omzetting vlot verlopen is. Nu nog even testen of we correct kunnen posten in een baltische taal. Is er een tweaker bij die dat in de vingers heeft? :)
Op pc's werd utf-8 toen ook nog niet gebruikt.
Ik merk op dat de website over het algemeen beter(lees:sneller) reageert, of is dit maar een idee?
Well done! _/-\o_ _/-\o_

[Reactie gewijzigd door crovax_be op 14 januari 2019 12:00]

Bedoel je te suggereren dat dat 'sinds utf-8' is? Dat lijkt me erg sterk, er is eerder meer dan minder werk nodig ;)
Dus alle Emojis die de browser laat zien kunnen gebruikt worden?
Full list: https://unicode.org/emoji/charts/full-emoji-list.html
Gaan dan alle berichten vol staan met 🐞 🌺 🥑 🎃 ?
Dat kon voorheen ook al, alleen werden ze geconverteerd naar de betreffende HTML entities, dus &#<code>; notering.

[Reactie gewijzigd door .oisyn op 14 januari 2019 13:03]

Okay, bedankt.
Op sommige forums wordt slechts een klein aantal UTF-8 tekens toegelaten. Hier op tweakers kan blijkbaar alles.
Als alles kan, dan hangt het van de browser af. De landenvlaggen gebruiken een dubbele UTF-8 notatie. Dat kan nog niet iedere browser.
Nederlandse vlag: 🇳🇱
Amerikaanse vlag: 🇺🇸
(ik zie een niet-golvende rechthoekige vlag met ronde hoeken in Firefox onder Ubuntu linux).

[Reactie gewijzigd door Mignol op 14 januari 2019 17:13]

Vreemd, op Firefox voor Android zijn ze wel golvend: https://i.postimg.cc/qRVM...ot-20190114-091326-01.jpg

Zal wel aan het OS liggen.
Heb speciaal ff Firefox geïnstalleerd, maar bij mij ziet het er wel gwn normaal uit? Is op MacOS, miss hebben ze daar een andere encoding ofzo
Die van mij alleen met 🦉🦉 natuurlijk. Al mijn posts gaan er uit zien als personal websites uit het eerste uur }>
Goed bezig!

Iets meer info voor de mensen die dezelfde wijziging plannen: het beste is om te kiezen voor utf8mb4 als het gaat om de database, aangezien de normale utf8 ook geen ingebouwde emoji-support heeft.
Om specifiek te zijn utf8mb4_unicode_ci.

Vergeten moet ook niet worden om alle servers, editor(s), en tools UTF-8 te laten praten. Met nieuw projecten is dat tegenwoordig geen probleem, die spreken 99% UTF-8, maar legacy omzetten naar deze is echt een hell. Wat het nog erger maakt is dat je editor code brak kan maken omdat deze niet (goed) is ingesteld voor die 'oude soep', zo heb ik helaas bij projecten genoeg PHP en js bestanden gezien die niets meer deden, al hadden we daar gelukkig wel git al voor opgezet. :)
Elke utf8mb4 collatie ondersteund emoji’s, verschil zit ‘em in sortering en zoeken. Echter kom je in Europa nog wel weg met het ‘oudere’, maar wel snellere, general_ci
Goed bezig!

Iets meer info voor de mensen die dezelfde wijziging plannen: het beste is om te kiezen voor utf8mb4 als het gaat om de database, aangezien de normale utf8 ook geen ingebouwde emoji-support heeft.
Je bedoelt dat voor MySQL de encoding 'utf8' UTF-8 niet volledig ondersteunt (dit is dus een design-bug in MySQL), waardoor wel heel veel, maar niet alle unicode code points verwerkt kunnen worden. Als je daarentegen in MySQL de encoding 'utf8mb4' kiest, dan kunnen wel alle unicode code-points opgeslagen worden.

Edit: het blijkt dat op dit moment MySQL 'utf8' interpreteert als 'utf8mb3'. En met utf8mb3 kunnen dus niet alle codepoints opgeslagen worden. In de toekomst willen ze utf8mb3 uitfaseren, en wordt 'utf8' hetzelfde als 'utf8mb4', en vanaf dan kun je dus gewoon 'utf8' gebruiken.

[Reactie gewijzigd door RJG-223 op 14 januari 2019 13:17]

Kan iemand vertellen of er toevallig ook utf8mb4 gebruikt is? Lijkt me wel wenselijk, ik liep laatst tegen een nieuwe emoji aan die in utf8mb3 zit...

Verder heb ik ook al even gespeeld met pt-online-schema-change, en ben nog een beetje huiverig om dit toe te passen op tabellen als er foreign keys naar zo'n tabel zijn. Iemand die daar (meer) ervaring mee heeft? Of pt-online-schema-change toegepast heeft op een Galera cluster?
We gebruiken idd mb4.

Foreign keys laat ie vrij duidelijk van zien dat ie het al-dan-niet begrijpt. Tot nu toe is het steeds goed gegaan ;)
Had dan niet beter in de titel en/of in het artikel kunnen staan dat het utf8mb4 is?
Want er zijn volgens mij meerdere utf8 versies voor database opslag waar utf8mb4 vaak geprefereerd wordt.
Ik ben geen server-geek maar genoeg Tweakers die zulke details wel op prijs stellen. :+
Waarom moet dat in de titel van het artikel staan?
We zijn toch niet naar 'utf8mb4' overgestapt? Alleen MySQL heeft daar wat onhandige details voor, maar dat is een implementatiedetail dat verder niet relevant is voor de generieke technologie (browsers, php, etc).
Maw: testen dus... tx!
Het currency symbool wordt hier in het artikel (nog) getoond als euro. Dat zullen we dus binnenkort wel zien veranderen als die laatste conversie overbodig is?
Volgens mij wordt er bedoeld dat het eerst nog werd opgeslagen als &euro;

.edit: nee wacht, volgens mij wordt er idd bedoeld dat het als ¤ te zien moet zijn. Ik snap eigenlijk niet helemaal waarom, ¤ is 164 in latin-1, en de € is 164 in latin-9. Maar dat zou betekenen dat ze de boel dan als latin-1 interpreteren voordat ze de omzetting naar UTF-8 doen ofzo? Vind het maar een rare opmerking.

.edit2: oh dat is grappig, als ik ¤ invul door te copypasten maakt tweakers er een € van :P

.edit3: over die omzetting, staat dus ook gewoon in het artikel 8)7
Omdat MySql feitelijk nooit support heeft gehad voor de door ons gebruikte latin-9 codering is er een extra conversie nodig om de verschillen tussen latin-1 en latin-9 nog op te lossen.
Helemaal logisch.

[Reactie gewijzigd door .oisyn op 14 januari 2019 12:36]

Op dit moment ondersteunen we het currency-sign effectief niet door die mysql-issue... We zetten die in de output laag nu om naar euro's (omdat mysql ze dus verkeerd omgezet heeft) en gaan nog bezig om de inhoud van de database om te zetten van \u00A4 naar \u20AC.
"Waar jullie hopelijk niets van hebben gemerkt" De website lag er zaterdagochtend voor enige tijd uit met een 503 error. Wellicht toch iets van gemerkt.
Toen was de UTF-8 conversie al lang gedaan, dus dat was niet gerelateerd ;)
Wat was dan wel de reden @crisp ? Op het feedback forum wordt daarover niet gereageerd, weet jij het wel?
nee, ik weet het niet precies. @Kees had het al opgelost toen ik wakker werd :P
@ACM Zijn jullie trouwens overgestapt op uft8 of utf8mb4? In het laatste geval wordt het opslaan van tekens ook gemakkelijker met betrekking tot o.a. Emoji's.

Ik ben erg benieuwd naar de werking van pt-online-schema-change tool van percona. Aangezien ik zelf een grote database beheer voor onze webapplicatie en regelmatig tegen uitdagingen aanloop om column wijzigingen te doen.

Hoe is precies de werkwijze?

PS congrats met de overzetting. Encodings zijn een pain in the b*tt en het heeft ons ook veel moeite gekost om over te stappen op mb4.

[Reactie gewijzigd door juggle op 14 januari 2019 14:57]

We gebruiken idd mb4. Voor online schema change kan je het beste hun online documentatie lezen. In het kort maakt ie een kopie van je tabelstructuur en voert je aanpassing uit. Via triggers wordt ervoor gezorgd dat alle data synchroon blijft en ondertussen gaat ie dan de oude records naar de nieuwe tabel kopiëren.
Ja idd, documentatie al helemaal doorgelezen en ziet er erg interessant uit! Toch wat huiverig om toe te passen op onze productie database. Uiteraard eerst testen op de dev omgeving. Zijn er nog bijzonderheden waar jullie tegenaan zijn gelopen of is de migratie soepeltjes verlopen?
Nee. Het werkt eigenlijk elke keer goed, maar er zijn scenario's die ie simpelweg niet aankan. Denk aan tabellen die geen primaire of unieke sleutel hebben, waardoor die niet bruikbaar zijn icm de triggers.

We hadden er uiteindelijk wel een paar die ie door een paar redenen niet kon. Maar het overgrote deel kon verwerkt worden en scheelde daardoor aardig wat tijd.
Dat betekent dus ook dat emoji/niet Latijnse tekst in ondertitel/signature nu niet meer extra karakters verbruiken tov de lengtelimiet :) ?
Dan is nog de vraag of de lengtelimiet in karakters of in bytes is? een emoji is over het algemeen 3 bytes

<edit> of 4: 🙃 (128579 / 0x1F643 byte sequence: F09F9983)

[Reactie gewijzigd door trenjeska op 14 januari 2019 15:05]

Niet al die code zal aangepast zijn, dus er is een kans dat het soms op karakters werkt en soms op bytes ;)
Viel me vanochtend al op, bij nieuws: AMD klaagt MediaTek aan voor inbreuk op gpu-patenten stond Nieuwsco�rdinator ipv Nieuwscoördinator

(staat nu wel goed)

[Reactie gewijzigd door cracking cloud op 14 januari 2019 13:49]

Dus om het verschil aan te geven gebruik je nu twee UTF-8 tekens in je reactie: een � en een ö ;)


Om te kunnen reageren moet je ingelogd zijn


Apple iPhone XS Red Dead Redemption 2 LG W7 Google Pixel 3 XL OnePlus 6T (6GB ram) FIFA 19 Samsung Galaxy S10 Google Pixel 3

Tweakers vormt samen met Tweakers Elect, Hardware.Info, Autotrack, Nationale Vacaturebank, Intermediair en Independer de Persgroep Online Services B.V.
Alle rechten voorbehouden © 1998 - 2019 Hosting door True