[PHP] regex 'preg_replace'

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • X-trace
  • Registratie: Juni 2004
  • Laatst online: 02-11-2024
Ik heb een stuk tekst in een variabele (komt uit database). Deze wil ik scannen op het voorkomen van een tag: [voorbeeld:X]. Hierin is X variabel en een integer.

In een functie (welke $content returnt) heb ik nu de volgende code om hem te matchen, welke op zich een andere functie (getForm) aanroept:
PHP:
1
$content = preg_replace('/\[voorbeeld:(.*?)\]/', getForm('$1'), $content);


De functie 'getForm()' ziet er momenteel als volgt uit:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
function getForm($id) {
    global $wpdb;
    global $databaseTable;
    
    $query = mysql_query("  SELECT
                                    id,
                                    formIdentity
                            FROM
                                    ".$databaseTable."
                            WHERE
                                    id=".trim($id)."
                        ") or die (mysql_error());
    $array = mysql_fetch_assoc($query) or die (mysql_error());
    if(isset($array['formIdentity'])) {
        return $array['formIdentity'].':'.$id.' - formulier met id:'.$array['formIdentity'];
    } else {
        return $array.':'.$id.' - bestaat niet';
    }
}


Ik krijg de error: Unknown column '$1' in 'where clause'

Maar als ik tde mysql_query vervang met de Wordpress functie (onderstaande code) krijg ik de volgende output:
PHP:
1
2
3
4
5
6
7
8
    $array = $wpdb->get_row("   SELECT
                                        id,
                                        formIdentity
                                FROM
                                        ".$databaseTable."
                                WHERE
                                        id=".trim($id)."
                            ",ARRAY_A);

:1 - bestaat niet
:10 - bestaat niet
:16 - bestaat niet

Hierin zie je dat $id in dit geval wel een waarde heeft. Waarom bij de WHERE clause van 1e query dan niet?

You cannot not communicate


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Je geeft de returnvalue van getForm('$1') nu mee als 2e parameter van preg_replace. GetForm krijgt dus letterlijk de string '$1'. En dat kan je ook gewoon zien aan de mysql error natuurlijk. ;)

{signature}


Acties:
  • 0 Henk 'm!

  • X-trace
  • Registratie: Juni 2004
  • Laatst online: 02-11-2024
Het is idd de bedoeling dat de integer hier wordt meegegeven. Ben zelf geen regex expert en heb al lang lopen zoeken. Zou dus graag willen weten hoe ik de int (na [voorbeeld: en voor de ]) mee kan geven aan de functie.

You cannot not communicate


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
De tweede parameter van preg_match is een string of array van strings. Je kunt er dus geen functie aanroepen voor iedere match. Wat er zal gebeuren hier, is dat eerst getForm('$1') aangeroepen wordt, en als die een string teruggeeft dat alle [voorbeeld:X] door diezelfde string vervangen worden.

Verder: waarom doe je trim($id) in je query? $id hoort een integer te zijn, en een trim doet daar niets mee. En als het een integer moet zijn, waarom match je dan op alle karakters met je regex?

[ Voor 14% gewijzigd door GlowMouse op 02-01-2008 18:29 . Reden: had het toch goed, stomme testcase :( ]


Acties:
  • 0 Henk 'm!

  • X-trace
  • Registratie: Juni 2004
  • Laatst online: 02-11-2024
ok, duidelijk. Dit gaat dus niet werken. Zal ik op zoek gaan naar een alternatief.

De reden van trim is dat de tag door gebruikers wordt ingevoerd. En gebruikers (Wordpress) zijn niet altijd even netjes bij het invoeren. Deed het meer 'voor de zekerheid', maar wist dus niet dat het op een integer geen effect had. Overigens check ik niet of het een integer is -> er wordt gekeken of de id voorkomt in de database. Zo niet krijg je dat wel te zien.

You cannot not communicate


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
En dat is dus de verkeerde mentaliteit. Jij weet dat het een integer moet zijn, dus check je dat. Tevens kan je casten naar int, en zoals gezegd uberhaupt alleen cijfers matchen in je regex.

Voor argumenten, zie eindeloze hoeveelheid leesmateriaal over 'sql injection' en het niet mogen vertrouwen van user input.

{signature}


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Waarom de Wordpresscode toch lijkt te werken, is omdat je daar het programma niet af laat sluiten bij een fout. Als je getForm('$1') aanroept, krijg je ':$1 - bestaat niet' terug. Omdat daar $1 nog in voorkomt, wordt die later toch door de juiste id's vervangen.
Een aanpak die mogelijk is, is eerst alle id's vinden die voorkomen. Daarna kun je voor ieder id een str_replace uitvoeren.
Wat betreft veiligheid is het goed dat je daaraan denkt, maar alleen kijken of het id echt bestaat is onvoldoende (en de trim helpt daar niet bij). Om zeker te weten dat alleen integers gematched worden, kun je \d gebruiken ipv een punt. Gebruik daarnaast een + ipv een * om te voorkomen dat [voorbeeld:] ook gematched wordt. Je hebt dan zeker een integer te pakken. Je hoeft dan pas alleen nog maar te kijken of hij bestaat. In andere gevallen, waar je nog niet zeker weet of je met een integer te maken hebt, moet je daar expliciet op controleren.
Mocht je query toch een fout bevatten, dan is het van groot belang dat de gebruiker die fout niet te zien krijgt. Daaruit zou hij namelijk informatie uit kunnen halen die van belang is om je database naar de *** te helpen. In dat geval wil je eigenlijk direct een mailtje ontvangen zodat je het kunt fixen, en geef je de gebruiker een vriendelijke maar informatieloze melding dat er iets mis is.

[ Voor 12% gewijzigd door GlowMouse op 02-01-2008 18:37 ]


Acties:
  • 0 Henk 'm!

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Je moet hier ook niet preg_replace gebruiken maar preg_replace_callback ;)

Intentionally left blank

Pagina: 1