ktexttohtmltest.cpp 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484
  1. /*
  2. SPDX-FileCopyrightText: 2005 Ingo Kloecker <kloecker@kde.org>
  3. SPDX-FileCopyrightText: 2007 Allen Winter <winter@kde.org>
  4. SPDX-License-Identifier: LGPL-2.0-only
  5. */
  6. #include "ktexttohtmltest.h"
  7. #include "kcoreaddons_debug.h"
  8. #include "../src/lib/text/ktexttohtml.h"
  9. #include "../src/lib/text/ktexttohtml_p.h"
  10. #include <QDebug>
  11. #include <QTest>
  12. #include <QUrl>
  13. QTEST_MAIN(KTextToHTMLTest)
  14. Q_DECLARE_METATYPE(KTextToHTML::Options)
  15. #ifndef Q_OS_WIN
  16. void initLocale()
  17. {
  18. setenv("LC_ALL", "en_US.utf-8", 1);
  19. }
  20. Q_CONSTRUCTOR_FUNCTION(initLocale)
  21. #endif
  22. void KTextToHTMLTest::testGetEmailAddress()
  23. {
  24. // empty input
  25. const QString emptyQString;
  26. KTextToHTMLHelper ll1(emptyQString, 0);
  27. QVERIFY(ll1.getEmailAddress().isEmpty());
  28. // no '@' at scan position
  29. KTextToHTMLHelper ll2(QStringLiteral("foo@bar.baz"), 0);
  30. QVERIFY(ll2.getEmailAddress().isEmpty());
  31. // '@' in local part
  32. KTextToHTMLHelper ll3(QStringLiteral("foo@bar@bar.baz"), 7);
  33. QVERIFY(ll3.getEmailAddress().isEmpty());
  34. // empty local part
  35. KTextToHTMLHelper ll4(QStringLiteral("@bar.baz"), 0);
  36. QVERIFY(ll4.getEmailAddress().isEmpty());
  37. KTextToHTMLHelper ll5(QStringLiteral(".@bar.baz"), 1);
  38. QVERIFY(ll5.getEmailAddress().isEmpty());
  39. KTextToHTMLHelper ll6(QStringLiteral(" @bar.baz"), 1);
  40. QVERIFY(ll6.getEmailAddress().isEmpty());
  41. KTextToHTMLHelper ll7(QStringLiteral(".!#$%&'*+-/=?^_`{|}~@bar.baz"), qstrlen(".!#$%&'*+-/=?^_`{|}~"));
  42. QVERIFY(ll7.getEmailAddress().isEmpty());
  43. // allowed special chars in local part of address
  44. KTextToHTMLHelper ll8(QStringLiteral("a.!#$%&'*+-/=?^_`{|}~@bar.baz"), qstrlen("a.!#$%&'*+-/=?^_`{|}~"));
  45. QCOMPARE(ll8.getEmailAddress(), QStringLiteral("a.!#$%&'*+-/=?^_`{|}~@bar.baz"));
  46. // '@' in domain part
  47. KTextToHTMLHelper ll9(QStringLiteral("foo@bar@bar.baz"), 3);
  48. QVERIFY(ll9.getEmailAddress().isEmpty());
  49. // domain part without dot
  50. KTextToHTMLHelper lla(QStringLiteral("foo@bar"), 3);
  51. QVERIFY(lla.getEmailAddress().isEmpty());
  52. KTextToHTMLHelper llb(QStringLiteral("foo@bar."), 3);
  53. QVERIFY(llb.getEmailAddress().isEmpty());
  54. KTextToHTMLHelper llc(QStringLiteral(".foo@bar"), 4);
  55. QVERIFY(llc.getEmailAddress().isEmpty());
  56. KTextToHTMLHelper lld(QStringLiteral("foo@bar "), 3);
  57. QVERIFY(lld.getEmailAddress().isEmpty());
  58. KTextToHTMLHelper lle(QStringLiteral(" foo@bar"), 4);
  59. QVERIFY(lle.getEmailAddress().isEmpty());
  60. KTextToHTMLHelper llf(QStringLiteral("foo@bar-bar"), 3);
  61. QVERIFY(llf.getEmailAddress().isEmpty());
  62. // empty domain part
  63. KTextToHTMLHelper llg(QStringLiteral("foo@"), 3);
  64. QVERIFY(llg.getEmailAddress().isEmpty());
  65. KTextToHTMLHelper llh(QStringLiteral("foo@."), 3);
  66. QVERIFY(llh.getEmailAddress().isEmpty());
  67. KTextToHTMLHelper lli(QStringLiteral("foo@-"), 3);
  68. QVERIFY(lli.getEmailAddress().isEmpty());
  69. // simple address
  70. KTextToHTMLHelper llj(QStringLiteral("foo@bar.baz"), 3);
  71. QCOMPARE(llj.getEmailAddress(), QStringLiteral("foo@bar.baz"));
  72. KTextToHTMLHelper llk(QStringLiteral("foo@bar.baz."), 3);
  73. QCOMPARE(llk.getEmailAddress(), QStringLiteral("foo@bar.baz"));
  74. KTextToHTMLHelper lll(QStringLiteral(".foo@bar.baz"), 4);
  75. QCOMPARE(lll.getEmailAddress(), QStringLiteral("foo@bar.baz"));
  76. KTextToHTMLHelper llm(QStringLiteral("foo@bar.baz-"), 3);
  77. QCOMPARE(llm.getEmailAddress(), QStringLiteral("foo@bar.baz"));
  78. KTextToHTMLHelper lln(QStringLiteral("-foo@bar.baz"), 4);
  79. QCOMPARE(lln.getEmailAddress(), QStringLiteral("foo@bar.baz"));
  80. KTextToHTMLHelper llo(QStringLiteral("foo@bar.baz "), 3);
  81. QCOMPARE(llo.getEmailAddress(), QStringLiteral("foo@bar.baz"));
  82. KTextToHTMLHelper llp(QStringLiteral(" foo@bar.baz"), 4);
  83. QCOMPARE(llp.getEmailAddress(), QStringLiteral("foo@bar.baz"));
  84. KTextToHTMLHelper llq(QStringLiteral("foo@bar-bar.baz"), 3);
  85. QCOMPARE(llq.getEmailAddress(), QStringLiteral("foo@bar-bar.baz"));
  86. }
  87. void KTextToHTMLTest::testGetUrl()
  88. {
  89. QStringList brackets;
  90. brackets << QString() << QString(); // no brackets
  91. brackets << QStringLiteral("<") << QStringLiteral(">");
  92. brackets << QStringLiteral("[") << QStringLiteral("]");
  93. brackets << QStringLiteral("\"") << QStringLiteral("\"");
  94. brackets << QStringLiteral("<link>") << QStringLiteral("</link>");
  95. for (int i = 0; i < brackets.count(); i += 2) {
  96. testGetUrl2(brackets[i], brackets[i + 1]);
  97. }
  98. }
  99. void KTextToHTMLTest::testGetUrl2(const QString &left, const QString &right)
  100. {
  101. QStringList schemas;
  102. schemas << QStringLiteral("http://");
  103. schemas << QStringLiteral("https://");
  104. schemas << QStringLiteral("vnc://");
  105. schemas << QStringLiteral("fish://");
  106. schemas << QStringLiteral("ftp://");
  107. schemas << QStringLiteral("ftps://");
  108. schemas << QStringLiteral("sftp://");
  109. schemas << QStringLiteral("smb://");
  110. schemas << QStringLiteral("file://");
  111. schemas << QStringLiteral("irc://");
  112. schemas << QStringLiteral("ircs://");
  113. QStringList urls;
  114. urls << QStringLiteral("www.kde.org");
  115. urls << QStringLiteral("user@www.kde.org");
  116. urls << QStringLiteral("user:pass@www.kde.org");
  117. urls << QStringLiteral("user:pass@www.kde.org:1234");
  118. urls << QStringLiteral("user:pass@www.kde.org:1234/sub/path");
  119. urls << QStringLiteral("user:pass@www.kde.org:1234/sub/path?a=1");
  120. urls << QStringLiteral("user:pass@www.kde.org:1234/sub/path?a=1#anchor");
  121. urls << QStringLiteral("user:pass@www.kde.org:1234/sub/\npath \n /long/ path \t ?a=1#anchor");
  122. urls << QStringLiteral("user:pass@www.kde.org:1234/sub/path/special(123)?a=1#anchor");
  123. urls << QStringLiteral("user:pass@www.kde.org:1234/sub/path:with:colon/special(123)?a=1#anchor");
  124. urls << QStringLiteral("user:pass@www.kde.org:1234/sub/path:with:colon/special(123)?a=1#anchor[bla");
  125. urls << QStringLiteral("user:pass@www.kde.org:1234/sub/path:with:colon/special(123)?a=1#anchor[bla]");
  126. urls << QStringLiteral("user:pass@www.kde.org:1234/\nsub/path:with:colon/\nspecial(123)?\na=1#anchor[bla]");
  127. urls << QStringLiteral("user:pass@www.kde.org:1234/ \n sub/path:with:colon/ \n\t \t special(123)?") + QStringLiteral("\n\t \n\t a=1#anchor[bla]");
  128. for (const QString &schema : std::as_const(schemas)) {
  129. for (QString url : std::as_const(urls)) {
  130. // by definition: if the URL is enclosed in brackets, the URL itself is not allowed
  131. // to contain the closing bracket, as this would be detected as the end of the URL
  132. if ((left.length() == 1) && (url.contains(right[0]))) {
  133. continue;
  134. }
  135. // if the url contains a whitespace, it must be enclosed with brackets
  136. if ((url.contains(QLatin1Char('\n')) || url.contains(QLatin1Char('\t')) || url.contains(QLatin1Char(' '))) && left.isEmpty()) {
  137. continue;
  138. }
  139. QString test(left + schema + url + right);
  140. KTextToHTMLHelper ll(test, left.length());
  141. QString gotUrl = ll.getUrl();
  142. // we want to have the url without whitespace
  143. url.remove(QLatin1Char(' '));
  144. url.remove(QLatin1Char('\n'));
  145. url.remove(QLatin1Char('\t'));
  146. bool ok = (gotUrl == (schema + url));
  147. if (!ok) {
  148. qCDebug(KCOREADDONS_DEBUG) << "got:" << gotUrl;
  149. }
  150. QVERIFY2(ok, qPrintable(test));
  151. }
  152. }
  153. QStringList urlsWithoutSchema;
  154. urlsWithoutSchema << QStringLiteral(".kde.org");
  155. urlsWithoutSchema << QStringLiteral(".kde.org:1234/sub/path");
  156. urlsWithoutSchema << QStringLiteral(".kde.org:1234/sub/path?a=1");
  157. urlsWithoutSchema << QStringLiteral(".kde.org:1234/sub/path?a=1#anchor");
  158. urlsWithoutSchema << QStringLiteral(".kde.org:1234/sub/path/special(123)?a=1#anchor");
  159. urlsWithoutSchema << QStringLiteral(".kde.org:1234/sub/path:with:colon/special(123)?a=1#anchor");
  160. urlsWithoutSchema << QStringLiteral(".kde.org:1234/sub/path:with:colon/special(123)?a=1#anchor[bla");
  161. urlsWithoutSchema << QStringLiteral(".kde.org:1234/sub/path:with:colon/special(123)?a=1#anchor[bla]");
  162. urlsWithoutSchema << QStringLiteral(".kde.org:1234/\nsub/path:with:colon/\nspecial(123)?\na=1#anchor[bla]");
  163. urlsWithoutSchema << QStringLiteral(".kde.org:1234/ \n sub/path:with:colon/ \n\t \t special(123)?") + QStringLiteral("\n\t \n\t a=1#anchor[bla]");
  164. QStringList starts;
  165. starts << QStringLiteral("www") << QStringLiteral("ftp") << QStringLiteral("news:www");
  166. for (const QString &start : std::as_const(starts)) {
  167. for (QString url : std::as_const(urlsWithoutSchema)) {
  168. // by definition: if the URL is enclosed in brackets, the URL itself is not allowed
  169. // to contain the closing bracket, as this would be detected as the end of the URL
  170. if ((left.length() == 1) && (url.contains(right[0]))) {
  171. continue;
  172. }
  173. // if the url contains a whitespace, it must be enclosed with brackets
  174. if ((url.contains(QLatin1Char('\n')) || url.contains(QLatin1Char('\t')) || url.contains(QLatin1Char(' '))) && left.isEmpty()) {
  175. continue;
  176. }
  177. QString test(left + start + url + right);
  178. KTextToHTMLHelper ll(test, left.length());
  179. QString gotUrl = ll.getUrl();
  180. // we want to have the url without whitespace
  181. url.remove(QLatin1Char(' '));
  182. url.remove(QLatin1Char('\n'));
  183. url.remove(QLatin1Char('\t'));
  184. bool ok = (gotUrl == (start + url));
  185. if (!ok) {
  186. qCDebug(KCOREADDONS_DEBUG) << "got:" << gotUrl;
  187. }
  188. QVERIFY2(ok, qPrintable(gotUrl));
  189. }
  190. }
  191. // test max url length
  192. QString url = QStringLiteral("https://www.kde.org/this/is/a_very_loooooong_url/test/test/test");
  193. {
  194. KTextToHTMLHelper ll(url, 0, 10);
  195. QVERIFY(ll.getUrl().isEmpty()); // url too long
  196. }
  197. {
  198. KTextToHTMLHelper ll(url, 0, url.length() - 1);
  199. QVERIFY(ll.getUrl().isEmpty()); // url too long
  200. }
  201. {
  202. KTextToHTMLHelper ll(url, 0, url.length());
  203. QCOMPARE(ll.getUrl(), url);
  204. }
  205. {
  206. KTextToHTMLHelper ll(url, 0, url.length() + 1);
  207. QCOMPARE(ll.getUrl(), url);
  208. }
  209. // mailto
  210. {
  211. QString addr = QStringLiteral("mailto:test@kde.org");
  212. QString test(left + addr + right);
  213. KTextToHTMLHelper ll(test, left.length());
  214. QString gotUrl = ll.getUrl();
  215. bool ok = (gotUrl == addr);
  216. if (!ok) {
  217. qCDebug(KCOREADDONS_DEBUG) << "got:" << gotUrl;
  218. }
  219. QVERIFY2(ok, qPrintable(gotUrl));
  220. }
  221. }
  222. void KTextToHTMLTest::testHtmlConvert_data()
  223. {
  224. QTest::addColumn<QString>("plainText");
  225. QTest::addColumn<KTextToHTML::Options>("flags");
  226. QTest::addColumn<QString>("htmlText");
  227. // Linker error when using PreserveSpaces, therefore the hardcoded 0x01 or 0x09
  228. // Test preserving whitespace correctly
  229. QTest::newRow("") << " foo" << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "&nbsp;foo";
  230. QTest::newRow("") << " foo" << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "&nbsp;&nbsp;foo";
  231. QTest::newRow("") << " foo " << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "&nbsp;&nbsp;foo&nbsp;&nbsp;";
  232. QTest::newRow("") << " foo " << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "&nbsp;&nbsp;foo&nbsp;";
  233. QTest::newRow("") << "bla bla bla bla bla" << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "bla bla bla bla bla";
  234. QTest::newRow("") << "bla bla bla \n bla bla bla " << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  235. << "bla bla bla&nbsp;<br />\n&nbsp;&nbsp;bla bla bla&nbsp;";
  236. QTest::newRow("") << "bla bla bla" << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "bla bla&nbsp;&nbsp;bla";
  237. QTest::newRow("") << " bla bla \n bla bla a\n bla bla " << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  238. << "&nbsp;bla bla&nbsp;<br />\n&nbsp;bla bla a<br />\n"
  239. "&nbsp;&nbsp;bla bla&nbsp;";
  240. // Test highlighting with *, / and _
  241. QTest::newRow("") << "Ce paragraphe _contient_ des mots ou des _groupes de mots_ à mettre en"
  242. " forme…"
  243. << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  244. << "Ce paragraphe <u>_contient_</u> des mots ou des"
  245. " <u>_groupes de mots_</u> à mettre en forme…";
  246. QTest::newRow("punctation-bug") << "Ce texte *a l'air* de _fonctionner_, à condition"
  247. " d’utiliser le guillemet ASCII."
  248. << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  249. << "Ce texte <b>*a l'air*</b> de <u>_fonctionner_</u>, à"
  250. " condition d’utiliser le guillemet ASCII.";
  251. QTest::newRow("punctation-bug") << "Un répertoire /est/ un *dossier* où on peut mettre des"
  252. " *fichiers*."
  253. << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  254. << "Un répertoire <i>/est/</i> un"
  255. " <b>*dossier*</b> où on peut mettre des <b>*fichiers*</b>.";
  256. QTest::newRow("punctation-bug") << "*BLA BLA BLA BLA*." << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  257. << "<b>BLA BLA BLA BLA</b>.";
  258. QTest::newRow("") << "Je vais tenter de repérer des faux positif*" << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  259. << "Je vais tenter de repérer des faux positif*";
  260. QTest::newRow("") << "*Ouais !* *Yes!*" << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  261. << "<b>*Ouais !*</b> <b>*Yes!*</b>";
  262. QTest::newRow("multispace") << "*Ouais foo*" << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  263. << "<b>*Ouais foo*</b>";
  264. QTest::newRow("multispace3") << "*Ouais: foo*" << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  265. << "<b>*Ouais: foo*</b>";
  266. QTest::newRow("multi-") << "** Ouais: foo **" << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  267. << "** Ouais:&nbsp;&nbsp;foo **";
  268. QTest::newRow("multi-") << "*** Ouais: foo ***" << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  269. << "*** Ouais:&nbsp;&nbsp;foo ***";
  270. QTest::newRow("nohtmlversion") << "* Ouais: foo *" << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  271. << "* Ouais:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo *";
  272. QTest::newRow("nohtmlversion2") << "*Ouais: foo *" << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  273. << "*Ouais:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo *";
  274. QTest::newRow("nohtmlversion3") << "* Ouais: foo*" << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  275. << "* Ouais:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;foo*";
  276. QTest::newRow("nohtmlversion3") << "* Ouais: *ff sfsdf* foo *" << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  277. << "* Ouais: <b>*ff sfsdf*</b> foo *";
  278. QTest::newRow("") << "the /etc/{rsyslog.d,syslog-ng.d}/package.rpmnew file"
  279. << KTextToHTML::Options(KTextToHTML::PreserveSpaces | KTextToHTML::HighlightText)
  280. << "the /etc/{rsyslog.d,syslog-ng.d}/package.rpmnew file";
  281. // This test has problems with the encoding, apparently.
  282. // QTest::newRow( "" ) << "*Ça fait plaisir de pouvoir utiliser des lettres accentuées dans du"
  283. // " texte mis en forme*." << 0x09 << "<b>Ça fait plaisir de pouvoir"
  284. // " utiliser des lettres accentuées dans du texte mis en forme</b>.";
  285. // Bug reported by dfaure, the <hostname> would get lost
  286. QTest::newRow("") << "QUrl url(\"http://strange<hostname>/\");" << KTextToHTML::Options(KTextToHTML::ReplaceSmileys | KTextToHTML::HighlightText)
  287. << "QUrl url(&quot;<a href=\"http://strange<hostname>/\">"
  288. "http://strange&lt;hostname&gt;/</a>&quot;);";
  289. // Bug: 211128 - plain text emails should not replace ampersand & with &amp;
  290. QTest::newRow("bug211128") << "https://green-site/?Ticket=85&Page=next" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  291. << "<a href=\"https://green-site/?Ticket=85&Page=next\">"
  292. "https://green-site/?Ticket=85&amp;Page=next</a>";
  293. QTest::newRow("dotBeforeEnd") << "Look at this file: www.example.com/example.h" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  294. << "Look at this file: <a href=\"http://www.example.com/example.h\">"
  295. "www.example.com/example.h</a>";
  296. QTest::newRow("dotInMiddle") << "Look at this file: www.example.com/.bashrc" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  297. << "Look at this file: <a href=\"http://www.example.com/.bashrc\">"
  298. "www.example.com/.bashrc</a>";
  299. // A dot at the end of an URL is explicitly ignored
  300. QTest::newRow("dotAtEnd") << "Look at this file: www.example.com/test.cpp." << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  301. << "Look at this file: <a href=\"http://www.example.com/test.cpp\">"
  302. "www.example.com/test.cpp</a>.";
  303. // Bug 313719 - URL in parenthesis
  304. QTest::newRow("url-in-parenthesis-1") << "KDE (website https://www.kde.org)" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  305. << "KDE (website <a href=\"https://www.kde.org\">https://www.kde.org</a>)";
  306. QTest::newRow("url-in-parenthesis-2") << "KDE website (https://www.kde.org)" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  307. << "KDE website (<a href=\"https://www.kde.org\">https://www.kde.org</a>)";
  308. QTest::newRow("url-in-parenthesis-3") << "bla (https://www.kde.org - section 5.2)" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  309. << "bla (<a href=\"https://www.kde.org\">https://www.kde.org</a> - section 5.2)";
  310. // Fix url as foo <<url> <url>> when we concatened them.
  311. QTest::newRow("url-with-url")
  312. << "foo <https://www.kde.org/ <https://www.kde.org/>>" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  313. << "foo &lt;<a href=\"https://www.kde.org/ \">https://www.kde.org/ </a>&lt;<a href=\"https://www.kde.org/\">https://www.kde.org/</a>&gt;&gt;";
  314. // Fix url exploit
  315. QTest::newRow("url-exec-html") << "https://\"><!--" << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "https://&quot;&gt;&lt;!--";
  316. QTest::newRow("url-exec-html-2") << "https://192.168.1.1:\"><!--" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  317. << "https://192.168.1.1:&quot;&gt;&lt;!--";
  318. QTest::newRow("url-exec-html-3") << "https://<IP>:\"><!--" << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "https://&lt;IP&gt;:&quot;&gt;&lt;!--";
  319. QTest::newRow("url-exec-html-4") << "https://<IP>:/\"><!--" << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "https://&lt;IP&gt;:/&quot;&gt;&lt;!--";
  320. QTest::newRow("url-exec-html-5") << "https://<IP>:/\"><script>alert(1);</script><!--" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  321. << "https://&lt;IP&gt;:/&quot;&gt;&lt;script&gt;alert(1);&lt;/script&gt;&lt;!--";
  322. QTest::newRow("url-exec-html-6") << "https://<IP>:/\"><script>alert(1);</script><!--\nTest2" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  323. << "https://&lt;IP&gt;:/&quot;&gt;&lt;script&gt;alert(1);&lt;/script&gt;&lt;!--\nTest2";
  324. QTest::newRow("url-with-ref-in-[") << "https://www.kde.org[1]" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  325. << "<a href=\"https://www.kde.org\">https://www.kde.org</a>[1]";
  326. QTest::newRow("url-with-ref-in-[2") << "[http://www.example.org/][whatever]" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  327. << "[<a href=\"http://www.example.org/\">http://www.example.org/</a>][whatever]";
  328. // Bug 346132
  329. QTest::newRow("url-with-ref-in-<") << "http://www.foo.bar<http://foo.bar/>" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  330. << "<a href=\"http://www.foo.bar\">http://www.foo.bar</a>&lt;<a href=\"http://foo.bar/\">http://foo.bar/</a>&gt;";
  331. QTest::newRow("url-with-ref-in-]") << "[Please visit our booth 24-25 http://example.com/]" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  332. << "[Please visit our booth 24-25 <a href=\"http://example.com/\">http://example.com/</a>]";
  333. QTest::newRow("two url with space") << "http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  334. << "<a href=\"http://www.kde.org/standards/kcfg/1.0\">http://www.kde.org/standards/kcfg/1.0</a> <a "
  335. "href=\"http://www.kde.org/\">http://www.kde.org/</a>";
  336. // Bug kmail
  337. QTest::newRow("two url with space-2")
  338. << "@@ -55,6 +55,10 @@ xsi:schemaLocation=\"http://www.kde.org/standards/kcfg/1.0 http://www.kde.org/"
  339. << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  340. << "@@ -55,6 +55,10 @@ xsi:schemaLocation=&quot;<a href=\"http://www.kde.org/standards/kcfg/1.0\">http://www.kde.org/standards/kcfg/1.0</a> <a "
  341. "href=\"http://www.kde.org/\">http://www.kde.org/</a>";
  342. const auto opt = KTextToHTML::PreserveSpaces | KTextToHTML::ConvertPhoneNumbers;
  343. // tel: urls
  344. QTest::newRow("tel url compact") << "bla bla <tel:+491234567890> bla bla" << opt
  345. << "bla bla &lt;<a href=\"tel:+491234567890\">tel:+491234567890</a>&gt; bla bla";
  346. QTest::newRow("tel url fancy") << "bla bla tel:+49-321-123456 bla bla" << opt << "bla bla <a href=\"tel:+49-321-123456\">tel:+49-321-123456</a> bla bla";
  347. // negative tel: url tests
  348. QTest::newRow("empty tel url") << "bla tel: blub" << opt << "bla tel: blub";
  349. // phone numbers
  350. QTest::newRow("tel compact international") << "call +49123456789, then hang up" << opt
  351. << "call <a href=\"tel:+49123456789\">+49123456789</a>, then hang up";
  352. QTest::newRow("tel parenthesis/spaces international")
  353. << "phone:+33 (01) 12 34 56 78 blub" << opt << "phone:<a href=\"tel:+330112345678\">+33 (01) 12 34 56 78</a> blub";
  354. QTest::newRow("tel dashes international") << "bla +44-321-1-234-567" << opt << "bla <a href=\"tel:+443211234567\">+44-321-1-234-567</a>";
  355. QTest::newRow("tel dashes/spaces international") << "+1 123-456-7000 blub" << opt << "<a href=\"tel:+11234567000\">+1 123-456-7000</a> blub";
  356. QTest::newRow("tel spaces international") << "bla +32 1 234 5678 blub" << opt << "bla <a href=\"tel:+3212345678\">+32 1 234 5678</a> blub";
  357. QTest::newRow("tel slash domestic") << "bla 030/12345678 blub" << opt << "bla <a href=\"tel:03012345678\">030/12345678</a> blub";
  358. QTest::newRow("tel slash/space domestic") << "Tel.: 089 / 12 34 56 78" << opt << "Tel.: <a href=\"tel:08912345678\">089 / 12 34 56 78</a>";
  359. QTest::newRow("tel follow by parenthesis") << "Telefon: 0 18 05 / 12 23 46 (14 Cent/Min.*)" << opt
  360. << "Telefon: <a href=\"tel:01805122346\">0 18 05 / 12 23 46</a> (14 Cent/Min.*)";
  361. QTest::newRow("tel space single digit at end") << "0123/123 456 7" << opt << "<a href=\"tel:01231234567\">0123/123 456 7</a>";
  362. QTest::newRow("tel space around dash") << "bla +49 (0) 12 23 - 45 6000 blub" << opt
  363. << "bla <a href=\"tel:+4901223456000\">+49 (0) 12 23 - 45 6000</a> blub";
  364. QTest::newRow("tel two numbers speparated by dash")
  365. << "bla +49 (0) 12 23 46 78 - +49 0123/123 456 78 blub" << opt
  366. << "bla <a href=\"tel:+49012234678\">+49 (0) 12 23 46 78</a> - <a href=\"tel:+49012312345678\">+49 0123/123 456 78</a> blub";
  367. // negative tests for phone numbers
  368. QTest::newRow("non-tel number") << "please send 1200 cakes" << opt << "please send 1200 cakes";
  369. QTest::newRow("non-tel alpha-numeric") << "bla 1-123-456-ABCD blub" << opt << "bla 1-123-456-ABCD blub";
  370. QTest::newRow("non-tel alpha prefix") << "ABCD0123-456-789" << opt << "ABCD0123-456-789";
  371. QTest::newRow("non-tel date") << "bla 02/03/2019 blub" << opt << "bla 02/03/2019 blub";
  372. QTest::newRow("non-tel too long") << "bla +012-4567890123456 blub" << opt << "bla +012-4567890123456 blub";
  373. QTest::newRow("non-tel unbalanced") << "bla +012-456789(01 blub" << opt << "bla +012-456789(01 blub";
  374. QTest::newRow("non-tel nested") << "bla +012-4(56(78)90)1 blub" << opt << "bla +012-4(56(78)90)1 blub";
  375. QTest::newRow("tel extraction disabled") << "call +49123456789 now" << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "call +49123456789 now";
  376. QTest::newRow("bug-414360")
  377. << "https://www.openstreetmap.org/directions?engine=graphhopper_foot&route=44.85765%2C-0.55931%3B44.85713%2C-0.56117#map=18/44.85756/-0.56094"
  378. << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  379. << "<a "
  380. "href=\"https://www.openstreetmap.org/directions?engine=graphhopper_foot&route=44.85765%2C-0.55931%3B44.85713%2C-0.56117#map=18/44.85756/"
  381. "-0.56094\">https://www.openstreetmap.org/directions?engine=graphhopper_foot&amp;route=44.85765%2C-0.55931%3B44.85713%2C-0.56117#map=18/44.85756/"
  382. "-0.56094</a>";
  383. // xmpp bug 422291
  384. QTest::newRow("xmpp1") << "xmpp:username@server.tld" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  385. << "<a href=\"xmpp:username@server.tld\">xmpp:username@server.tld</a>";
  386. QTest::newRow("xmpp2") << "xmpp:conversations@conference.siacs.eu" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  387. << "<a href=\"xmpp:conversations@conference.siacs.eu\">xmpp:conversations@conference.siacs.eu</a>";
  388. QTest::newRow("xmpp3") << "xmpp:conversations@conference.siacs.eu?join" << KTextToHTML::Options(KTextToHTML::PreserveSpaces)
  389. << "<a href=\"xmpp:conversations@conference.siacs.eu?join\">xmpp:conversations@conference.siacs.eu?join</a>";
  390. // Test news: only
  391. QTest::newRow("news") << "news: " << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "news:&nbsp;";
  392. QTest::newRow("ftp") << "ftp: " << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "ftp:&nbsp;";
  393. QTest::newRow("mailto") << "mailto: " << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "mailto:&nbsp;";
  394. QTest::newRow("empty") << "" << KTextToHTML::Options(KTextToHTML::PreserveSpaces) << "";
  395. }
  396. void KTextToHTMLTest::testHtmlConvert()
  397. {
  398. QFETCH(QString, plainText);
  399. QFETCH(KTextToHTML::Options, flags);
  400. QFETCH(QString, htmlText);
  401. QEXPECT_FAIL("punctation-bug", "Linklocator does not properly detect punctation as boundaries", Continue);
  402. const QString actualHtml = KTextToHTML::convertToHtml(plainText, flags);
  403. QCOMPARE(actualHtml, htmlText);
  404. }
  405. #include "moc_ktexttohtmltest.cpp"