2010-12-08 41 views
3

Quelle est la plus simple et la plus rapide pour vérifier si la chaîne est URL unique ou TEXT (qui peut contenir des urls)Comment séparer l'URI possible d'un autre contenu en PHP?

scénarios possibles:

// successful scenario 
$example[] = 'http://sub-domain.my-domain.com/folder/file.php?some=param'; 
// successful scenario 
$example[] = '/assets/scripts/jquery.min.js?v=1.4'; 
// successful scenario 
$example[] = 'jquery.min.js'; 
// this scenario should fail validation 
$example[] = "http://www.domain.com welcome text\n and some other http://www.domain.com"; 
// this scenario should fail validation 
$example[] = "scriptVar=50;"; 

J'ai essayé d'utiliser les fonctions PHP natives comme parse_url, filter_var mais pas d'entre eux fonctionnent comme prévu.

MISE À JOUR 1

Pour le rendre plus clair, je suis en train de séparer URI possible du contenu du script qui serait inséré comme élément DOM. Tous les urls iraient comme attribut SRC et de repos en tant que contenu, par exemple:

<script type="text/javascript" src="{$string}"></script> 
<script type="text/javascript">{$string}</script> 

MISE À JOUR 2 En analysant le contenu possible que je viens à la conclusion que la chaîne contenant caractère d'espace blanc ou virgule signifie que la chaîne ne pouvait pas être URI, Je présume que ce modèle pourrait résoudre mon problème:

preg_match('/[\s]|[;]/', $string); 

serait-il couvrir tout le code javascript/css possible?

+3

Définir "URL". Auront-ils toujours le préfixe de protocole? Si non, que dirait une URL en dehors d'une chaîne aléatoire - le 'www.''? Voulez-vous tester http uniquement ou aussi ftp, scp, https ...? Qu'en est-il du nom d'utilisateur @ mot de passe: préfixe hostname?Qu'en est-il des URL relatives '/ dossier/fichier.php'? –

+1

Vous savez que, techniquement, ces deux cas sont des URL valides, n'est-ce pas? La différence est que le premier aboutira probablement à une ressource valide, tandis que le second échouera à la validation/recherche de nom de domaine. – cdhowie

+0

Merci Pekka, j'ai oublié scénario sans protocole ou domaine. – Nazariy

Répondre

2
$exampleData = Array(
    'http://sub-domain.my-domain.com/folder/file.php?some=param', 
    '/assets/scripts/jquery.min.js?v=1.4', 
    '<a href="/assets/scripts/jquery.min.js?v=1.4">', 
    '<a href="assets/scripts/jquery.min.js?v=1.4">', 
    'http://www.domain.com welcome text\n and some other http://www.domain.com', 
); 

foreach($exampleData as $example) 
{ 
    echo "Trying \"" . $example . "\" -> "; 

    echo (preg_match('%((http(s)?://|www\.)[^ \r\n]+|<a.+?href=(\'|")(http(s)?://|www\.|[^#])[^\4\r\n]*?\4.*?>)%i', $example)) ? 
    "Match" : "No match"; 

    echo "\r\n"; 
} 

Ceci produirait:

Trying "http://sub-domain.my-domain.com/folder/file.php?some=param" -> Match 
Trying "/assets/scripts/jquery.min.js?v=1.4" -> No match 
Trying "<a href="/assets/scripts/jquery.min.js?v=1.4">" -> Match 
Trying "<a href="assets/scripts/jquery.min.js?v=1.4">" -> Match 
Trying "http://www.domain.com welcome text\n and some other http://www.domain.com" -> Match 

Mise à jour:

Après avoir lu votre dernière mise à jour. Si vous voulez analyser HTML. Utilisez un analyseur DOM comme:

http://simplehtmldom.sourceforge.net/

Exemple:

include_once('simple_html_dom.php'); 

$dom = file_get_html('http://www.stackoverflow.com/'); 

