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).
Related
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.
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
}
I am getting data from arduino and stored in database through ethienet. But when i got value ambientemp from arduino. it showed correct value when i tested on serial monitor. but when I use sprintf() I got -3275 or 0 value, which it is not correct value. Here is my partial code in sketch, please help...Here is guy doing his project. The result on Sketch serial montior is: ambientTemp 23.55 and then GET /getData/temp.php?t=-3278 I copied some of him: getting data and stored it into mysql
void getData() {
double ambientTemp=23.55; //to make it easy I assign ambientTemp a value.
unsigned long previousMillis = 0;
unsigned long currentMillis = 0;
long interval = 10000;
char strURL[70];
EthernetClient client;
// If there's a successful connection, send the HTTP POST request
currentMillis = millis();
if(currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
if (client.connect(server, 80)) {
Serial.println("get data connecting...");
//client.println("GET /getData/temp.php?t=%d,temp HTTP/1.1");
// delay(10000);
Serial.println("ambientTemp");
Serial.println(ambientTemp);
sprintf(strURL,"GET /getData/temp.php?t=%d",ambientTemp);
delay(50000);
client.print(strURL);
client.println();
// client.print(strURL);
Serial.print(strURL);
}
else {
// If you couldn't make a connection:
Serial.println("Connection failed");
Serial.println("Disconnecting.");
client.stop();
}
}
}
You need to read up on C format specifications. "%d" means take the corresponsding variable (ambientTemp in your case) and interpret it as an integer. So what the runtime code is doing is looking at the bytes which make up your double, and interpreting the first 2 of those an in integer. Not what you want.... use "%f" as a format specifier...
I want to import my IIS logs into SQL for reporting using Bulk Insert, but the comment lines - the ones that start with a # - cause a problem becasue those lines do not have the same number f fields as the data lines.
If I manually deleted the comments, I can perform a bulk insert.
Is there a way to perform a bulk insert while excluding lines based on a match such as : any line that beings with a "#".
Thanks.
The approach I generally use with BULK INSERT and irregular data is to push the incoming data into a temporary staging table with a single VARCHAR(MAX) column.
Once it's in there, I can use more flexible decision-making tools like SQL queries and string functions to decide which rows I want to select out of the staging table and bring into my main tables. This is also helpful because BULK INSERT can be maddeningly cryptic about the why and how of why it fails on a specific file.
The only other option I can think of is using pre-upload scripting to trim comments and other lines that don't fit your tabular criteria before you do your bulk insert.
I recommend using logparser.exe instead. LogParser has some pretty neat capabilities on its own, but it can also be used to format the IIS log to be properly imported by SQL Server.
Microsoft has a tool called "PrepWebLog" http://support.microsoft.com/kb/296093 - which strips-out these hash/pound characters, however I'm running it now (using a PowerShell script for multiple files) and am finding its performance intolerably slow.
I think it'd be faster if I wrote a C# program (or maybe even a macro).
Update: PrepWebLog just crashed on me. I'd avoid it.
Update #2, I looked at PowerShell's Get-Content and Set-Content commands but didn't like the syntax and possible performance. So I wrote this little C# console app:
if (args.Length == 2)
{
string path = args[0];
string outPath = args[1];
Regex hashString = new Regex("^#.+\r\n", RegexOptions.Multiline | RegexOptions.Compiled);
foreach (string file in Directory.GetFiles(path, "*.log"))
{
string data;
using (StreamReader sr = new StreamReader(file))
{
data = sr.ReadToEnd();
}
string output = hashString.Replace(data, string.Empty);
using (StreamWriter sw = new StreamWriter(Path.Combine(outPath, new FileInfo(file).Name), false))
{
sw.Write(output);
}
}
}
else
{
Console.WriteLine("Source and Destination Log Path required or too many arguments");
}
It's pretty quick.
Following up on what PeterX wrote, I modified the application to handle large log files since anything sufficiently large would create an out-of-memory exception. Also, since we're only interested in whether or not the first character of a line starts with a hash, we can just use StartsWith() method on the read operation.
class Program
{
static void Main(string[] args)
{
if (args.Length == 2)
{
string path = args[0];
string outPath = args[1];
string line;
foreach (string file in Directory.GetFiles(path, "*.log"))
{
using (StreamReader sr = new StreamReader(file))
{
using (StreamWriter sw = new StreamWriter(Path.Combine(outPath, new FileInfo(file).Name), false))
{
while ((line = sr.ReadLine()) != null)
{
if(!line.StartsWith("#"))
{
sw.WriteLine(line);
}
}
}
}
}
}
else
{
Console.WriteLine("Source and Destination Log Path required or too many arguments");
}
}
}
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");
}