escape_string.hpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. //
  2. // Copyright (c) 2019-2024 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BOOST_MYSQL_ESCAPE_STRING_HPP
  8. #define BOOST_MYSQL_ESCAPE_STRING_HPP
  9. #include <boost/mysql/error_code.hpp>
  10. #include <boost/mysql/string_view.hpp>
  11. #include <boost/mysql/detail/escape_string.hpp>
  12. #include <boost/mysql/detail/output_string.hpp>
  13. #include <boost/config.hpp>
  14. namespace boost {
  15. namespace mysql {
  16. struct format_options;
  17. /**
  18. * \brief (EXPERIMENTAL) Identifies the context which a string is being escaped for.
  19. */
  20. enum class quoting_context : char
  21. {
  22. /// The string is surrounded by double quotes.
  23. double_quote = '"',
  24. /// The string is surrounded by single quotes.
  25. single_quote = '\'',
  26. /// The string is surrounded by backticks.
  27. backtick = '`',
  28. };
  29. /**
  30. * \brief (EXPERIMENTAL) Escapes a string, making it safe for query composition.
  31. * \details
  32. * Given a string `input`, computes a string with special characters
  33. * escaped, and places it in `output`. This function is a low-level building
  34. * block for composing client-side queries with runtime string values without
  35. * incurring in SQL injection vulnerabilities.
  36. * If you can, prefer using higher-level functions like \ref format_sql.
  37. * \n
  38. * Escaping rules are different depending on the context a string is
  39. * being used in. `quot_ctx` identifies where the string will appear in
  40. * a query. Possible values are: \n
  41. * \li \ref quoting_context::double_quote : the string is surrounded by
  42. * double quotes. For example:
  43. * \code "SELECT * FROM employee WHERE company = \"<runtime_value>\"" \endcode
  44. * \li \ref quoting_context::single_quote : the string is surrounded by
  45. * single quotes. For example:
  46. * \code "SELECT * FROM employee WHERE company = '<runtime_value>'" \endcode
  47. * \li \ref quoting_context::backtick : the string is surrounded by
  48. * backticks. This may happen when escaping identifiers. For example:
  49. * \code "SELECT `<runtime_column>` FROM employee" \endcode
  50. * \n
  51. * By default, MySQL treats backslash characters as escapes in string values
  52. * (for instance, the string `"\n"` is treated as a newline). This behavior is
  53. * enabled by default, but can be disabled by enabling the
  54. * <a
  55. * href="https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_no_backslash_escapes">`NO_BACKSLASH_ESCAPES`</a>
  56. * SQL mode. When enabled, backslashes no longer have a special meaning, which changes
  57. * the escaping rules. `opts.backslash_escapes` should be set to `true` if backslashes represent
  58. * escapes (i.e. `NO_BACKSLASH_ESCAPES` is not enabled), and `false` otherwise.
  59. * \n
  60. * MySQL can be configured to treat double-quoted strings as identifiers instead of values.
  61. * This is enabled by activating the
  62. * <a href="https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_ansi_quotes">`ANSI_QUOTES`</a> or
  63. * <a href="https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html#sqlmode_ansi">`ANSI`</a> SQL modes.
  64. * Servers don't report whether this mode is enabled to clients.
  65. * This SQL mode is not directly supported by this function.
  66. * \n
  67. * `opts.charset` should identify the connection's character set (as given by the
  68. * `character_set_client` session variable). The character set is used to iterate
  69. * over the input string. It must be an ASCII-compatible character set (like \ref utf8mb4_charset).
  70. * All character sets allowed by `character_set_client` satisfy this requirement.
  71. * \n
  72. * You can use \ref any_connection::format_opts to retrieve an `opts` value suitable for your connection.
  73. * \n
  74. * \par Exception safety
  75. * Basic guarantee. Memory allocations may throw.
  76. *
  77. * \par Complexity
  78. * Linear in `input.size()`.
  79. *
  80. * \par Errors
  81. * \ref client_errc::invalid_encoding if `input` contains a string
  82. * that is not valid according to `opts.charset`.
  83. */
  84. template <BOOST_MYSQL_OUTPUT_STRING OutputString>
  85. BOOST_ATTRIBUTE_NODISCARD error_code
  86. escape_string(string_view input, const format_options& opts, quoting_context quot_ctx, OutputString& output)
  87. {
  88. output.clear();
  89. return detail::escape_string(
  90. input,
  91. opts,
  92. static_cast<char>(quot_ctx),
  93. detail::output_string_ref::create(output)
  94. );
  95. }
  96. } // namespace mysql
  97. } // namespace boost
  98. #endif