Bestandsnamen zoeken in databank

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Geert Huylebroeck

Geert Huylebroeck

01/10/2019 11:25:13
Quote Anchor link
Ik gebruik PHP om een map met foto's uit te lezen. Daarvoor gebruik ik deze code:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
while (false !== ($entry = readdir($handle)))


Elke $entry wil ik controleren in een databank. Dat werkt behalve als er speciale karakters in de bestandsnaam voorkomen: AdigûzelElbinur21.03.2001.jpg, TruöngNgoc Mai13.09.2009.jpg, ...

Er zit dus iets niet juist met de encoding van de bestanden vs. de databank. De databank staat volledig in utf8_general_ci. Ik ga zoeken in een view die twee tabellen via union samenvoegt.

Als ik met mb_detect_encoding kijk, dan zie ik dat de bestandsnamen ook in utf8 staan.

Het script draait op een Centos 7 server met PHP versie 7.3.9.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
while (false !== ($entry = readdir($handle))) {
  if($entry !=='.' && $entry !=='..' && $entry !== '__MACOSX'){
    echo "<div class=\"bold\">$entry</div>";
    $sqlentry = mysqli_real_escape_string($link, $entry);
    $query = "select pointer from vwLeerlingenFotosNaarSmartschool where zoekstring  = '$sqlentry'";
  }
}



Ik heb ook getest door alle namen vanuit de databank eerst in een array te stoppen.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
$query  = "select distinct pointer from vwLeerlingenFotosNaarSmartschool";
$result = mysqli_query($link, $query);

$arr_pointer = array();

while($row = mysqli_fetch_assoc($result)){
    $pointer = $row['pointer'];
    $arr_pointer[$pointer] = $row['zoekstring'];
}


Ik gebruik daarna in_array of array_search om te zoeken maar ook daar werkt dat niet bij de speciale gevallen.

Hoe kan ik er voor zorgen dat de strings in de array (of de databank) toch matchen met de strings die ik uit het bestandssysteem ophaal?
Gewijzigd op 01/10/2019 11:53:12 door Geert Huylebroeck
 
PHP hulp

PHP hulp

16/06/2024 15:17:12
 
- Ariën  -
Beheerder

- Ariën -

01/10/2019 11:39:10
Quote Anchor link
Zou je de code tussen code-tags kunnen plaatsen?
 
Thomas van den Heuvel

Thomas van den Heuvel

01/10/2019 16:51:39
Quote Anchor link
Geert Huylebroeck op 01/10/2019 11:25:13:
De databank staat volledig in utf8_general_ci.

Maar dat is een collation, niet een character encoding.

Geert Huylebroeck op 01/10/2019 11:25:13:
Als ik met mb_detect_encoding kijk, dan zie ik dat de bestandsnamen ook in utf8 staan.

Dat is allemaal leuk en aardig, maar hoe maak je een connectie met je database? Gebruik je ook set_charset()?

En je zou natuurlijk eens kunnen kijken hoe dat er op byte-niveau allemaal uitziet. In MySQL kun je dit met HEX('waarde') doen, en in PHP met strtoupper(bin2hex($waarde)). Afwijkingen tussen die twee verklaren waarschijnlijk waarom je geen matches vindt. En geven ook aan dat er mogelijk onnodige (extra) vertalingen plaatsvinden wanneer je e.e.a. naar de database wegschrijft omdat set_charset() ontbreekt en er een andere/verkeerde character encoding wordt verondersteld.
 
Geert Huylebroeck

Geert Huylebroeck

01/10/2019 17:08:57
Quote Anchor link
De tabellen staan effectief in utf8 als default character set, ook op veld-niveau.
De verbinding staat ook in UTF8:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
mysqli_set_charset($link, "utf8")
.

Ik ga morgen eens proberen om die HEX waarden te vergelijken.

Maar wat als die twee effectief geen match hebben? Kan ik dan nog iets doen om toch tot een match te komen?
 
Thomas van den Heuvel

Thomas van den Heuvel

01/10/2019 17:16:32
Quote Anchor link
Dan heb je een concreet voorbeeld te pakken van een case die misgaat. Die kun je dan als startpunt gebruiken om de oorzaak van de afwijkende encoding te verklaren. Je zou dan kunnen proberen te reproduceren wat er misgaat. En als je dat kunt doen, dan weet je precies wat er misgaat en kun je een oplossing gaan formuleren.

Maar als je niet precies weet wat er misgaat dan is het in wezen onmogelijk om iets op te lossen. Je weet dan immers niet wat er aan de hand is.

EDIT: je zou ook kunnen opteren voor een compleet andere aanpak. Als de foto-informatie opgeslagen wordt in de database dan is er in principe geen noodzaak voor de foto's om een bepaalde naam te dragen. Je zou dan in wezen het bestand kunnen hernoemen naar het auto-increment id van het record (bv 12.jpg). Ik neem aan dat deze foto's nu ook niet enkel "beveiligd" zijn door het feit dat ze een voor anderen onbekende naam hebben en voor de rest volledig toegankelijk zijn?
Gewijzigd op 01/10/2019 17:19:38 door Thomas van den Heuvel
 
