Если бы вы использовали метод jQuery .html () для ненадежного ввода, ваше веб-приложение было бы уязвимо для атаки межсайтового скриптинга (XSS), которую можно было бы использовать, отправив вредоносный твит. Лучший способ избежать этой проблемы безопасности - добавлять каждую часть твита по отдельности, используя правильные функции jQuery, которые используют функции DOM веб-браузера для HTML-строк.
Сначала объедините два регулярных выражения в одно, используя чередование регулярных выражений (символ |
). Для целей моего примера кода регулярное выражение имени пользователя в Твиттере равно /@\w+/gi
, а регулярное выражение URL-адреса равно /(?:https?|ftp):\/\/.*?\..*?(?=\W?\s)/gi
. Эти регулярные выражения не совпадают с теми, что были в исходном вопросе; оригинальное регулярное выражение URL, похоже, не работает правильно, и нам не нужно использовать группы захвата. Таким образом, объединенное регулярное выражение равно /@\w+|(?:https?|ftp):\/\/.*?\..*?(?=\W?\s)/gi
.
При каждом совпадении регулярного выражения надежно добавляйте текст, предшествующий совпадению, в контейнер. Для этого в jQuery создайте пустой элемент span и используйте метод .text () для вставки текста внутрь. Использование $ ('text here') оставит широко открытую дыру в XSS. Что если содержимое твита составляет <script>alert(document.cookie)</script>
?
Проверьте первый символ совпадения, чтобы определить, как он должен быть отформатирован. Имена пользователей Twitter начинаются с "@", но URL-адреса не могут.
Отформатируйте совпадение и добавьте его в контейнер. Опять же, не передавайте ненадежный ввод функции $ или jQuery; используйте метод .attr () для добавления таких атрибутов, как href и метод .text () для добавления текста ссылки.
После того, как все совпадения были обработаны, добавьте последнюю часть текста в виде простого текста, которая не была добавлена в шаге 3 или 4.
Пример кода (также на http://jsfiddle.net/6X6xD/3/):
var tweet = 'joined @BundleHunt for a chance to win the 2010 Mega Bundle! http://bundlehunt.com * Only 10 Days Left! URL containing an at sign: http://www.last.fm/event/1196311+Live+@+Public+Assembly. This should not work: <scr'+'ipt>alert(document.cookie)</scr'+'ipt>';
var combinedRegex = /@\w+|(?:https?|ftp):\/\/.*?\..*?(?=\W?\s)/gi,
container = $('#tweet-container');
var result, prevLastIndex = 0;
combinedRegex.lastIndex = 0;
while((result = combinedRegex.exec(tweet))) {
// Append the text coming before the matched entity
container.append($('<span/>').text(tweet.slice(prevLastIndex, result.index)));
if(result[0].slice(0, 1) == "@") {
// Twitter username was matched
container.append($('<a/>')
// .slice(1) cuts off the first character (i.e. "@")
.attr('href', 'http://twitter.com/' + encodeURIComponent(result[0].slice(1)))
.text(result[0])
);
} else {
// URL was matched
container.append($('<a/>')
.attr('href', result[0])
.text(result[0])
);
}
// prevLastIndex will point to the next plain text character to be added
prevLastIndex = combinedRegex.lastIndex;
}
// Append last plain text part of tweet
container.append($('<span/>').text(tweet.slice(prevLastIndex)));
Примечание. Старые версии этого ответа рекомендовали использовать метод .html (). Поскольку это серьезная проблема безопасности, как уже упоминалось выше, я использовал кнопку редактирования, чтобы опубликовать свой новый ответ, удалив старый из вида.