Saltar al contenido

Reemplazar URL en texto con enlaces HTML

Revisamos cada noticia de nuestro sitio web con el objetivo de mostrarte siempre la información con la mayor veracidad y actual.

Solución:

Veamos los requisitos. Tiene texto sin formato proporcionado por el usuario, que desea mostrar con URL con hipervínculos.

  1. El protocolo “http: //” prefix debe ser opcional.
  2. Deben aceptarse tanto los dominios como las direcciones IP.
  3. Se debe aceptar cualquier dominio de nivel superior válido, por ejemplo, .aero y .xn – jxalpdlp.
  4. Deben permitirse los números de puerto.
  5. Las URL deben permitirse en contextos de oraciones normales. Por ejemplo, en “Visite stackoverflow.com.”, El punto final no forma parte de la URL.
  6. Probablemente también desee permitir URL “https: //”, y quizás también otras.
  7. Como siempre, cuando se muestra el texto proporcionado por el usuario en HTML, desea evitar las secuencias de comandos entre sitios (XSS). Además, querrá que los símbolos de unión en las URL se escapen correctamente como &.
  8. Probablemente no necesite soporte para direcciones IPv6.
  9. Editar: Como se señaló en los comentarios, la compatibilidad con direcciones de correo electrónico es definitivamente una ventaja.
  10. Editar: Solo se admitirá la entrada de texto sin formato; no se deben respetar las etiquetas HTML en la entrada. (La versión de Bitbucket admite la entrada HTML).

Editar: Consulte GitHub para obtener la última versión, con soporte para direcciones de correo electrónico, URL autenticadas, URL entre comillas y paréntesis, entrada HTML, así como una lista de TLD actualizada.

Aquí está mi opinión:

alert('Remember kids: Say no to XSS-attacks! Always HTML escape untrusted input!');
EOD;

$rexProtocol = '(https?://)?';
$rexDomain   = '((?:[-a-zA-Z0-9]1,63.)+[-a-zA-Z0-9]2,63|(?:[0-9]1,3.)3[0-9]1,3)';
$rexPort     = '(:[0-9]1,5)?';
$rexPath     = '(/[!$-/0-9:;[email protected]_':;!a-zA-Zx7f-xff]*?)?';
$rexQuery    = '(?[!$-/0-9:;[email protected]_':;!a-zA-Zx7f-xff]+?)?';
$rexFragment = '(#[!$-/0-9:;[email protected]_':;!a-zA-Zx7f-xff]+?)?';

// Solution 1:

function callback($match)

    // Prepend http:// if no protocol specified
    $completeUrl = $match[1] ? $match[0] : "http://$match[0]";

    return ''
        . $match[2] . $match[3] . $match[4] . '';


print "
";
print preg_replace_callback("&\b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:"]?(s|$))&",
    'callback', htmlspecialchars($text));
print "

";

  • Para escapar correctamente de los caracteres
  • Como lo demuestra el “Y recuerda, nadie es perfecto”. (en la que recuerde, nadie es tratado como una URL, debido al espacio que falta), podría ser necesario realizar más comprobaciones sobre los dominios de nivel superior válidos.

Editar: El siguiente código corrige los dos problemas anteriores, pero es un poco más detallado ya que estoy más o menos reimplementando preg_replace_callback utilizando preg_match.

// Solution 2:

$validTlds = array_fill_keys(explode(" ", ".aero .asia .biz .cat .com .coop .edu .gov .info .int .jobs .mil .mobi .museum .name .net .org .pro .tel .travel .ac .ad .ae .af .ag .ai .al .am .an .ao .aq .ar .as .at .au .aw .ax .az .ba .bb .bd .be .bf .bg .bh .bi .bj .bm .bn .bo .br .bs .bt .bv .bw .by .bz .ca .cc .cd .cf .cg .ch .ci .ck .cl .cm .cn .co .cr .cu .cv .cx .cy .cz .de .dj .dk .dm .do .dz .ec .ee .eg .er .es .et .eu .fi .fj .fk .fm .fo .fr .ga .gb .gd .ge .gf .gg .gh .gi .gl .gm .gn .gp .gq .gr .gs .gt .gu .gw .gy .hk .hm .hn .hr .ht .hu .id .ie .il .im .in .io .iq .ir .is .it .je .jm .jo .jp .ke .kg .kh .ki .km .kn .kp .kr .kw .ky .kz .la .lb .lc .li .lk .lr .ls .lt .lu .lv .ly .ma .mc .md .me .mg .mh .mk .ml .mm .mn .mo .mp .mq .mr .ms .mt .mu .mv .mw .mx .my .mz .na .nc .ne .nf .ng .ni .nl .no .np .nr .nu .nz .om .pa .pe .pf .pg .ph .pk .pl .pm .pn .pr .ps .pt .pw .py .qa .re .ro .rs .ru .rw .sa .sb .sc .sd .se .sg .sh .si .sj .sk .sl .sm .sn .so .sr .st .su .sv .sy .sz .tc .td .tf .tg .th .tj .tk .tl .tm .tn .to .tp .tr .tt .tv .tw .tz .ua .ug .uk .us .uy .uz .va .vc .ve .vg .vi .vn .vu .wf .ws .ye .yt .yu .za .zm .zw .xn--0zwm56d .xn--11b5bs3a9aj6g .xn--80akhbyknj4f .xn--9t4b11yi5a .xn--deba0ad .xn--g6w251d .xn--hgbk6aj7f53bba .xn--hlcj6aya9esc7a .xn--jxalpdlp .xn--kgbechtv .xn--zckzah .arpa"), true);

$position = 0;
while (preg_match("\b$rexProtocol$rexDomain$rexPort$rexPath$rexQuery$rexFragment(?=[?.!,;:"]?(s", $text, &$match, PREG_OFFSET_CAPTURE, $position))
 isset($validTlds[$tld]))
    
        // Prepend http:// if no protocol specified
        $completeUrl = $match[1][0] ? $url : "http://$url";

        // Print the hyperlink.
        printf('%s', htmlspecialchars($completeUrl), htmlspecialchars("$domain$port$path"));
    
    else
    
        // Not a valid URL.
        print(htmlspecialchars($url));
    

    // Continue text parsing from after the URL.
    $position = $urlPosition + strlen($url);


// Print the remainder of the text.
print(htmlspecialchars(substr($text, $position)));

Aquí hay algo que encontré que está probado y probado

function make_links_blank($text)

  return  preg_replace(
     array(
       '/(?(?=]*>.+)
             (?:]*>.+)
             

Esto funciona para mi. Y funciona para correos electrónicos y URL. Perdón por responder mi propia pregunta. 🙁

Pero este es el único que funciona

Aquí está el enlace donde lo encontré: http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/PHP/Q_21878567.html

Sry de antemano por ser un intercambio de expertos.

Ustedes chicos están hablando de cosas complejas y avanzadas, lo cual es bueno para alguna situación, pero sobre todo necesitamos una solución simple y descuidada. ¿Qué tal simplemente esto?

preg_replace('/(http[s]0,1://S4,)s0,/ims', '$1 ', $text_msg);

Pruébelo y déjeme saber qué URL loca no satisface.

Reseñas y puntuaciones

Al final de la post puedes encontrar las reseñas de otros desarrolladores, tú igualmente puedes mostrar el tuyo si dominas el tema.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *