Hmm, for some reason, its only doing this on the first username (and password) and does it for how big my my vector is. Any ideas on why?
int eMysql::strip(string &input) {
char* from = new char[strlen(input.c_str()) * 3 + 1];
mysql_real_escape_string(&mysql, from, input.c_str(), input.length());
input = input.assign(from);
delete from;
}
Where its used:
if(query.size() > 0) {
mysql->strip(query[0]);
mysql->strip(query[1]);
mysql->query("SELECT `username` FROM `users` where `username` = '"+ query[0] +"';");
I suggest building the query as a separate string variable rather than passing the mess in the argument:
static const char fixed_text[] = "SELECT `username` FROM `users` where `username` = '";
std::string query_text(fixed_text);
query_text += query[0];
query_text += "';";
mysql->query(query_text);
This technique allows you to examine the query before it is sent to MySql.
I suggest you examine the query[0] variable for any strange characters such as \r and \n. The MySql manual has a section listing characters that need to be escaped.
Related
Following ONVIF documentation, the password digest for making ONVIF Soap request should be like this.
PasswordDigest = B64ENCODE( SHA1( B64DECODE( Nonce ) + Date + Password ) )
For example:
Nonce – LKqI6G/AikKCQrN0zqZFlg==
Date – 2010-09-16T07:50:45Z
Password – userpassword
Resulting Digest – tuOSpGlFlIXsozq4HFNeeGeFLEI=
Below is how I have written in C++, which resulted in an invalid user token.
std::string dateTime = "2022-09-10T10:10:59.000Z";
std::string nonce = "secret";
std::string password = "mypassword";
std::string str = decode_str(nonce) + dateTime + password;
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *) str.c_str(), strlen(str.c_str()) - 1, hash);
uint8_t * hash_ptr = hash;
std::string psswrd = encode_str(hash_ptr, sizeof(hash));
std::cout << psswrd << std::endl; // +cz8/SJS89Uee7cTjW9aiMG9CTE=
But the above password is invalid, resulted the request to fail after timeout.
How to create Password Digest for ONVIF in C++?
I believe your problem is in the call to SHA1. The second parameter (length of the string to be hashed) is strlen(str) - 1, meaning you cut off the final character of the password, which will then result in an invalid hash.
Please either use the length function of std::string or strlen without that decrement (which does not include the \0).
The second 'problem' is in the string nonce, which is not a Base64 string at all, however I am willing to assume this to be a plain 'example value' because you do not wish you disclose your actual nonce value.
Below is a valid digest password.
std::string dateTime = "2022-09-10T10:10:59.000Z";
std::string nonce = "secret";
std::string password = "mypassword";
std::string str = nonce + dateTime + password;
unsigned char hash[SHA_DIGEST_LENGTH];
SHA1((const unsigned char *) str.c_str(), str.size(), hash);
uint8_t * hash_ptr = hash;
std::string psswrd = encode_str(hash_ptr, sizeof(hash));
I have been writing a wrapper for the Cassandra cppdriver for CQL3.0 and I have come across some odd behavior, and I am not sure if it is typical or a bug.
For reference, I am working with with the cppdriver code release on 4 September (from the repository), libuv0.10 and off of the songs / playlist example posted on the datastax website (http://www.datastax.com/documentation/cql/3.1/cql/ddl/ddl_music_service_c.html)
The problem that I am having is with executing query strings. There seems to be some threshold of characters after which the query string being sent to Cassandra becomes garbage. The code that I am using to construct and send the string to the cppdriver library (and parse the results) is provided below. I added a function (cass_session_print_query) to the cassandra.h and session.cpp files to print out generated statement.
map<string, vector<string> > retresults;
int i = 0, ccount;
stringstream ss;
vector<string> keys = get.GetList();
vector<string>::iterator kit = keys.begin();
map<int, pair<string, string> > primkeys = get.GetMap();
map<int, pair<string, string> >::iterator mit = primkeys.begin();
if (!keys.empty())
{
ss << "SELECT " << (*kit);
++kit;
for ( ; kit != keys.end(); ++kit)
ss << "," << (*kit);
ss << " FROM " << tablename;
if (!primkeys.empty())
{
ss << " WHERE ";
ss << mit->second.first << " = ?";
++mit;
for ( ; mit != primkeys.end(); ++mit)
ss << " and " << mit->second.first << " = ?";
mit = primkeys.begin();
}
ss << ";";
cass_bool_t has_more_pages = cass_false;
const CassResult* result = NULL;
CassString query = cass_string_init(ss.str().c_str());
CassStatement* statement = cass_statement_new(query, primkeys.size());
for ( ; mit != primkeys.end(); ++mit)
cass_statement_bind_string(statement, i++, cass_string_init(mit->second.second.c_str()));
cass_statement_set_paging_size(statement, 100);
do
{
cass_session_print_query(statement);
CassIterator* iterator;
CassFuture* future = cass_session_execute(session_, statement);
if (cass_future_error_code(future) != 0)
{
CassString message = cass_future_error_message(future);
fprintf(stderr, "Error: %.*s\n", (int)message.length, message.data);
break;
}
result = cass_future_get_result(future);
ccount = cass_result_column_count(result);
vector<string> cnames;
for (i = 0; i < ccount; i++)
cnames.push_back(cass_result_column_name(result, i).data);
iterator = cass_iterator_from_result(result);
ListVector::iterator vit;
while (cass_iterator_next(iterator))
{
const CassRow* row = cass_iterator_get_row(iterator);
for (vit = cnames.begin(); vit != cnames.end(); ++vit)
{
CassString value;
char value_buffer[256];
cass_value_get_string(cass_row_get_column_by_name(row, (*vit).c_str()), &value);
if (value.length == 0 || value.data == NULL)
continue;
memcpy(value_buffer, value.data, value.length);
value_buffer[value.length] = '\0';
retresults[(*vit)].push_back(value_buffer);
}
}
has_more_pages = cass_result_has_more_pages(result);
if (has_more_pages)
cass_statement_set_paging_state(statement, result);
cass_iterator_free(iterator);
cass_result_free(result);
} while (has_more_pages);
}
return retresults;
With this, an initial query string of SELECT id,album,title,artist,data FROM songs; results in a Cassandra query string of SELECT id,album,title,artist,data FROM songs;. However, if I add one more column to the SELECT portion SELECT id,album,title,artist,data,tags FROM songs; the query string in the Cassandra cppdriver library becomes something like: ,ar����,dat�� jOM songX. This results in the following error from Cassandra / library: Error: line 1:49 no viable alternative at character '�'.
I have also tried fewer columns, but with a WHERE clause, and that results in the same problem.
Is this a bug? Or am I building and sending strings to the cppdriver library incorrectly?
You should cass_future_wait() on the execute future before testing the error code.
Unrelated: there are also a couple of things that should be freed (future, statement), but I'm assuming that was omitted to keep this concise.
So, it looks like (for whatever reason) I HAVE to parse out the row key from the results. I checked the example, and I was able to not parse out the row key information and everything still worked. I am not yet entirely sure what is forcing me to do this (compared to the provided paging example), but for others, you need to include the following within the while (cass_iterator_nex(iterator)) block to "magically" fix my code above.
CassUuid key;
char key_buffer[CASS_UUID_STRING_LENGTH];
const CassRow* row = cass_iterator_get_row(iterator);
cass_value_get_uuid(cass_row_get_column(row, 0), key);
cass_uuid_string(key, key_buffer);
This is really a long shot, but since you mentioned the Music Service example, did you possibly download and use cql_collections.zip query strings? If so, the strings (now fixed) had minor syntax errors:
-use music
-CREATE TABLE music.songs ( id uuid PRIMARY KEY, album text, artist text, data blob, reviews list, tags set, title text, venue map
+use music;
+CREATE TABLE music.songs ( id uuid PRIMARY KEY, album text, artist text, data blob, reviews list, tags set, title text, venue map);
AeroBuffalo's code worked for me except that I had to put '&' in front of the second parameter of cass_value_get_uuid() function. It required reference type.
cass_value_get_uuid(cass_row_get_column(row, 0), &key);
i have setup a working mysql connector for my c++ project. Now i'm making a login for registered users.
i want to get the username and password into the SQLquery string.
i am trying to get this working:
currently its displaying noting and the game crashes.
#include "boost/lexical_cast.hpp" //boost
#include <cgl\cgl.h> // game library (core media library)
#include <sstream> // sstream
char* username=DEFSER;
char* password=PASS12345;
const char *SQLquery;
std::string SQLquery("SELECT * FROM Users WHERE UserName='" + boost::lexical_cast<std::string>(username) + "' AND PassWord='" + boost::lexical_cast<std::string>(password) + "'");
what i want to get out of SQLquery:
SELECT * FROM Users WHERE UserName='DEFSER' AND PassWord='PASS12345'
and i execute it in this way:
res = stmt->executeQuery(SQLquery);
this is not a fully working code i only want to know how i can get the username and password into the SQLquery.
error when i try to run the query:
Run-Time Check Failure #3 - The variable 'SQLquery' is being used without being initialized.
What you are doing is not concatenating strings, you are adding std::string objects to a literal string pointer.
The std::string class handles concatenation of C-style strings just fine without any lexical_cast, so just do e.g.
std::string SQLquery = "SELECT * FROM Users WHERE UserName='" +
username + "' AND PassWord='" + password + "'";
After testing the above solution doesn't actually work for me. But the following does:
std::string SQLQuery = (std::ostringstream() << "SELECT * FROM Users WHERE UserName='"
<< username << "' AND PassWord='" << password << "'").str();
I'm using pqlib with postgresql version 9.1.11
I have the following code
const char *spid = std::to_string(pid).c_str();
PGresult *res;
const char *paramValues[2] = {u->getID().c_str(), spid};
std::string table;
table = table.append("public.\"").append(Constants::USER_PATTERNS_TABLE).append("\"");
std::string param_name_pid = Constants::RELATION_TABLE_PATTERN_ID;
std::string param_name_uid = Constants::RELATION_TABLE_USER_ID;
std::string command = Constants::INSERT_COMMAND + table + " (" + param_name_uid + ", " + param_name_pid + ") VALUES ($1, $2::int)";
std::cout << "command: " << command << std::endl;
res = PQexecParams(conn, command.c_str(), 2, NULL, paramValues, NULL, NULL,0);
Where
INSERT_COMMAND = "INSERT INTO " (string)
USER_PATTERN_TABLE = "User_Patterns" (string)
RELATION_TABLE_PATTERN_ID = "pattern_id" (string)
RELATION_TABLE_USER_ID = "user_id" (string)
pid = an int
u->getID() = a string
conn = the connection to the db
The table "User_Patterns" is defined as
CREATE TABLE "User_Patterns"(
user_id TEXT references public."User" (id) ON UPDATE CASCADE ON DELETE CASCADE
,pattern_id BIGSERIAL references public."Pattern" (id) ON UPDATE CASCADE
,CONSTRAINT user_patterns_pkey PRIMARY KEY (user_id,pattern_id) -- explicit pk
)WITH (
OIDS=FALSE
);
I already have a user and a pattern loaded into their respective tables.
The command generated is :
INSERT INTO public."User_Patterns" (user_id, pattern_id) VALUES ($1, $2::int)
I also tried with $2, $2::bigint, $2::int4
The problem is:
I receive the error :
ERROR: invalid input syntax for integer: "public.""
I already use PQexecParams to store users and patterns, the only difference is that they all have text/xml fields (the only int field on patterns is a serial one and I don't store that value myself) but because the user_patterns is a relation table I need to store and int for the pattern_id.
I already read the docs for pqlib and saw the examples, both are useless.
The problem is in the lines:
const char *spid = std::to_string(pid).c_str();
const char *paramValues[2] = {u->getID().c_str(), spid};
std::to_string(pid) creates temporary string and .c_str() returns a pointer to an internal representation of this string, which is destroyed at the end of the line, resulting in a dead pointer. You may also see answer to the question
stringstream::str copy lifetime
I have the following problem that has me stumped. As a note to keep in mind, I am using a precompiled sqlite3.dll rather than Qt's built-in SQLite support.
Table creation code:
CREATE TABLE STUDY(
Name NOT NULL,
UserName NOT NULL REFERENCES USERS(UserName),
Description DEFAULT NULL,
PathToOsirixDB DEFAULT NULL,
PRIMARY KEY(Name, UserName)
)
The following C++ code fails to update the value in column PathToOsirixDB if it already contains a value.
It fails silently, with no error returned. That would imply that no rows are matched in the UPDATE. However, if I take the same UPDATE with valid entries for user and study to match a row and run it via either the SQLite Manager Firefox plugin, or the command line tool, it works properly.
void CStudyDatabase::SetOsirixDBForStudy(const QString user, const QString study, const QString path)
{
if (mp_db)
{
int before = sqlite3_total_changes(mp_db);
QString insert = QString("UPDATE STUDY SET PathToOsirixDB = '%1' WHERE Name = '%2' AND UserName = '%3'").arg(path, study, user);
if (!InsertData(insert))
{
int after = sqlite3_total_changes(mp_db);
if (after - before >= 1)
{
SetOsirixDB(path.toAscii().data());
emit ReturnOsirixDB(osirix_db);
}
else
{
emit DatabaseError(QString("Failed to update the target path."));
}
}
}
}
And for Insert Data
int CStudyDatabase::InsertData(const QString insert)
{
char *err_msg = 0;
int rc = sqlite3_exec(mp_db,
insert.toStdString().c_str(),
NULL,
this,
&err_msg);
if (rc)
SignalDatabaseError(&err_msg);
return rc;
}
Any insights are appreciated. Thank you.
UPDATE: added the following code to SetOsiriXDBForStudy to see if we actually find a row to update:
osirix_db = QString("");
QString query = QString("SELECT PathToOsirixDB FROM STUDY WHERE Name = '%1' AND UserName = '%2'").arg(study, user);
int rc = 0;
char *err_msg = 0;
rc = sqlite3_exec(mp_db,
query.toStdString().c_str(),
&OsirixDBCallback,
this,
&err_msg);
if (rc)
SignalDatabaseError(&err_msg);
if (!(QString(osirix_db).isEmpty()))
studyrowfound = true;
In this case, it leaves osirix_db as an empty string.
But, if I execute this function:
void CStudyDatabase::QueryOsirixDB(const QString user, const QString study)
{
int rc = 0;
char *err_msg = 0;
// we query the OrisixDB via the callback and then emit the signal if all went well
QString query = QString("SELECT PathToOsirixDB FROM STUDY WHERE Name = '%1' AND UserName = '%2'").arg(study, user);
rc = sqlite3_exec(mp_db,
query.toStdString().c_str(),
&OsirixDBCallback,
this,
&err_msg);
if (rc)
SignalDatabaseError(&err_msg);
if (QString(osirix_db).isEmpty())
emit NeedToSetOsirixDB(user, study, QString());
else
emit ReturnOsirixDB(osirix_db);
}
Then it does correctly retrieve the expected value into osirix_db.
Last update: found the problem. It was leading spaces on user and study. Had been staring at the same debugger statements for too long and glossed over the extra spaces. The failing SELECT was a big clue that there was something wrong in the construction of the SQL.
There were leading spaces on user and study. Had been staring at the same debugger statements for too long and glossed over the extra spaces. The failing SELECT was a big clue that there was something wrong in the construction of the SQL.