Development PHP : linkify user input

Discussion in 'Software' started by Draxin, 23 Sep 2008.

  1. Draxin

    Draxin Seeker of Photons

    Joined:
    29 Nov 2001
    Posts:
    965
    Likes Received:
    5
    I would like to be able to create a link from user input.
    The problem is the user input is a textarea and may not always contain a link.

    Id like to be able to do this without haveing to have the user mark up their text.

    I have the following
    PHP:
    $output preg_replace("/(http:\/\/|(www\.))(([^\s<]{4,68})[^\s<]*)/"'<a href="http://$2$3" rel="nofollow">$2$4</a>'$input);
    but it has some problems.
    if the text to be made into a link is followed by a <br /> then everything after that until the end of the input string is converted into a link, not only that but the <br /> is part of the link text and thus automatically making it useless link.

    regular expressions / preg_replace arent really my thing.

    anyone care to help me out for a cookie?
     
  2. Firehed

    Firehed Why not? I own a domain to match.

    Joined:
    15 Feb 2004
    Posts:
    12,574
    Likes Received:
    16
    I'm not great at regexes either, but I think if you change the [^\s<]* to [^\s\<]* it may work - I'm pretty sure the less than sign needs to be escaped. Alternately, you can try
    PHP:
    <?php
    $text 
    ereg_replace("[[:alpha:]]+://[^<>[:space:]]+[[:alnum:]/]",
                         
    "<a href=\"\\0\">\\0</a>"$text);
    ?>
    which is from the ereg_replace manual page.

    You could just use str_replace to add in a space before <br /> tags before running the regex, too :)
     
  3. koola

    koola Minimodder

    Joined:
    11 Jul 2004
    Posts:
    2,401
    Likes Received:
    10
    I've fixed the regex.

    PHP:
    $input "<span>test</span>www.test.com <br /><div id='test'><a href=\"http://www.test.net\">testing</a></div><br /> http://testing.org.uk ";

    $output preg_replace("/[\s|>]((http:\/\/|www\.)([a-z0-9\_\-]{4,64}([.][a-z]{2,4})+))[\s|\.|\,|\/|<]/i""<a href=\"http://$1\" rel=\"nofollow\">$1</a>"$input);

    echo 
    $output;
    [edit] The previous was broken for .co.uk names
     
    Last edited: 23 Sep 2008
  4. Draxin

    Draxin Seeker of Photons

    Joined:
    29 Nov 2001
    Posts:
    965
    Likes Received:
    5
    ok well it works better but it still has issues if there is a line break after the text that is to be linkified.

    id do an str_replace for <br /> but the raw newline is going into the DB '\n' so i tried a str_replace on that and it did no good

    on data recall the returned data is run through nl2br()

    should i linkify on insert or on recall? (that might be a stupid question)
     
    Last edited: 23 Sep 2008
  5. Jamie

    Jamie ex-Bit-Tech code junkie

    Joined:
    12 Mar 2001
    Posts:
    8,180
    Likes Received:
    54
    You can't string replace a newline character (\n). You can however do it with a regular expression replace.
     
  6. koola

    koola Minimodder

    Joined:
    11 Jul 2004
    Posts:
    2,401
    Likes Received:
    10
    This works for me :)

    PHP:
    $input "
    <br />www.test1.com sub.domain.test2.name
    <br />
    <span>http://sub.domain.test3.org.uk</span><br />
        <div id=\"test\">
            <a href=\"http://www.test.net\">testing</a>
        </div>
    <br />
    www.test4.uk.net<br />"
    ;

    $pattern '{((http://)?([a-zA-Z0-9-.]+)(com|net|co.uk|uk.net|org.uk|name)(?!".*>))}';

    $output preg_replace($pattern"<a href=\"$1\" rel=\"nofollow\">$1</a>"$input);

    echo 
    "<pre>";
    echo 
    htmlspecialchars($output);
    echo 
    "</pre>";
    [edit] Final regex works perfectly :D
     
    Last edited: 24 Sep 2008
  7. Draxin

    Draxin Seeker of Photons

    Joined:
    29 Nov 2001
    Posts:
    965
    Likes Received:
    5
    So here's what i have i know its messy but right now Im just trying to get ti to work then i will streamline it
    But im still not having any luck with it. If the text is followed by a newline it breaks the linkify

    PHP:
            $body mysql_real_escape_string(strip_tags(stripslashes($_POST['post']), '<a></a><b></b><img>'));
            
            
    $body preg_replace("/[\n]/",' \n',$body); // strips newline and adds a space buffered newline
            
    $body preg_replace("/(http:\/\/|www\.)([a-z0-9\_\.\-]{4,64}[a-z]{2,6})([\s|\/|<])/i"'<a href="http://$2" rel="nofollow">$1$2</a>$3'$body);  // Linkify properly formatted text
    should i just pass it through nl2br() then buffer the <br />'s with a space and then linkify it? for simplicity / "Just make it work" sake?
     
  8. koola

    koola Minimodder

    Joined:
    11 Jul 2004
    Posts:
    2,401
    Likes Received:
    10
    This should work correctly now.

    PHP:
    $input "
    www.test1.com sub.domain.test3.co.uk

    www.testt.net blah blah

    www.test4.co.uk
    text"
    ;

    $body mysql_real_escape_string(strip_tags(stripslashes($input), '<a></a><b></b><img>'));

    $output preg_replace("/(http:\/\/|www\.)([a-z0-9\_\.\-]{4,64}[a-z]{2,6})(\\n)*/i"'<a href="http://$2" rel="nofollow">$1$2</a>'$body);

    echo 
    "<pre>";
    echo 
    htmlspecialchars($output);
    echo 
    "</pre>";
     
    Last edited: 25 Sep 2008

Share This Page