qthelp_url.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #include "base/qthelp_url.h"
  8. namespace qthelp {
  9. namespace {
  10. QRegularExpression CreateRegExp(const QString &expression) {
  11. auto result = QRegularExpression(
  12. expression,
  13. QRegularExpression::UseUnicodePropertiesOption);
  14. result.optimize();
  15. return result;
  16. }
  17. QString ExpressionDomain() {
  18. // Matches any domain name, containing at least one '.', including "file.txt".
  19. return QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)?((?:[A-Za-z" "\xD0\x90-\xD0\xAF\xD0\x81" "\xD0\xB0-\xD1\x8F\xD1\x91" "0-9\\-\\_]+\\.){1,10}([A-Za-z" "\xD1\x80\xD1\x84" "\\-\\d]{2,22})(\\:\\d+)?)");
  20. }
  21. QString ExpressionDomainExplicit() {
  22. // Matches any domain name, containing a protocol, including "test://localhost".
  23. return QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)((?:[A-Za-z" "\xD0\x90-\xD0\xAF\xD0\x81" "\xD0\xB0-\xD1\x8F\xD1\x91" "0-9\\-\\_]+\\.){0,10}([A-Za-z" "\xD1\x80\xD1\x84" "\\-\\d]{2,22})(\\:\\d+)?)");
  24. }
  25. QString ExpressionIpExplicit() {
  26. //Matches any ip, containing a protocol, including "test://127.0.0.1:1234"
  27. return QString::fromUtf8("(?<![\\w\\$\\-\\_%=\\.])(?:([a-zA-Z]+)://)(((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\\:\\d+)?)");
  28. }
  29. bool IsGoodProtocol(const QString &protocol) {
  30. const auto equals = [&](QLatin1String string) {
  31. return protocol.compare(string, Qt::CaseInsensitive) == 0;
  32. };
  33. return equals(qstr("http"))
  34. || equals(qstr("https"))
  35. || equals(qstr("tg"))
  36. || equals(qstr("ton"))
  37. || equals(qstr("tonsite"));
  38. }
  39. } // namespace
  40. const QRegularExpression &RegExpDomain() {
  41. static const auto result = CreateRegExp(ExpressionDomain());
  42. return result;
  43. }
  44. const QRegularExpression &RegExpDomainExplicit() {
  45. static const auto result = CreateRegExp(ExpressionDomainExplicit());
  46. return result;
  47. }
  48. const QRegularExpression &RegExpIpExplicit() {
  49. static const auto result = CreateRegExp(ExpressionIpExplicit());
  50. return result;
  51. }
  52. QRegularExpression RegExpProtocol() {
  53. static const auto result = CreateRegExp("^([a-zA-Z]+)://");
  54. return result;
  55. }
  56. QMap<QString, QString> url_parse_params(
  57. const QString &params,
  58. UrlParamNameTransform transform) {
  59. auto result = QMap<QString, QString>();
  60. const auto transformParamName = [transform](const QString &name) {
  61. if (transform == UrlParamNameTransform::ToLower) {
  62. return name.toLower();
  63. }
  64. return name;
  65. };
  66. for (const auto &param : params.split('&')) {
  67. // Skip params without a name (starting with '=').
  68. if (auto separatorPosition = param.indexOf('=')) {
  69. const auto paramName = transformParamName(
  70. (separatorPosition > 0)
  71. ? param.mid(0, separatorPosition)
  72. : param);
  73. const auto paramValue = (separatorPosition > 0)
  74. ? url_decode(param.mid(separatorPosition + 1))
  75. : QString();
  76. if (!result.contains(paramName)) {
  77. result.insert(paramName, paramValue);
  78. }
  79. }
  80. }
  81. return result;
  82. }
  83. bool is_ipv6(const QString &ip) {
  84. //static const auto regexp = QRegularExpression("^[a-fA-F0-9:]+$");
  85. //return regexp.match(ip).hasMatch();
  86. return ip.indexOf('.') < 0 && ip.indexOf(':') >= 0;
  87. }
  88. QString url_append_query_or_hash(const QString &url, const QString &add) {
  89. const auto query = url.lastIndexOf('?');
  90. if (query < 0) {
  91. return url + '?' + add;
  92. }
  93. const auto hash = url.lastIndexOf('#');
  94. return url
  95. + (query >= 0 && query > hash ? '&' : '?')
  96. + add;
  97. }
  98. QString validate_url(const QString &value) {
  99. const auto trimmed = value.trimmed();
  100. if (trimmed.isEmpty()) {
  101. return QString();
  102. }
  103. const auto domainMatch = RegExpDomainExplicit().match(trimmed);
  104. const auto ipMatch = RegExpIpExplicit().match(trimmed);
  105. if (!domainMatch.hasMatch() && !ipMatch.hasMatch()) {
  106. const auto domain = RegExpDomain().match(trimmed);
  107. if (!domain.hasMatch() || domain.capturedStart() != 0) {
  108. return QString();
  109. }
  110. return qstr("http://") + trimmed;
  111. } else if (domainMatch.capturedStart() != 0 && ipMatch.capturedStart() != 0) {
  112. return QString();
  113. }
  114. const auto protocolMatch = RegExpProtocol().match(trimmed);
  115. Assert(protocolMatch.hasMatch());
  116. return IsGoodProtocol(protocolMatch.captured(1)) ? trimmed : QString();
  117. }
  118. } // namespace qthelp