foreach($dom->find('script') as $scriptElement) 
{ 
    if(strlen(trim($scriptElement->src)) > 0) 
    { 
     // Script with URI set 
     echo "<strong>Found script with URI</strong>"; 
     echo "<p>" . $scriptElement->src . "</p>"; 
    } 
    else 
    { 
     // Script with content 
     echo "<strong>Found script with content</strong>"; 
     echo("<p>" . nl2br(htmlspecialchars($scriptElement->innertext)) . "</p>"); 
    } 
} 

génèrerait quelque chose comme (HTML dépouillé):

Found script with URI 
http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js 

Found script with URI 
http://sstatic.net/js/master.min.js?v=afc76d4deac3 

Found script with content  
var imagePath='http://sstatic.net/stackoverflow/img/'; 
var inboxUnviewedCount = -1; 

...etc 
+0

qui est plus proche de ce que je Je recherche, mais dans mon cas, le troisième et quatrième élément dans le tableau devrait échouer à la validation. – Nazariy

+0

Non, je construis un conteneur HTML en utilisant DOMDocument et essaye de créer une seule méthode pour la balise SCRIPT au lieu de deux. – Nazariy

0

filter_var devrait faire ce que vous voulez pour une seule URL:

<?php 
$safe_url = filter_var($unsafe_url, FILTER_SANITIZE_URL); 
?> 
+0

FILTER_SANITIZE_URL convertira $ text en URL valide et ce n'est pas ce que j'essaye d'archiver. – Nazariy

+0

Ensuite, vous devriez utiliser: 'if (filter_var ($ url, FILTER_VALIDATE_URL))' – Buddy

+0

FILTER_VALIDATE_URL ne fonctionne pas comme prévu et serait corrigé dans les prochaines versions de PHP, il échouerait toujours pour les domaines contenant le trait d'union – Nazariy

1

Cette fonction retourne vrai si le texte adopté est une URL. Il est basé sur une regex vue ici sur SO. en réponse http://www.exorithm.com/algorithm/view/validate_url

EDIT pour commenter, cette fonction validera des fragments d'URL comme index.php ou index.php

function validate_url_fragment ($url) 
{ 
    $regex = '/^(((\/?([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)*'; //path 
    $regex .= '(\?([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)'; //query string 
    $regex .= '?)?)?'; //path and query string optional 
    $regex .= '(#([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)?'; //fragment 
    $regex .= '$/i'; 

    return (preg_match($regex, $url) ? true : false); 
} 

if (validate_url_fragment($url) || validate_url($url)) { 
    //is url 
} else { 
    //not url 
} 

(Note:

function validate_url ($url) 
{ 
    $regex = '/^(https?|ftp):\/\/'; //protocol 
    $regex .= '(([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+'; //username 
    $regex .= '(:([a-z0-9$_\.\+!\*\'\(\),;\?&=-]|%[0-9a-f]{2})+)?'; //password 
    $regex .= '@)?'; //auth requires @ 
    $regex .= '((([a-z0-9][a-z0-9-]*[a-z0-9]\.)*'; //domain segments AND 
    $regex .= '[a-z][a-z0-9-]*[a-z0-9]'; //top level domain OR 
    $regex .= '|((\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])\.){3}'; 
    $regex .= '(\d|[1-9]\d|1\d{2}|2[0-4][0-9]|25[0-5])'; //IP address 
    $regex .= ')(:\d+)?'; //port 
    $regex .= ')(((\/+([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)*'; //path 
    $regex .= '(\?([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)'; //query string 
    $regex .= '?)?)?'; //path and query string optional 
    $regex .= '(#([a-z0-9$_\.\+!\*\'\(\),;:@&=-]|%[0-9a-f]{2})*)?'; //fragment 
    $regex .= '$/i'; 

    return (preg_match($regex, $url) ? true : false); 
} 

Vous pouvez l'essayer ici que la chaîne vide est valide, donc vous pouvez vouloir un cas spécial pour cela)

+0

cela fonctionnerait-il pour url comme "/index.php"? – Nazariy

+0

voir la réponse éditée –