2010-12-08 15 views
3

Was ist die einfachste und schnellste Weg, um zu überprüfen, ob Zeichenfolge einzelne URL oder TEXT ist (das könnte Urls enthalten)Wie trennt man mögliche URI von anderen Inhalten in PHP?

mögliche Szenarien:

// 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;"; 

ich versucht habe nativen PHP-Funktionen wie parse_url zu verwenden, filter_var aber keiner von ihnen funktioniert wie erwartet.

UPDATE 1

Um es klar zu machen, versuche ich, möglichst URI von Skript Inhalt zu trennen, die als DOM-Element eingefügt werden würden. Alle URLs würden als SRC-Attribut gehen und Ruhe als Inhalt, Beispiel:

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

UPDATE 2 von möglichem Inhalt zu analysieren ich zu dem Schluss gekommen, dass String, String weiße Leerzeichen oder Semikolon bedeuten, die nicht URI sein könnte, Ich vermute, dass dieses Muster mein Problem lösen könnte:

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

würde es alle möglichen Javascript/CSS-Code abdecken?

+3

Definieren Sie "URL". Werden sie immer das Protokollpräfix haben? Wenn nicht, was würde eine URL von einer zufälligen Zeichenfolge unterscheiden - die "www."? Möchten Sie nur für http oder ftp, scp, https ... testen? Was ist mit Benutzername @ Passwort: Hostname Präfixe?Was ist mit den relativen URLs '/ folder/file.php'? –

+1

Sie wissen, dass beide Fälle technisch gültige URLs sind, oder? Der Unterschied besteht darin, dass der erste wahrscheinlich zu einer gültigen Ressource führt, während der zweite eine Überprüfung/Überprüfung des Domänennamens zur Folge hat. – cdhowie

+0

Danke Pekka, ich habe das Szenario ohne Protokoll oder Domain vergessen. – Nazariy

Antwort

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"; 
} 

Dies würde produzieren:

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 

Update:

Nach dem letzten Update zu lesen. Wenn Sie HTML analysieren wollen. Verwenden Sie einen DOM-Parser wie:

http://simplehtmldom.sourceforge.net/

Beispiel:

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>"); 
    } 
} 

ausgeben würde, so etwas wie (HTML gestrippt):

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

, die näher an was ich Ich suche nach, aber in meinem Fall sollte das dritte und vierte Element im Array die Validierung nicht bestehen. – Nazariy

+0

Nein, ich erstelle einen HTML-Container mit DOMDocument und versuche, eine einzige Methode für das SCRIPT-Tag anstelle von zwei zu erstellen. – Nazariy

0

filter_var sollte tun, was Sie für eine einzelne URL wollen:

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

FILTER_SANITIZE_URL konvertiert $ Text in eine gültige URL und es ist nicht das, was ich versuche zu archivieren. – Nazariy

+0

Dann sollten Sie verwenden: 'if (filter_var ($ url, FILTER_VALIDATE_URL))' – Buddy

+0

FILTER_VALIDATE_URL funktioniert nicht wie erwartet und würde in zukünftigen Versionen von PHP behoben werden, würde es immer für Domänen mit Bindestrich – Nazariy

1

Diese Funktion gibt true zurück, wenn der übergebene Text ist eine URL. Es basiert auf einer Regex, die hier auf SO zu sehen ist.

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); 
} 

Sie können es versuchen, hier: http://www.exorithm.com/algorithm/view/validate_url

EDIT als Antwort auf einen Kommentar, wird diese Funktion URL-Fragmente wie /index.php oder 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 
} 

(Anmerkung validieren dass die leere Zeichenfolge gültig ist, Sie können also einen Sonderfall dafür wünschen)

+0

würde es für URL wie "/index.php" funktionieren? – Nazariy

+0

siehe bearbeitete Antwort –

Verwandte Themen