Problem with handling the result of SELECT query in MYSQL C API - mysql

I'm getting a Internal Server Error with one of my scripts. I'm using MYSQL C API. https://dev.mysql.com/doc/refman/5.6/en/c-api.html
Here is the corresponding part of my script:
MYSQL *con;
MYSQL_RES *result;
MYSQL_ROW robe;
con = mysql_init(NULL);
if (!mysql_real_connect(valid values)) {
printf("Content-type: text/html\n\n");
printf("Could not connect\n");
exit(0); }
char somequery[512];
//userinput is sanitized beforehand
int sog = sprintf(somequery, "SELECT password from testtab WHERE username='%s'", userinput);
if (sog < 0) {
printf("Content-type: text/html\n\n");
printf("Something went wrong with Sprintf\n");
exit(0); }
int bos = mysql_real_query(con, somequery, strlen(somequery));
if (bos != 0) {
printf("Content-type: text/html\n\n");
printf("The query produced no result\n");
exit(0); }
result = mysql_store_result(con);
if (result == NULL) {
printf("Content-type: text/html\n\n");
printf("No Result Set Produced\n");
exit(0); }
robe = mysql_fetch_row(result);
char *passdb = robe[0];
printf("Content-type: text/html\n\n");
printf("And it is: %s", passdb);
A HTML form submits via POST to this script (part of which is seen above). When I submit a username which exists in the database beforehand, I'm receiving no error. Everything works fine.
The problem arises, when I'm submitting a username that doesn't exist in the said table(testtab). Well, I'm getting 500 Internal Server Error. I have looked at Apache Error log as well: "End of Script output before Headers".
I have tried a few things so far, but none of them worked. Any help is appreciated.
Note: Doing mysql_num_fields(result); in both cases gives 1.

First, you should NEVER store passwords in a database, especially one that is reachable through an online service. exit(0) indicates success. It's also short-circuiting your output before it is completed. You can't just call exit(0) in the middle of producing output. Use some kind of "data not available" string instead.

I have found the solution elsewhere, thanks to the help of some good people. It seems, that I had made a silly mistake as well as needed a thorough understanding of the difference between two MYSQL C API functions.
I'm writing the answer here, in hope of it benefiting others.
The mistakes is here:
robe = mysql_fetch_row(result);
Though it is correct in itself. I fail to check its result. What happens is that when the SQL query is performed using a username that did not exist in the DB beforehand, the result is a empty set (and not a error).
The mysql_store_result and mysql_fetch_row have a slight difference here. While the former will not return NULL if the set is empty, the later will.
All I have to do is add a check after the above line with the logic:
if (robe == NULL) {
//error occured
} else { //go on
}

Related

Problems with C prog fetching SQL table and integration of JSON to display table on webserver

