C++变量从 GETTEXT 获取为mysql_query变量
C++ variable gotten from GETTEXT as a mysql_query variable
我正在尝试执行以下操作:
- 获取在用户字段中键入的用户名
- 使用用户名作为变量进行搜索mysql_query
我很难通过第 2 阶段,因为mysql_query将 const char* 作为查询字符串,并且我只能将用户名作为 char* 或 wchar_t*
我也在用 unicode 编译。
我现在的代码:
void mysql_connect(HWND hLoginWnd) {
MYSQL *con, mysql;
MYSQL_RES *res;
mysql_init(&mysql);
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8");
mysql_real_connect(&mysql, "localhost", "root", "", "treenitaulu", 3306, NULL, 0);
char name[512], pass[512];
int lenUser = SendMessage(userField, WM_GETTEXT, 512, (LPARAM)name);
int lenPass = SendMessage(passField, WM_GETTEXT, 512, (LPARAM)pass);
if(lenUser > 0 && lenPass > 0) {
std::string query = "SELECT pass FROM users WHERE name='" + std::string(name) + "'";
mysql_query(&mysql, query.c_str());
}
}
我该怎么办?
您将 SQL 字符集设置为 UTF-8,因此请使用 WideCharToMultiByte()
将检索到的 UI Unicode 字符串转换为 UTF-8,然后将转换后的数据传递给数据库查询。 UTF-8 编码的数据可以使用char
缓冲区进行存储,并且您可以在预期const char*
的位置传递char*
(或char[]
)。 例如:
std::string Utf8Encode(WCHAR *wStr, int wLen)
{
int utf8len = WideCharToMultiByte(CP_UTF8, 0, wStr, wLen, NULL, 0, NULL, NULL);
if (utf8len > 0)
{
std::vector<char> utf8(utf8len);
utf8len = WideCharToMultiByte(CP_UTF8, 0, wStr, wLen, &utf8[0], utf8len, NULL, NULL);
if (utf8len > 0)
return std::string(&utf8[0], utf8len);
}
return std::string();
}
void mysql_connect(HWND hLoginWnd)
{
MYSQL *con, mysql;
MYSQL_RES *res;
mysql_init(&mysql);
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8");
mysql_real_connect(&mysql, "localhost", "root", "", "treenitaulu", 3306, NULL, 0);
WCHAR name[512];
int lenUser = SendMessage(userField, WM_GETTEXTW, 512, (LPARAM)name);
if (lenUser > 0)
{
std::string query = "SELECT pass FROM users WHERE name='" + Utf8Encode(name, lenUser) + "'";
mysql_query(&mysql, query.c_str());
...
}
}
话虽如此,在动态构建 SQL 语句时,您确实需要转义字符串。 它更安全,因为它不容易受到SQL注入攻击:
std::string Utf8EncodeAndEscape(MYSQL *mysql, WCHAR *wStr, int wLen)
{
int utf8len = WideCharToMultiByte(CP_UTF8, 0, wStr, wLen, NULL, 0, NULL, NULL);
if (utf8len > 0)
{
std::vector<char> utf8(utf8len);
utf8len = WideCharToMultiByte(CP_UTF8, 0, wStr, wLen, &utf8[0], utf8len, NULL, NULL);
if (utf8len > 0)
{
std::vector<char> escaped(utf8len*2+1);
unsigned long escapedLen = mysql_real_escape_string(mysql, &escaped[0], &utf8[0], utf8len);
if (escapedLen > 0)
return std::string(&escaped[0], escapedLen);
}
}
return std::string();
}
void mysql_connect(HWND hLoginWnd)
{
MYSQL *con, mysql;
MYSQL_RES *res;
mysql_init(&mysql);
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, "utf8");
mysql_real_connect(&mysql, "localhost", "root", "", "treenitaulu", 3306, NULL, 0);
WCHAR name[512];
int lenUser = SendMessage(userField, WM_GETTEXTW, 512, (LPARAM)name);
if (lenUser > 0)
{
std::string query = "SELECT pass FROM users WHERE name='" + Utf8EncodeAndEscape(&mysql, name, lenUser) + "'";
mysql_query(&mysql, query.c_str());
...
}
}
参数化查询同样安全,但比动态 SQL 语句更有效,尤其是在需要多次执行同一语句时:
std::wstring Utf8Decode(char *utf8Str, int utf8Len)
{
int wlen = MultiByteToWideChar(CP_UTF8, 0, utf8Str, utf8Len, NULL, 0);
if (wLen > 0)
{
std::vector<wchar_t> wStr(wLen);
wLen = MultiByteToWideChar(CP_UTF8, 0, utf8Str, utf8Len, &wStr[0], wLen);
if (wLen > 0)
return std::wstring(&wStr[0], wLen);
}
return std::wstring();
}
MYSQL_STMT *stmt = mysql_stmt_init(&mysql);
if (stmt)
{
std::string query = "SELECT pass FROM users WHERE name=?"
if (mysql_stmt_prepare(stmt, query.c_str(), query.length()) == 0)
{
if (mysql_stmt_param_count(stmt) == 1)
{
std::string utf8User = Utf8Encode(name, lenUser);
unsigned long utf8len = utf8User.length();
MYSQL_BIND param = {0};
param.buffer_type = MYSQL_TYPE_STRING;
param.buffer = utf8User.c_str();
param.buffer_length = utf8len;
param.length = &utf8len;
param.is_unsigned = true;
mysql_stmt_bind_param(stmt, ¶m);
char result[512];
unsigned long resultLen = 0;
MYSQL_BIND result = {0};
param.buffer_type = MYSQL_TYPE_STRING;
param.buffer = &result[0];
param.buffer_length = 512;
param.length = &resultlen;
param.is_unsigned = true;
mysql_stmt_bind_result(stmt, &result);
if (mysql_stmt_execute(stmt) == 0)
{
mysql_stmt_fetch(stmt);
mysql_stmt_free_result(stmt);
SendMessage(passField, WM_SETTEXTW, 0, (LPARAM) Utf8Decode(result, resultLen).c_str());
}
}
}
}
mysql_stmt_close(stmt);
相关文章:
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 将数组的地址分配给变量并删除
- 为"adjacent"变量赋值时出现问题
- enum是C++中的宏变量还是整数变量
- 在全局变量中保存类的实例以重新创建类(创建"backup")
- 用C++中的一个变量定义一个常量
- 具有奇怪重复模板模式的派生类中的成员变量已损坏
- 将变量插入到 mysql 表中
- MySQL 连接器/C++声明变量
- Wt Dbo MySQL 后端连接错误"SET storage_engine=INNODB;":未知的系统变量'storage_engine'
- 未初始化的本地变量(变量是类中的对象)-MYSQL
- 插入MySQL命令和C++变量
- 如何使用本地变量作为MySQL查询的一部分(Qt c++)
- 在c/c++中向SQL/MYSQL语句传递变量
- MySQL++-运行时检查失败#2-变量周围的堆栈已损坏
- 使用mysql连接器将mysql数据库中的数据存储到c++变量中
- 从不同的c++类访问Mysql*连接变量
- c++和MySQL -如何在我的查询中包含变量
- 将变量从 c++ 发送到 mysql