Geert Huylebroeck

Geert Huylebroeck

01/10/2019 17:43:16
Quote Anchor link
Bedankt alvast, ik test morgen verder uit.

Het opslagen van de foto’s in de databank is helaas geen optie. Het is zo dat ik de foto’s van de schoolfotograaf ontvang met een bepaalde bestandsnaam. Die moet ik voor een bepaalde applicatie omzetten naar de unieke sleutelwaarde van de leerling.

De foto’s worden via een zip-bestand geüploaded en van zodra ze verwerkt zijn (upload via API) meteen verwijderd.
 
Geert Huylebroeck

Geert Huylebroeck

02/10/2019 20:58:54
Quote Anchor link
Ik heb twee bestanden manueel bekeken en er zit inderdaad een verschil op beide HEX namen:

EjdaâSarah19.09.2005.jpg
92544 - sarah.ejdaa

File: 456A646161CC82536172616831392E30392E323030352E6A7067
DB: 456A6461C3A2536172616831392E30392E323030352E6A7067


MöllerElisabeth04.10.2002.jpg
23164 - elisabeth.moller

File: 4D6FCC886C6C6572456C6973616265746830342E31302E323030322E6A7067
DB: 4DC3B66C6C6572456C6973616265746830342E31302E323030322E6A7067

Het lijkt er dus op dat die speciale karakters dus een andere encodering hebben. De vraag is nu, hoe lost ik dit op?
 
Rob Doemaarwat

Rob Doemaarwat

02/10/2019 23:10:24
Quote Anchor link
Het zijn twee manieren om hetzelfde te bereiken:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
$file = '456A6461'.'61CC82'.'536172616831392E30392E323030352E6A7067';
//0x61 = a + utf8:CC82=COMBINING CIRCUMFLEX ACCENT
$db   = '456A6461'.'C3A2'.'536172616831392E30392E323030352E6A7067';
//    \xc3\xa2    LATIN SMALL LETTER A WITH CIRCUMFLEX

In de filenaam wordt dus een "a" gecombineerd met een "^" = "â".
In je database wordt gewoon direct een "â" gebruikt.
Effectief hetzelfde, maar binair niet.

Je zou dus iets kunnen maken wat al die combining karakters omzet naar enkele karakters (of in ieder geval een "vertaaltabel" maken die dit gewoon binair doet: '61CC82' => 'C3A2', enz). Of een functie zoeken die dit voor je kan doen (ik heb even kort met iconv() en mb_convert_encoding() zitten spelen, maar kon zo snel geen "magische config" vinden).
Gewijzigd op 02/10/2019 23:12:01 door Rob Doemaarwat
 
Thomas van den Heuvel

Thomas van den Heuvel

03/10/2019 01:43:28
Quote Anchor link
Oef. Dat was een avontuur.

En ik zie dat @Rob mij al voor was :/

Zoals @Rob al aangeeft zijn "6FCC88" en "C3B6" (de letter "o" met een umlaut) twee manieren om hetzelfde te zeggen, in de eerste variant is dit symbool (glyph) samengesteld uit twee zogenaamde "code points": een code point voor de letter o (0x6f) en een code point voor een trema (0xcc 0x88). De tweede variant is de zogenaamde "genormaliseerde" vorm.

Het woord "normaliseren" bleek hier cruciaal, PHP heeft hier een ingebouwde class voor, mits je PHP-versie nieuw genoeg is. Dit is onderdeel van de int(ernationa)l(ization) extensie.

Een simpele test om te kijken of dit bij jou out-of-the-box werkt:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php
$source
= '4D6FCC886C6C6572456C6973616265746830342E31302E323030322E6A7067';
$target = '4DC3B66C6C6572456C6973616265746830342E31302E323030322E6A7067';

if (Normalizer::normalize(hex2bin($source)) == hex2bin($target)) {
    echo 'fixed!';
}
else {
    echo 'not fixed :(';
}

?>

Je zou dan "fixed!" te zien moeten krijgen. En anders moet je deze extensie installeren en e.e.a. opnieuw starten.

EDIT: had trouwens tijdens deze speurtocht een coole toolsite gevonden: onlineutf8tools.com.
Gewijzigd op 03/10/2019 01:48:13 door Thomas van den Heuvel
 
Geert Huylebroeck

Geert Huylebroeck

03/10/2019 14:26:31
Quote Anchor link
Super! Hartelijk dank voor alle hulp! Het is inderdaad gelukt door die normalize toe te passen op de strings. Nu kan hij ze meteen terugvinden.

mvg
Geert
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.