I have two problems that drive me crazy.
The first one is to integrate JSON in the following code to use JSON as a kind of wrapper around the sqlite statements. This should be for the purpose to display just the entire sql table on a webserver page embedded in HTML. To connect to the database and fetch the table I used sqlite3 and the given functions like sqlite3_open()/sqlite3_close() and so on. I know that sqlite3 has functions to handle JSON as well like json_array()/json_insert() etc. I think this should be a good possible solution to reach my goal. I played around with those functions a bit, but nothing has worked yet. Means there was absolutely no result. Maybe anyone knows how to put the sqlite3 commands/requests in JSON objects to display in a further step those table entries on a simple HTML page. I have to say I`m a absolutely beginer in this section, but read and tried a lot to get into it. But didnt catch it yet.
The second problem is, that the following C code does not execute the while loop to return the rows of my sql table. Output is "Database sucessfull opened unable to fetch data, means it stopps within the last if statement. But I dont know why. Tried to fix it but didnt solve the puzzle yet. The while statement "sqlite3_step(stmt) == SQLITE_ROW" seems to be false, but why? Maybe something is wrong with the stmt pointer.
Hope you could help me. Would be very thankful for every hint to get it work.
C code:
#include "sqlite3.h"
#include <stdio.h>
int main(void) {
sqlite3 *db;
sqlite3_stmt *stmt;
int rc = 0;
rc = sqlite3_open("test.db",&db);
if(rc != SQLITE_OK)
{
printf("Database could not be opened %s \n",sqlite3_errmsg(db));
exit(EXIT_FAILURE);
}
else
{
printf("Database sucessful opened");
}
sqlite3_close(db);
char *sql_stmt = "SELECT * FROM students";
rc = sqlite3_prepare_v2(db, sql_stmt, -1, &stmt, 0);
if(rc != SQLITE_OK)
{
printf("\nUnable to fetch data");
sqlite3_close(db);
return 1;
}
printf("student records\n");
while(sqlite3_step(stmt) == SQLITE_ROW)
{
printf("%s %s %s\n", sqlite3_column_text(stmt, 0), sqlite3_column_text(stmt, 1),
sqlite3_column_text(stmt, 2));
}
sqlite3_finalize(stmt);
sqlite3_close(db);
return 0;
}
I suggest you first figure out why rc = sqlite3_prepare_v2(db, sql_stmt, -1, &stmt, 0); doesn't return an error. Then remove the first sqlite3_close(db); so you are operating on a open database handle.

HTML form and C - checking for a unique username

I'm currently writing my own website and I'm trying to make sure that when someone is making an account the username is unique. I'm doing the back-end in C (since I don't know php/js) and I've been running in a bit of a problem. Right now I'm getting the environment variables in a file newuser.txt (this file has only unique usernames) as such:
fullname=test
description=test
username=test
password=test
I know that at lines 3, 7, 11 etc. in my newusers.txt file I will get my username so I thought of adding all the usernames to another file (which also hosts the incoming data) and then check to see if the incoming username is unique and if it is then I want to add all the data (so fullname, username etc) to newusers.txt. Here's my code:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(int argc, char *argv[])
{
int currentLine = 1;
char fileLine[100];
int searchLine= 3;
char input[200];
int i=0;
int n = atoi(getenv("CONTENT_LENGTH"));
fgets(input,n+1,stdin); //get the input from the form
printf("Content-Type:text/html\n\n");
printf("<TITLE>Account Creation Query</TITLE>\n");
if (n == 0)
{
printf("<p> Error. Please try again.</p>");
}
FILE *f = fopen("newusers.txt", "ab");
FILE *g = fopen("incoming.txt", "ab");
if (f == NULL)
{
printf("<p> Error in opening the file. Check if the file exists</p>");
printf("<p>Login Page</p>");
printf("<p>Homepage</p>");
}
else
{
while(fgets(fileLine, 100, f)) /*searching for the usernames and adding them to the incoming.txt file */
{
if(searchLine == currentLine)
{
fputs(fileLine, g);
searchLine = searchLine + 4;
}
currentLine++;
}
char *token = strtok(input, "&"); /*tokenizing the incoming data and adding it to the incoming.txt file */
while(token!=NULL)
{
fputs(token, g);
fputs("\n", g);
token = strtok(NULL, "&");
}
}
printf("<p> Account created successfully. You can now login!</p>");
printf("<p>Login Page</p>");
fclose(f);
fclose(g);
return 0;
}
Ideally at this point my incoming.txt file would look like this:
firstname=bla
description=bla
username=bla
password=bla
username=u1
username=u2
username=u3
...
Right now I'm stuck at comparing the incoming username to the other usernames and then copying the data back into newusers.txt. Any help would be appreciated!
use system() call to invoke grep binary to search instead writing searching code in C.
as below
//concat strings to get "grep filename username | cut -d'=' -f2" into cmdstring and then
// read the contents
in=popen(cmdstring, "r");
if(in==NULL)
{
perror("Shell execution error");
exit(EXIT_FAILURE);
}
fgets(buf,3000,in)!=NULL)
here buf contains name of the new user then it is already exist.
otherwise he chose unique name.
I'd strongly recommend that you learn a scripting language for this project. PHP, Perl, Python, Ruby, Javascript… there's plenty of choices, and any one of them will be much more suitable for web programming than C.
That being said, what you need here is a database. Consider using SQLite or Berkeley DB; both are easy to interact with from C, and will allow you to perform lookups and insertions much more easily than would be possible with a flat file (as you're trying to do here).

MySQL C Connector / mysql_autocommit function

I'm having a little trouble with the mysql connector in C.
I'm converting some (working) node.js scripts to a standalone C application, and for one part of this I need to switch off auto-commit, make two updates to the database and commit.
However, every time I call mysql_autocommit(mysql, 0); it fails - returning non-zero. I know my connection is good, since I've just completed a query and I'm operating on the results of that query.
Interestingly the MySQL logs are empty...which isn't very helpful.
Any ideas how might find out what the problem is, or fix it? The Node.js scripts were also switching off autocommit and [apparently] work.
Thanks in advance
I use this function the following way in my C application:
int main( int argc, char **argv ) {
my_bool reconnect = 1;
...
dbconnect(); // my function (-> conn)
mysql_options( conn, MYSQL_OPT_RECONNECT, &reconnect );
...
exit (0);
}
Then this code switch out the auto-commit:
mysql_autocommit( conn, 0 );
And this switch back:
mysql_commit( conn );
mysql_autocommit( conn, 1 );

in iOS sqlite getting insertion error for html strings

I am in the requirement of saving the html strings in SQLite Database. While running the insert query, I am getting a syntax error near the style tag of the HTML file.
Here is the code:
-(BOOL)insertAttendees{
sqlite3_stmt *statement;
NSString *insertSQL;
BOOL var=NO;
if (sqlite3_open(dbpath, &db) == SQLITE_OK)
{
//work only for the 1st event
for (int i=0; i<[attendeeCount[0]integerValue];i++)
{
insertSQL = [NSString stringWithFormat:#"INSERT INTO ATTENDEE (A_NAME,A_IMAGE,A_EMAIL,A_PHONE,A_BIO) VALUES (\"%#\",\"%#\", \"%#\",\"%#\",\"%#\")",arrayOf_AName[0][i],arrayOf_AImage[0][i],arrayOf_AEmail[0][i],arrayOf_APhone[0][i],arrayOf_ABio[0][i]];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(db, insert_stmt,-1, &statement, NULL);
if (sqlite3_step(statement) == SQLITE_DONE)
{
var=YES;
}
else
{
NSLog(#"sqlite insertion error %s", sqlite3_errmsg(db));
var=NO;
}
sqlite3_finalize(statement);
}
sqlite3_close(db);
return var;
}
return var;
}
There are a whole bunch of issues here:
The root of the problem is that you're building your SQL using stringWithFormat, which you should not do. If your values contained a quotation mark in them (such as might be near your style tag in your HTML), your SQLite code would fail. Instead, you should:
Your SQL should use ? placeholders (note, no quotation marks in the SQL, either):
const char *insert_stmt = "INSERT INTO ATTENDEE (A_NAME,A_IMAGE,A_EMAIL,A_PHONE,A_BIO) VALUES (?,?,?,?,?)";
Then you should then bind values with something like:
if (sqlite3_bind_text(statement, 1, [string UTF8String], -1, SQLITE_TRANSIENT) != SQLITE_OK) {
NSLog(#"%s: bind column 1 failed: %s", __FUNCTION__, sqlite3_errmsg(db));
}
where string is the NSString value you want to insert, and that second parameter (1, in the above example) is the index of the ? placeholder that you're binding to the text value (where the leftmost placeholder has an index of one).
Only after you've called sqlite3_bind_xxxx() for each of the five ? placeholders, then you can proceed by calling sqlite3_step(), etc.
A second problem is that you are not checking to see if sqlite3_prepare_v2 succeeded or not. This is significant because the meaningful error messages you would have seen if you called sqlite3_errmsg immediately after the prepare statement failed is now lost. You're ignoring any potential prepare error, proceeding with sqlite3_step regardless, and so the meaningful error message will be replaced with one that effectively (but cryptically) says that you called sqlite3_step without first successfully calling sqlite3_prepare_v2.
So, check to make sure if sqlite3_prepare_v2 succeeded, and if it failed, check sqlite3_errmsg immediately before doing any other SQLite calls.
Once you solve the above two issues, you might consider optimizing your code a little. Notably, if you perform a BEGIN TRANSACTION before all of your INSERT statements, and COMMIT TRANSACTION when you're done with all of your inserts, it will be much faster. If you're only inserting a couple of records it might not be observable, but if inserting a lot of records, the performance gain can be staggering.
As yet a further optimization, let's imagine that you addressed my above points (notably, eliminated stringWithFormat for the SQL and used ? placeholders instead) and you had something like the following pseudo code (but obviously checking all of the sqlite3 function return values and handling errors properly):
sqlite3_exec("begin transaction");
for (i = 0; i < whatever; i++) {
sqlite3_prepare(...);
sqlite3_bind(...);
sqlite3_bind(...);
sqlite3_bind(...);
sqlite3_bind(...);
sqlite3_bind(...);
sqlite3_step();
sqlite3_finalize();
}
sqlite3_exec("commit transaction");
Rather than preparing the same SQL many times, you can prepare it once, bind the values, perform the step, and then reset the bindings so you can do it again:
sqlite3_exec("begin transaction");
sqlite3_prepare(...);
for (i = 0; i < whatever; i++) {
sqlite3_bind(...);
sqlite3_bind(...);
sqlite3_bind(...);
sqlite3_bind(...);
sqlite3_bind(...);
sqlite3_step();
sqlite3_reset();
}
sqlite3_finalize();
sqlite3_exec("commit transaction");
Personally, I'd suggest you focus on points 1 and 2 above, and only once you fix the fundamental problem should you contemplate the optimizations of points 3 and 4. Make sure you've got it working before you bother to optimize it.
Finally, I'd be remiss if I didn't point out that you really should contemplate the wonderful third-party FMDB Objective-C wrapper around the SQLite C interface. When you write proper SQLite code, that is binding each value, checking each return code, etc., it gets unwieldy quickly. FMDB greatly simplifies your code.
If you really want to insert HTML in sqlite database then replace all " with \" before executing the query.
(You have't mentioned that whether you are replacing special characters or not).
Suppose, you are doing this..
"SELECT * FROM table WHERE someColume = <div style="width:25px"></div>"
It will fail right after style=" because sqlite will try to execute "SELECT * FROM table WHERE someColume = <div style=",
But if you replace " with \", then your final query will look like this -
"SELECT * FROM table WHERE someColume = <div style=\"width:25px\"></div>"
Good luck.

MySQL C API using results

I am using the MySQL C API to query the database and I have the results stored in MYSQL_ROW types. I am able to print the results to the console with
printf("%s", row[0]);
however, according to the MySQL C API documentation, I cannot use them as null-terminated strings.
At the bottom of the function overview, they say I can "extract" the information with mysql_store_result() or mysql_use_result(). However, I am still confused as to how this is done.
Ideally, I want to use the results as a string so I can do stuff like strcmp, but otherwise I definitely need to use the information somehow with those two functions.
Can somebody show me an example of how to do this?
Basically, you call mysql_store_result() or mysql_use_result() to access the result set, the former loads all the rows into memory on the client side, the latter accesses rows one at a time from the server. If you use mysql_use_result(), you need to call mysql_fetch_row() to access each row until the function returns NULL. Each successful call to mysql_fetch_row() will return a MYSQL_ROW which you can use to access the individual field values.
Since the fields are not nul-terminated, you need to use mysql_fetch_lengths() to get the lengths of each of the fields so that you can copy them somewhere else via memcpy, etc.
Since the field values are not nul-terminated you will need to add your own NUL character when you make the copy if you want to use it as a string. Be aware that the field values may contain binary data, so if you do treat it as a string, functions that expect a C string will stop processing data if it encounters a nul-character in the data.
Here is an example from the documentation that should help you put all this together:
MYSQL_ROW row;
unsigned int num_fields;
unsigned int i;
num_fields = mysql_num_fields(result);
while ((row = mysql_fetch_row(result)))
{
unsigned long *lengths;
lengths = mysql_fetch_lengths(result);
for(i = 0; i < num_fields; i++)
{
printf("[%.*s] ", (int) lengths[i],
row[i] ? row[i] : "NULL");
}
printf("\n");
}