2008-10-10 8 views
2

Je ne suis pas vraiment un codeur, mais j'ai besoin d'écrire une simple instruction preg_replace en PHP qui va m'aider avec un plugin WordPress. Fondamentalement, j'ai besoin de code qui va chercher une chaîne, retirer l'ID de la vidéo, et renvoyer le code d'intégration avec l'ID vidéo inséré dans celui-ci.Écrire un preg_replace simple en PHP

En d'autres termes, je cherche ceci:

[youtube=http://www.youtube.com/watch?v=VIDEO_ID_HERE&hl=en&fs=1] 

et que vous voulez le remplacer par cette (en gardant l'ID vidéo de la même):

param name="movie" value="http://www.youtube.com/v/VIDEO_ID_HERE&hl=en&fs=1&rel=0 

Si possible, je Soyez toujours reconnaissant si vous pouviez expliquer comment vous avez utilisé les différentes barres obliques, carets et étoiles de Kleene dans le motif de recherche, c'est-à-dire le traduire de grep en anglais pour que je puisse apprendre. :-)

Merci!
Mike

Répondre

2
$str = preg_replace('/\[youtube=.*?v=([a-z0-9_-]+?)&.*?\]/i', 'param name="movie" value="http://www.youtube.com/v/$1&hl=en&fs=1&rel=0', $str); 

     / - Start of RE 
     \[ - A literal [ ([ is a special character so it needs escaping) 
     youtube= - Make sure we've got the right tag 
     .*? - Any old rubbish, but don't be greedy; stop when we reach... 
     v= - ...this text 
     ([a-z0-9_-]+?) - Take some more text (just z-a 0-9 _ and -), and don't be greedy. Capture it using(). This will get put in $1 
     &.*?\] - the junk up to the ending ] 
     /i - end the RE and make it case-insensitive for the hell of it 
+0

Ne pas être nitpicky, mais ne devriez-vous pas le faire rechercher uniquement alphanumérique/underscores comme la valeur de v? De cette façon, les gens ne peuvent pas être stupides là-dedans. –

+0

Belle explication des atomes de regex. Pourtant, Paolo a raison - ce modèle ne devrait pas accepter tous les personnages dans le cadre d'un identifiant de vidéo YouTube. –

0
$embedString = 'youtube=http://www.youtube.com/watch?v=VIDEO_ID_HERE&hl=en&fs=1'; 
preg_match('/v=([^&]*)/',$embedstring,$matches); 
echo 'param name="movie" value="http://www.youtube.com/v/'.$matches[1].'&hl=en&fs=1&rel=0'; 

essayer.

Le regex /v=([^&]*)/ fonctionne de cette façon:

  • il recherche v=
  • il enregistre alors le match au modèle à l'intérieur des parenthèses à $matches
  • [^&] lui indique pour correspondre à tout caractère sauf l'esperluette ('&')
  • * dit que nous voulons de 0 à n'importe quel engourdissement er de ces caractères dans le match
0

Un avertissement. Si le texte après .*? n'est pas trouvé immédiatement, le moteur regex continuera de rechercher sur toute la ligne, en sautant éventuellement à l'étiquette [youtube...] suivante. Il est souvent préférable d'utiliser [^\]]*? pour limiter la recherche entre parenthèses.

Basé sur RoBorgs Réponse:

$str = preg_replace('/\[youtube=[^\]]*?v=([^\]]*?)&[^\]]*?\]/i', ...) 

[^\]] correspond à tout caractère sauf ']'.

6

SOYEZ PRUDENT! S'il s'agit d'un système de type BBCode avec une entrée utilisateur, ces deux autres solutions vous rendraient vulnérables aux attaques XSS.

Vous avez plusieurs façons de vous protéger contre cela. Avoir la regex explicitement interdire les caractères qui pourraient vous causer des problèmes (ou, permettre seulement ceux valables pour un id vidéo youtube), ou désinfecter l'entrée et utiliser plutôt preg_match, que je vais illustrer ci-dessous à partir de regex de RoBorg.

<?php 

$input = "[youtube=http://www.youtube.com/watch?v=VIDEO_ID_HERE&hl=en&fs=1]"; 

if (preg_match('/\[youtube=.*?v=(.*?)&.*?\]/i', $input, $matches)) 
{ 
    $sanitizedVideoId = urlencode(strip_tags($matches[1])); 
    echo 'param name="movie" value="http://www.youtube.com/v/' . $sanitizedVideoId . '&hl=en&fs=1&rel=0'; 
} else { 
    // Not valid input 
} 

Voici un exemple de ce type d'attaque en action

<?php 

$input = "[youtube=http://www.youtube.com/watch?v=\"><script src=\"http://example.com/xss.js\"></script>&hl=en&fs=1]"; 

// Is vulnerable to XSS 
echo preg_replace('/\[youtube=.*?v=(.*?)&.*?\]/i', 'param name="movie" value="http://www.youtube.com/v/$1&hl=en&fs=1&rel=0', $input); 
echo "\n"; 

// Prevents XSS 
if (preg_match('/\[youtube=.*?v=(.*?)&.*?\]/i', $input, $matches)) 
{ 
    $sanitizedVideoId = urlencode(strip_tags($matches[1])); 
    echo 'param name="movie" value="http://www.youtube.com/v/' . $sanitizedVideoId . '&hl=en&fs=1&rel=0'; 
} else { 
    // Not valid input 
} 
1

J'avoind des expressions régulières dans ce cas, si possible, parce que: qui garantit que le querystring dans la première URL sera toujours être dans ce format?

j'utiliser parse_url($originalURL, PHP-URL-QUERY); et ensuite en boucle le tableau retourné trouver la paire « name = valeur » correcte pour la partie V de la chaîne de requête: quelque chose comme:

$originalURL = 'http://www.youtube.com/watch?v=VIDEO_ID_HERE&hl=en&fs=1'; 

foreach(parse_url($originalURL, PHP_URL_QUERY) as $keyvalue) 
{ 
    if (strlen($keyvalue) > 2 && substr($keyvalue, 0, 2) == 'v=') 
    { 
     $videoId = substr($keyvalue, 2); 
     break; 
    } 
} 

$newURL = sprintf('http://www.youtube.com/v/%s/whatever/else', url_encode($videoId)); 

P.S. écrit dans la zone de texte SO, non testé.

Questions connexes