ESP32 skips last value in JSON - json

I'm trying to send a JSON to a ESP32 and set the value to a variable, for the first 3 variables it works fine, but for some reason it skips the last one. Right now it's sent in an array, but when it's not in an array and I make it a JSONObject instead of a JSONArray it even skips the last 2 values.
When trying a hardcoded JSON it works fine though.
Here is the code:
#include <Arduino.h>
#include <EEPROM.h>
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
#include <NeoPixelBus.h>
#include <AsyncJson.h>
#include <ArduinoJson.h>
#define EEPROM_SIZE 512
const int powerStateAddress = 0;
const int groupNumberAddress = 2;
const uint16_t pixelCount = 82;
const uint pixelPin = 17;
const uint relayPin = 26;
const char* ssid = "";
const char* password = "";
AsyncWebServer server(80);
const size_t jsonCapacity = JSON_OBJECT_SIZE(3) + JSON_OBJECT_SIZE(4) + 70;
int powerState;
int groupNumber;
int colorSaturation = 255;
int greenValue;
int redValue;
int blueValue;
int whiteValue;
NeoPixelBus<NeoGrbwFeature, NeoEsp32I2s1800KbpsMethod> strip(pixelCount, pixelPin);
RgbwColor green(colorSaturation, 0, 0, 0);
RgbwColor red(0, colorSaturation, 0, 0);
RgbwColor blue(0, 0, colorSaturation, 0);
RgbwColor white(0, 0, 0, colorSaturation);
RgbwColor black(0);
void setGroupNumber(DynamicJsonDocument json) {
groupNumber = json["groupNumber"];
EEPROM.write(groupNumberAddress, groupNumber);
EEPROM.commit();
}
void setColor() {
for(uint16_t pixel = 0; pixel < pixelCount; pixel++) {
strip.SetPixelColor(pixel, RgbwColor(greenValue, redValue, blueValue, whiteValue));
}
}
void setColorValues(DynamicJsonDocument json) {
JsonArray colorValues = json["colorValues"];
if(greenValue != colorValues[0]) {
greenValue = colorValues[0];
}
if(redValue != colorValues[1]) {
redValue = colorValues[1];
}
if(blueValue != colorValues[2]) {
blueValue = colorValues[2];
}
if(whiteValue != colorValues[3]) {
whiteValue = colorValues[3];
}
setColor();
}
void setBrightness(DynamicJsonDocument json) {
colorSaturation = json["brightness"];
setColor();
}
DynamicJsonDocument parseData(AsyncWebServerRequest *request, uint8_t *data, String endpoint) {
DynamicJsonDocument doc(jsonCapacity);
DeserializationError err = deserializeJson(doc, data);
Serial.println(serializeJson(doc, Serial));
if(err) {
request->send(400, "text/plain", "err on" + endpoint);
} else {
request->send(200, "application/json", "{'msg': 'OK'}");
}
return doc;
}
void setup() {
Serial.begin(115200);
while(!Serial) {}
EEPROM.begin(EEPROM_SIZE);
if(EEPROM.read(powerStateAddress) == LOW || EEPROM.read(powerStateAddress) == HIGH) {
powerState = EEPROM.read(powerStateAddress);
if(powerState == HIGH) {
digitalWrite(relayPin, HIGH);
}
} else {
powerState = LOW;
EEPROM.write(powerStateAddress, powerState);
EEPROM.commit();
}
if(EEPROM.read(groupNumberAddress) != 255) {
groupNumber = EEPROM.read(groupNumberAddress);
}
WiFi.begin(ssid, password);
while(WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(250);
}
Serial.println(WiFi.localIP());
server.on("/controller/setGroup", HTTP_POST, [](AsyncWebServerRequest *request) {}, NULL,
[](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
DynamicJsonDocument doc = parseData(request, data, "/setGroup");
setGroupNumber(doc);
});
server.on("/controller/setColor", HTTP_POST, [](AsyncWebServerRequest *request) {}, NULL,
[](AsyncWebServerRequest *request, uint8_t *data, size_t len, size_t index, size_t total) {
DynamicJsonDocument doc = parseData(request, data, "/setColor");
setColorValues(doc);
});
server.begin();
}
void loop() {
Serial.println(powerState);
Serial.println(EEPROM.read(powerStateAddress));
Serial.println(groupNumber);
Serial.println(EEPROM.read(groupNumberAddress));
Serial.print("Brightness: ");
Serial.println(colorSaturation);
Serial.print("green: ");
Serial.println(greenValue);
Serial.print("red: ");
Serial.println(redValue);
Serial.print("blue: ");
Serial.println(blueValue);
Serial.print("white: ");
Serial.println(whiteValue);
Serial.println("---------");
delay(2000);
}
Here is the JSON that I send:
"colorValues": [
255,
255,
255,
255
]
}
This is what the ESP32 receives:
{"colorValues":[255,255,255,255]}33
And this is the result:
green: 255
red: 255
blue: 255
white: 0

Okay here is an example of my JavasScript code when I ran into the issue
var colors = {"red":255, "green":255, "blue":255};
is just added the coma to the back like so
var colors = {"red":255, "green":255, "blue":255,};
and now my arduino can find the blue I intend to use

I ran into the same issue and weird enough if you add an element to the object like the 115:
111,
112,
113,
114,
115
]
}
Then it gets the last 114 and still doesn't get the 115 but atleast you can use you 4 elements, I am guessing it is somethint to do with the last elmenet doesn't have a comma

Related

How to write multiple ssid's and passwords to the same json file ESP32

I am currently testing a piece of code using arduinojson6. My goal is to store multiple ssid's and passwords to the esp32 SPIFF.
The uneddited question contained a piece of code that would append to the file rather than reading doc, deleting /SSID.json, adding to doc serialization and saving the file again like I have now, is also not the solution.
the desired json file would be:
{"information":[{ "SSID":"variable blaat1", "PASS1":"variable Abc1", "NUMBER": "1" },{ "SSID":"variable blaat2", "PASS2":"variable Abc2", "NUMBER": "2" },{ "SSID":"variable blaat3", "PASS3":"variable Abc3", "NUMBER": "3" },{ "SSID":"variable blaat4", "PASS4":"variable Abc4", "NUMBER": "4" },{ "SSID":"variable blaat5", "PASS5":"variable Abc5", "NUMBER": "5" }]}
Instead, when more then 1 value is serialized and appended it will read like this:
{
"information": {},
"test": [
"mooiman\n",
"mooiweer\n"
],
"number": [
1,
2
]
}
Maybe some of you know how to serialize it properly.
The code I test with:
#include <Arduino.h>
#include <WiFi.h>
//#include <time.h>
//#include <ESP32Ping.h>
#include "FS.h"
#include "SPIFFS.h"
//#include <HTTPClient.h>
#include <ArduinoJson.h>
int numberofInputs = 1;
String ssid = "YourSSID";
String passwords = "YourPassword";
String readString;
char FileReadBuff[1024];
DynamicJsonDocument doc(1024);
void readFile(fs::FS &fs, const char * path){
if (SPIFFS.exists("/SSID.json") == false)
{
File file = SPIFFS.open("/SSID.json", FILE_WRITE);
if (!file) {
Serial.println("There was an error opening the file for writing");
return;
}
if (file.print("SSID")) {
Serial.println("File was written");
} else {
Serial.println("File write failed");
}
file.close();
}
Serial.printf("Reading file: %s\r\n", path);
File file = fs.open(path);
if(!file || file.isDirectory()){
Serial.println("- failed to open file for reading");
return;
}
uint16_t i = 0;
Serial.println("reading");
while (file.available()) {
FileReadBuff[i] = file.read();
i++;
}
file.close();
}
void CleanFile(fs::FS &fs, const char * path, const char * message) {
for( int i = 0; i < sizeof(FileReadBuff); ++i ){
FileReadBuff[i] = (char)0;
}
File file = SPIFFS.open(path, FILE_WRITE);
if (fs.remove(path)) {
Serial.println("\r\n- file cleaned");
} else {
Serial.println("\r\n- Cleaning failed");
}
file.print(path);
}
void appendFile(fs::FS &fs, const char * path, const char * message){
if (SPIFFS.exists("/SSID.json") == false)
{
File file = SPIFFS.open("/SSID.json", FILE_WRITE);
if (!file) {
Serial.println("There was an error opening the file for writing");
return;
}
if (file.print("SSID")) {
Serial.println("File was written");
} else {
Serial.println("File write failed");
}
file.close();
}
Serial.printf("Appending to file: %s\r\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file){
Serial.println("- failed to open file for appending");
return;
}
if(file.println(message)){
Serial.println("- message appended");
} else {
Serial.println("- append failed");
}
file.close();
}
void Deserialization(){
for( int i = 0; i < sizeof(FileReadBuff); ++i ){
FileReadBuff[i] = (char)0;
}
readFile(SPIFFS, "/SSID.json"); //read everything from ssid.json file
const char * JsonFF = FileReadBuff; // put everything in to const char
Serial.print("Json From File:"); Serial.println(JsonFF);
DeserializationError error = deserializeJson(doc, JsonFF);
if(error){
Serial.print(F("deserializeJson() failed: ")); Serial.println(error.f_str()); // if not legit print error
}
if(!error){
String information = doc["information"];
Serial.println(information);
information = "";
}
}
void testjson(){
readString = "";
while(readString.length() < 1) {
while (Serial.available()) {
delay(10); //small delay to allow input buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
break;
} //breaks out of capture loop to print readstring
readString += c;
} //makes the string readString
}
if (readString.length() > 0) {
Serial.println(readString); //prints string to serial port out
if (readString.indexOf("READ") >= 0) {
Serial.println("reading file");
readFile(SPIFFS, "/SSID.json");
Serial.println(FileReadBuff);
for( int i = 0; i < sizeof(FileReadBuff); ++i ){
FileReadBuff[i] = (char)0;
}
}
if (readString.indexOf("DES") >= 0) { //DEZ deserialize will result in an error because json file is currently not valid
Serial.println("reading deserialized json");
Deserialization();
}
if (readString.indexOf("CLEAN") >= 0) { //CLEAN cleans the SSID.json file
Serial.println("reading deserialized json");
CleanFile(SPIFFS, "/SSID.json", "");
}
if (readString.indexOf("WRANDOM") >= 0){ //WRANDOM writes a random string to the SSID.json file
readString = "";
Serial.println("Going to write the following input:"); //waiting for user input
while(readString.length() < 1) {
while (Serial.available()) {
delay(10); //small delay to allow input buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
break;
} //breaks out of capture loop to print readstring
readString += c;
} //makes the string readString
}
if (readString.length() > 0) {
Serial.println(readString); //prints string to serial port out
`here is the part we're talking about`
CleanFile(SPIFFS, "/SSID.json", "");
JsonObject information = doc.createNestedObject("information");
String SerializedJson = "";
doc["test"].add(readString);
doc["number"].add(numberofInputs);
serializeJsonPretty(doc, SerializedJson);
appendFile(SPIFFS, "/SSID.json", SerializedJson.c_str());
SerializedJson = "";
numberofInputs ++;
return;
}
}
}
}
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
if (!SPIFFS.begin(true)) {
Serial.println("An Error has occurred while mounting SPIFFS");
return;
}
if (SPIFFS.exists("/SSID.json") == false)
{
File file = SPIFFS.open("/SSID.json", FILE_WRITE);
if (!file) {
Serial.println("There was an error opening the file for writing");
return;
}
if (file.print("SSID")) {
Serial.println("File was written");
} else {
Serial.println("File write failed");
}
file.close();
}
WiFi.mode(WIFI_MODE_STA);
WiFi.begin(ssid.c_str(), passwords.c_str());
while (WiFi.status() != WL_CONNECTED) { //Check for the connection
delay(1000);
Serial.print(".");
}
Serial.println("Connected");
}
void loop() {
// put your main code here, to run repeatedly:
readString = ""; //clears variable for new input
Serial.println("Ready for new input: ");
testjson();
}
So when you serial write WRANDOM you'll get promted to put in something.
When that is recieved it will store that in json.
Do that another time.
Next when you serial write READ it will show you the saved /SSID.json.
Thanks in advance.
Note that the DynamicJsonDocument startsof empty.
PS. I know littlefs is the new spiff but lets first try to make this work (or I need to make sepperate files for every ssid+password)
Here is a test sketch you can implement to your project.
I did not had the time to write more detailed sketch than this.
Let me know if you have any question about this
#include <Arduino.h>
#include "FS.h"
#include <LittleFS.h>
#include <ArduinoJson.h>
#define DOC_SIZE 5000
/*
Example JSON :
{
"information":[
{ "SSID":"variable blaat1", "PASS1":"variable Abc1", "NUMBER": "1" },
{ "SSID":"variable blaat2", "PASS2":"variable Abc2", "NUMBER": "2" },
{ "SSID":"variable blaat3", "PASS3":"variable Abc3", "NUMBER": "3" },
{ "SSID":"variable blaat4", "PASS4":"variable Abc4", "NUMBER": "4" },
{ "SSID":"variable blaat5", "PASS5":"variable Abc5", "NUMBER": "5" }
]
}
*/
/*
When you create a JSON array, you don't need to push the index of the object, since you can later
ask for the array size, therefor you know the indexes. Also you don't need to separate the passwords
like PASS1 or PASS2 since every cred is a separate object.
*/
void addCredentials( const char* SSID, const char* PW ){
// Create a static JSON document.
StaticJsonDocument fileDoc(DOC_SIZE);
// Open the file containing the credentials
File credFile = LittleFS.open(FILE_PATH,FILE_READ);
// Check if it opened.
if( !credFile ){ Serial.println("Failed to open file"); return; }
// Deserialize the file
DeserializationError error = deserializeJson(fileDoc, credFile );
// Check if the deserialization has any errors.
if( error ){ Serial.printf("Error on deserialization: %s\n", error.c_str() );
// Get the info array from the JSON.
JsonArray infoArr = fileDoc["information"].as<JsonArray>();
// Create a new object inside the array.
JsonObject newCred = infoArr.createNestedObject();
// Add credentials to the object.
newCred["SSID"] = SSID;
newCred["PASS"] = PW;
// Serialize everythig back to the file.
serializeJson(fileDoc, credFile);
// Close the file.
credFile.close();
}
// Open the file and put the pretty json into the serial directly.
void printFileContent(){
File credFile = LittleFS.open(FILE_PATH,FILE_READ);
if( !credFile ){ Serial.println("Failed to open file"); return; }
serializeJsonPretty(Serial, credFile);
credFile.close();
}
void clearFile(){
if( !LittleFS.exists(FILE_PATH) ){ Serial.println("Credentials file does not exists yet!"); return; }
File credFile = LittleFS.open(FILE_PATH,FILE_READ);
credFile.remove();
}
void getUserInput(){
if( !Serial.available() ){ return; }
// Get the credentials or whatever from the serial
// and call the **addCredentials( const char* SSID, const char* PW );** function.
}
void setup() {
Serial.begin(115200);
}
void loop() {
getUserInput();
}
I got it figured out with help from Dr.Random. It wasn't the full answer but it helped getting the json format and apend to that file correctly. The following code is a working example.
#include <Arduino.h>
#include <WiFi.h>
#include "FS.h"
#include "LittleFS.h"
#include <ArduinoJson.h>
#define FORMAT_LITTLEFS_IF_FAILED true
#define DOC_SIZE 5000
#define FILE_PATH "/SSID.json"
String ssid = "yourssid";
String passwords = "yourpass";
String readString;
char FileReadBuff[1024];
void readFile(fs::FS &fs, const char * path){
Serial.printf("Reading file: %s\r\n", path);
File file = fs.open(path);
if(!file || file.isDirectory()){
Serial.println("- failed to open file for reading");
return;
}
Serial.println("- read from file:");
while(file.available()){
Serial.write(file.read());
}
file.close();
}
void Showone(int wichone){
DynamicJsonDocument doc(DOC_SIZE);
File credFile = LittleFS.open(FILE_PATH, FILE_READ);// open file for reading
DeserializationError error = deserializeJson(doc, credFile);// deserialize json
if( !credFile ){ Serial.println("Failed to open file"); return; }// if file doesn't exist, return
const char* SSID = doc[wichone]["SSID"]; //
const char* PASS = doc[wichone]["PASS"]; //
Serial.print("SSID and PASS = "); Serial.print(SSID); Serial.print(PASS); Serial.print(" "); Serial.println(" ");
credFile.close();
}
void addCredentials(const char * input){
DynamicJsonDocument doc(DOC_SIZE);// create json doc
String Serialized; // create string to store serialized json
File credFile = LittleFS.open(FILE_PATH, FILE_READ);// open file for reading
if( !credFile ){ Serial.println("Failed to open file"); return; }// if file doesn't exist, return
DeserializationError error = deserializeJson(doc, credFile);// deserialize json
if( error ){ Serial.printf("Error on deserialization: %s\n", error.c_str() );} //error when spiff is empty or not formatted correctly
JsonArray inforArr = doc["information"].as<JsonArray>();// get array from json
JsonObject newCred = doc.createNestedObject();// create new object in json
newCred["SSID"] = input;
newCred["PASS"] = input;
serializeJsonPretty(doc, Serialized);
Serial.print("input = "); Serial.println(input);
Serial.print("Serialized: "); Serial.println(Serialized);
File credFile2 = LittleFS.open(FILE_PATH, FILE_WRITE);// open file for writing
credFile2.print(Serialized);
credFile2.close();
credFile.close();
Serialized = "";
}
void testjson(){
readString = "";
while(readString.length() < 1) {
while (Serial.available()) {
delay(10); //small delay to allow input buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
break;
} //breaks out of capture loop to print readstring
readString += c;
} //makes the string readString
}
if (readString.length() > 0) {
Serial.println(readString); //prints string to serial port out
if (readString.indexOf("READ") >= 0) {
Serial.println("reading file");
readFile(LittleFS, "/SSID.json");
Serial.println(FileReadBuff);
for( int i = 0; i < sizeof(FileReadBuff); ++i ){
FileReadBuff[i] = (char)0;
}
}
if (readString.indexOf("SHOW") >= 0) {
readString = "";
Serial.println("Showing the following input(number): "); //waiting for user input
while(readString.length() < 1) {
while (Serial.available()) {
delay(10); //small delay to allow input buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
break;
} //breaks out of capture loop to print readstring
readString += c;
} //makes the string readString
}
if (readString.length() > 0) {
Serial.println(readString); //prints string to serial port out
Showone(readString.toInt());
}
}
}
if (readString.indexOf("CLEAN") >= 0) { //CLEAN cleans the SSID.json file
Serial.println("reading deserialized json");
File credFile = LittleFS.open(FILE_PATH, FILE_WRITE);// open file for writing
credFile.print("");
credFile.close();
}
if (readString.indexOf("WRANDOM") >= 0){ //WRANDOM writes a random string to the SSID.json file
readString = "";
Serial.println("Going to write the following input:"); //waiting for user input
while(readString.length() < 1) {
while (Serial.available()) {
delay(10); //small delay to allow input buffer to fill
if (Serial.available() > 0) {
char c = Serial.read(); //gets one byte from serial buffer
if (c == ',') {
break;
} //breaks out of capture loop to print readstring
readString += c;
} //makes the string readString
}
if (readString.length() > 0) {
Serial.println(readString); //prints string to serial port out
addCredentials(readString.c_str());
}
}
}
}
}
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
if(!LittleFS.begin(FORMAT_LITTLEFS_IF_FAILED)){
Serial.println("LittleFS Mount Failed");
return;
}
//if /ssid.json doesn't exist, create it littlefs
if(!LittleFS.exists(FILE_PATH)){
Serial.println("File doesn't exist, creating it");
File credFile = LittleFS.open(FILE_PATH, FILE_WRITE);
if(!credFile){
Serial.println("Failed to create file");
return;
}
credFile.close();
}
WiFi.mode(WIFI_MODE_STA);
WiFi.begin(ssid.c_str(), passwords.c_str());
while (WiFi.status() != WL_CONNECTED) { //Check for the connection
delay(1000);
Serial.print(".");
}
Serial.println("Connected");
}
void loop() {
// put your main code here, to run repeatedly:
readString = ""; //clears variable for new input
Serial.println("Ready for new input: ");
testjson();
}
Any improvements are still desirable.

C program giving weird output from HTML GET input and prints at bottom of HTML page

I made a C webserver that is able to display an HTML page and then take input from a text box. So far it works to display basic commands like ls but for some reason when i enter into the text box the command ls -l | wc -l it will only act as if i typed in ls -l | w and wont process the command because of this. Based on how im tokenizing i dont understand why it wont go past this line? In the textbox that ends up being the input it comes as ls+-l+%7C+wc+-l which is why i had to separate it in this way. Also my output displays at the bottom of the html page, how can i place it in the correct output areas?
Server.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#include <poll.h>
#define PORT "3838" //port being connected to
#define MAXLEN 800
#define BACKLOG 10 //number of pending connections to be held in queue
//format of html page
char header []=
"HTTP/1.1 200 Ok\r\n"
"Content-Type: text/html; charset=UTF-8\r\n\r\n"
"<!DOCTYPE html>\r\n"
"<html>\n"
"<head>\n"
"<title>Web-Based Remote Command Server</title>\r\n"
"</head>\n"
"<body>\n\n";
char input []=
"<form action= \"/run\" method= \"GET\"> \n"
"Command: <input type=\"text\" size=\"100\" name=\"command\">\n"
"<input type=\"submit\" value=\"Run\">\n"
"</form>";
char output []=
"<p>Command that was run and testing this:</p>\n"
"<pre>Your server will include the command that was just run here.</pre>\n\n"
"<p>Standard Output:</p>\n""<pre>Your server will include the stdout results here.</pre>\n\n";
char outputerr[]=
"<p>Standard Error:</p>\n"
"<pre>Your server will include the stderr results here.</pre>\r\n\r\n"
"</body>\r\n""</html>\r\n";
char *buff = header;
void sigchld_handler(int s)
{
(void)s; // quiet unused variable warning
// waitpid() might overwrite errno, so we save and restore it:
int saved_errno = errno;
while(waitpid(-1, NULL, WNOHANG) > 0);
errno = saved_errno;
}
void *get_in_addr(struct sockaddr *sa)
{
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
char *parse(char *command){
char * newCommand = (char *) malloc(sizeof(char)*50);
int tgt = 0;
newCommand = strtok(command, " ");
//printf("%s\n", newCommand);
newCommand = strtok(NULL, "/run?command= ");
//printf("%s\n", newCommand);
for(int src = 0; src< strlen(newCommand); src++){
if(newCommand[src] == '+')
{
newCommand[src] = ' ';
}
else if(newCommand[src] == '%')
{
newCommand[src] = ' ';
}
else if(newCommand[src] == '7')
{
newCommand[src] = ' ';
}
else if(newCommand[src] == 'C')
{
newCommand[src] = '|';
}
}
return newCommand;
}
char * execution(char *command){
//printf("yo:%s\n",command );
int piper[2];
size_t len = 0;
pipe(piper);
char* output = malloc(1000 * sizeof(char));
memset(output, '\0', 1000* sizeof(char));
pid_t pid = fork();
if(pid != 0)// parent
{
wait(NULL);
close(piper[1]);
int n = sizeof(output);
struct pollfd * poll_fd = malloc(sizeof(struct pollfd));
poll_fd->fd = piper[0];
poll_fd->events = POLLIN;
//wait(NULL);
//printf("done\n");
//printf("AAA %s", output);
if(poll(poll_fd, 1, 0) == 1){ // pipe data check
read(piper[0], output, 1000);
}
//printf("the command is %s\n", output);
//read(&output,output, piper[0]);
// printf("%s\n",piper[0]);
// dup2(piper[1],1);
// close(0)
}
else{
//dup2(piper[1], 1);
//printf("run : %s", command);
close(1);
dup(piper[1]);
//close(0);
execlp(command, command, NULL);
exit(1);
}
// dup2 execute and print it out in parent
// if(*(commands+1)!=NULL) // redirect stdout as long as were not at the last row
// {
// dup2(piper[1],1);
// close(piper[0]);
// }
return output;
}
int main (void){
int sockfd;
int new_fd;
struct addrinfo hints;
struct addrinfo *serverinfo;
struct addrinfo *p;
struct sockaddr_storage client_addr;
socklen_t addrsize;
struct sigaction sa;
int yes = 1;
char s[INET6_ADDRSTRLEN];
int status;
memset(&hints, 0, sizeof hints); //makes struct empty
hints.ai_family = AF_UNSPEC; //IPv4 or v6
hints.ai_socktype = SOCK_STREAM; //TCP type need
hints.ai_flags = AI_PASSIVE; //Fill in IP for us
//if can't get address info print error
if((status = getaddrinfo(NULL, PORT, &hints, &serverinfo)) != 0){
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(status));
return 1;
}
for(p = serverinfo; p != NULL; p = p->ai_next){
if((sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1){
perror("server: socket");
continue;
}
if(setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1){
perror("setsockopt");
exit(1);
}
if(bind(sockfd, p->ai_addr, p->ai_addrlen) == -1){
close(sockfd);
perror("server: bind");
continue;
}
break;
}
freeaddrinfo(serverinfo);
if(p == NULL){
fprintf(stderr, "server: failed to bind\n");
exit(1);
}
if(listen(sockfd, BACKLOG) == -1){
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections....\n");
while(1){
addrsize = sizeof client_addr;
new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &addrsize);
if(new_fd == -1){
perror("Did not accept");
continue;
}
inet_ntop(client_addr.ss_family, get_in_addr((struct sockaddr *)&client_addr), s, sizeof s);
printf("server: got connection from %s\n", s);
if(!fork()){
close(sockfd);
int bufsize = 1024;
char *buffer = malloc(bufsize);
recv(new_fd, buffer, bufsize, 0);
send(new_fd, header, bufsize, 0);
//printf("%s\n", buffer);
//printf("%s\n", parse(buffer));
//printf("%s\n", execution(parse(buffer)));
//int length = strlen(output);
//output [length + 1] = execution(parse(buffer));
//write(new_fd, "HTTP/1.1 200 OK\n", 16);
//write(new_fd, "Content-length: 46\n", 19);
//write(new_fd, "Content-type: text/html\n\n", 25);
//write(new_fd, "<html><head>\n<head>\n<title>The CAvengers Web Page</title>\n</head>\n</html>", 46);
if(send(new_fd, execution(parse(buffer)), 1000, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd);
}
return 0;
}

How to get all html file with a HTTP GET request using c++?

I need to create a c++ console application that query a site in turn to get the html page.
The site is static because when I queried it in the url I see the html file, so I use this code:
send(Socket, "GET /it/ricette/q-torte_forno_statico.html HTTP/1.1\r\nHost: worldrecipes.expo2015.org/\r\nConnection: close\r\n\r\n", strlen("GET /it/ricette/q-torte_forno_statico.html HTTP/1.1\r\nHost: worldrecipes.expo2015.org\r\nConnection: close\r\n\r\n"), 0);
char buffer[1000000];
int nDataLength;
while ((nDataLength = recv(Socket, buffer, 1000000, 0)) > 0) {
int i = 0;
while (buffer[i] >= 32 || buffer[i] == '\n' || buffer[i] == '\r') {
cout << buffer[i];
i += 1;
}
}
It doesn't give me any errors but don't show me the whole html page and every time that I call send the request I get different answers ... why?
This code below seems to only work on the index page worldrecipes.expo2015.org and not the sub pages. You might want to look at more advanced webbrowser controls for visual studio for parsing and processing HTML.
Like here : http://www.codeproject.com/Articles/3365/Embed-an-HTML-control-in-your-own-window-using-pla
here : https://msdn.microsoft.com/en-us/library/aa752046(v=vs.85).aspx
and here : http://www.codeproject.com/Articles/3919/Using-the-WebBrowser-control-simplified
Example code:
#include <windows.h>
#include <string>
#include <stdio.h>
using std::string;
#pragma comment(lib,"ws2_32.lib")
HINSTANCE hInst;
WSADATA wsaData;
void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename);
SOCKET connectToServer(char *szServerName, WORD portNum);
int getHeaderLength(char *content);
char *readUrl2(char *szUrl, long &bytesReturnedOut, char **headerOut);
int main()
{
const int bufLen = 1024;
char *szUrl = "http://worldrecipes.expo2015.org/it/ricette/q-torte_forno_statico.html";
long fileSize;
char *memBuffer, *headerBuffer;
FILE *fp;
memBuffer = headerBuffer = NULL;
if ( WSAStartup(0x101, &wsaData) != 0)
return -1;
memBuffer = readUrl2(szUrl, fileSize, &headerBuffer);
printf("returned from readUrl\n");
printf("data returned:\n%s", memBuffer);
if (fileSize != 0)
{
printf("Got some data\n");
fp = fopen("downloaded.file", "wb");
fwrite(memBuffer, 1, fileSize, fp);
fclose(fp);
// SetDlgItemText(hwndDlg, IDC_EDIT4, headerBuffer);
// SetDlgItemText(hwndDlg, IDC_EDIT5, memBuffer);
delete(memBuffer);
delete(headerBuffer);
}
WSACleanup();
return 0;
}
void mParseUrl(char *mUrl, string &serverName, string &filepath, string &filename)
{
string::size_type n;
string url = mUrl;
if (url.substr(0,7) == "http://")
url.erase(0,7);
if (url.substr(0,8) == "https://")
url.erase(0,8);
n = url.find('/');
if (n != string::npos)
{
serverName = url.substr(0,n);
filepath = url.substr(n);
n = filepath.rfind('/');
filename = filepath.substr(n+1);
}
else
{
serverName = url;
filepath = "/";
filename = "";
}
}
SOCKET connectToServer(char *szServerName, WORD portNum)
{
struct hostent *hp;
unsigned int addr;
struct sockaddr_in server;
SOCKET conn;
conn = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (conn == INVALID_SOCKET)
return NULL;
if(inet_addr(szServerName)==INADDR_NONE)
{
hp=gethostbyname(szServerName);
}
else
{
addr=inet_addr(szServerName);
hp=gethostbyaddr((char*)&addr,sizeof(addr),AF_INET);
}
if(hp==NULL)
{
closesocket(conn);
return NULL;
}
server.sin_addr.s_addr=*((unsigned long*)hp->h_addr);
server.sin_family=AF_INET;
server.sin_port=htons(portNum);
if(connect(conn,(struct sockaddr*)&server,sizeof(server)))
{
closesocket(conn);
return NULL;
}
return conn;
}
int getHeaderLength(char *content)
{
const char *srchStr1 = "\r\n\r\n", *srchStr2 = "\n\r\n\r";
char *findPos;
int ofset = -1;
findPos = strstr(content, srchStr1);
if (findPos != NULL)
{
ofset = findPos - content;
ofset += strlen(srchStr1);
}
else
{
findPos = strstr(content, srchStr2);
if (findPos != NULL)
{
ofset = findPos - content;
ofset += strlen(srchStr2);
}
}
return ofset;
}
char *readUrl2(char *szUrl, long &bytesReturnedOut, char **headerOut)
{
const int bufSize = 512;
char readBuffer[bufSize], sendBuffer[bufSize], tmpBuffer[bufSize];
char *tmpResult=NULL, *result;
SOCKET conn;
string server, filepath, filename;
long totalBytesRead, thisReadSize, headerLen;
mParseUrl(szUrl, server, filepath, filename);
///////////// step 1, connect //////////////////////
conn = connectToServer((char*)server.c_str(), 80);
///////////// step 2, send GET request /////////////
sprintf(tmpBuffer, "GET %s HTTP/1.0", filepath.c_str());
strcpy(sendBuffer, tmpBuffer);
strcat(sendBuffer, "\r\n");
sprintf(tmpBuffer, "Host: %s", server.c_str());
strcat(sendBuffer, tmpBuffer);
strcat(sendBuffer, "\r\n");
strcat(sendBuffer, "\r\n");
send(conn, sendBuffer, strlen(sendBuffer), 0);
// SetWindowText(edit3Hwnd, sendBuffer);
printf("Buffer being sent:\n%s", sendBuffer);
///////////// step 3 - get received bytes ////////////////
// Receive until the peer closes the connection
totalBytesRead = 0;
while(1)
{
memset(readBuffer, 0, bufSize);
thisReadSize = recv (conn, readBuffer, bufSize, 0);
if ( thisReadSize <= 0 )
break;
tmpResult = (char*)realloc(tmpResult, thisReadSize+totalBytesRead);
memcpy(tmpResult+totalBytesRead, readBuffer, thisReadSize);
totalBytesRead += thisReadSize;
}
headerLen = getHeaderLength(tmpResult);
long contenLen = totalBytesRead-headerLen;
result = new char[contenLen+1];
memcpy(result, tmpResult+headerLen, contenLen);
result[contenLen] = 0x0;
char *myTmp;
myTmp = new char[headerLen+1];
strncpy(myTmp, tmpResult, headerLen);
myTmp[headerLen] = NULL;
delete(tmpResult);
*headerOut = myTmp;
bytesReturnedOut = contenLen;
closesocket(conn);
return(result);
}

Segfault submitting query

I'm testing a wrapper library for the MySQL C API, and I'm trying to insert a row.
I've tested it in GDB, and the line (in my code) that faults appears as follows:
Breakpoint 1, cq_query (con=0x7fffffffe1c0,
query=0x6014a0 "INSERT INTO TaskType(state,parentID,displayName) VALUES(1,19,'boop')") at cqstatic.c:32
32 return mysql_query(con->con, query);
This query string is formatted correctly (I can paste it into the mysql command line, and it runs fine), so it would appear that something is wrong in the connection (con->con is of type void * cast to MYSQL *).
My other functions which do SELECT and UPDATE work fine. Only insert appears to be broken.
Here is my Test Code
#include <stdio.h>
#include <string.h>
#include <cquel.h>
int main(void)
{
struct dbconn con = cq_new_connection("myurl.tld",
"myuser", "mypasswd", "mydb");
cq_init(1024, 128);
char *fields[] = {
"state",
"parentID",
"displayName"
};
char *vals[] = {
"1",
"19",
"boop"
};
struct drow *row = cq_new_drow(3);
cq_drow_set(row, vals);
struct dlist *list = cq_new_dlist(3, fields, "");
cq_dlist_add(list, row);
cq_insert(con, "TaskType", list);
cq_free_dlist(list);
return 0;
}
Insert Function
int cq_insert(struct dbconn con, const char *table, const struct dlist *list)
{
int rc;
char *query, *columns, *values;
const char *fmt = "INSERT INTO %s(%s) VALUES(%s)";
if (table == NULL)
return 1;
if (list == NULL)
return 2;
query = calloc(CQ_QLEN, sizeof(char));
if (query == NULL)
return -1;
columns = calloc(CQ_QLEN/2, sizeof(char));
if (columns == NULL) {
free(query);
return -2;
}
values = calloc(CQ_QLEN/2, sizeof(char));
if (values == NULL) {
free(query);
free(columns);
return -3;
}
rc = cq_dlist_fields_to_utf8(&con, columns, CQ_QLEN/2, *list);
if (rc) {
free(query);
free(columns);
free(values);
return 100;
}
rc = cq_connect(&con);
if (rc) {
free(query);
free(columns);
free(values);
return 200;
}
for (struct drow *r = list->first; r != NULL; r = r->next) {
rc = cq_drow_to_utf8(&con, values, CQ_QLEN/2, *r);
if (rc)
break;
rc = snprintf(query, CQ_QLEN, fmt, table, columns, values);
if (CQ_QLEN <= (size_t) rc) {
rc = -4;
break;
}
rc = cq_query(&con, query);
if (rc) {
rc = 201;
break;
}
}
cq_close_connection(&con);
free(query);
free(columns);
free(values);
return rc;
}
And one of the important helper functions
int cq_fields_to_utf8(struct dbconn *con, char *buf, size_t buflen,
size_t fieldc, char * const *fieldnames, bool usequotes)
{
int rc = 0;
size_t num_left = fieldc, written = 0;
if (num_left == 0)
return 1;
char *temp = calloc(CQ_FMAXLEN+3, sizeof(char));
if (NULL == temp)
return -1;
char *field = calloc((CQ_FMAXLEN+3)*2+1, sizeof(char));
if (NULL == field) {
free(temp);
return -2;
}
/* prevent appending to buffer */
buf[0] = '\0';
cq_connect(con);
for (size_t i = 0; i < fieldc; ++i) {
bool escaped = fieldnames[i][0] == '\\';
const char *orig = escaped ? &fieldnames[i][1] : fieldnames[i];
const char *value;
bool isstr = false;
if (!escaped) {
mysql_real_escape_string(con->con, field, orig, strlen(orig));
value = field;
if (usequotes)
for (size_t j = 0; j < strlen(value); ++j) {
if (!isdigit(value[j])) {
isstr = true;
break;
}
}
} else {
value = orig;
}
const char *a = isstr ? "'" : "";
const char *c = --num_left > 0 ? "," : "";
written += snprintf(temp, CQ_FMAXLEN+3, "%s%s%s%s", a, value, a, c);
if (written >= buflen) {
rc = 2;
break;
}
strcat(buf, temp);
}
cq_close_connection(con);
free(field);
free(temp);
return rc;
}
used when setting up the query string.
Found my own issue. Blame the 10 minute rule.
I didn't look closely enough at cq_insert(), and it is making a double connection, closing the second one, leaving the first one lost, and the pointer pointing to freed memory, so segfault.

Whats wrong with my function?

My char read function isnt working, it prints what i would like it to print but it prevents the program from going to the next step and and reading what number the user inputted, it worked fine before it was a function but i need it to have a certain amount of functions as this is an assignment
#include "aservelibs/aservelib.h"
#include <stdio.h>
#include <math.h>
int length();
float mtof( int note);
float octave(int notes);
char read(char print);
int main()
{
//do while the user hasnt pressed exit key (whatever)
int control[8] = {74, 71, 91, 93, 73, 72, 5, 84};
int index;
int mod;
float frequency;
int notes[8];
int response;
float octave;
char print;
mod = aserveGetControl(1);
//ask backwards, forwards, exit
//SCALING
//(getControl(75) / ((127 - 0) / (1000 - 100))) + 100;
while(true)
{
read(print);
mod = 0;
if(response == 1)
{
while(mod==0)
{
for(index = 0; index < 8; index++)
{
notes[index] = aserveGetControl(control[index]);
frequency = mtof(notes[index]);
aserveOscillator(0, frequency, 1.0, 0);
aserveSleep(length());
printf("Slider Value:%5d\n", notes[index]);
printf("frequency: %f\n", frequency);
mod = aserveGetControl(1);
octave = aserveGetControl(7);
}
}
}
else if(response == 2)
{
while(mod==0)
{
for(index = 7; index > 0; index--)
{
notes[index] = aserveGetControl(control[index]);
frequency = mtof(notes[index]);
aserveOscillator(0, frequency, 1.0, 0);
aserveSleep(length());
printf("Slider Value:%5d\n", notes[index]);
printf("%f", frequency);
mod = aserveGetControl(1);
}
}
}
else if(response == 0)
{
return 0;
}
}
}
int length()
{
return (aserveGetControl(75)/((127.0 - 0) / (1000 - 100))) + 100;
}
float mtof( int note)
{
return 440 * pow(2, (note-69) / 12.0);
}
float octave(int note)
{
float slider = aserveGetControl(7) / 16383.0;
slider *=24;
return 440 * pow(2, ((note+slider)-69) / 12.0);
}
char read(char print)
{
char response;
printf("Run Loop Forwards (1), Backwards (2), Exit (0)\nMove modwheel to return to menu\n");
scanf("%c", &response);
}
You need to return response from read:
char read(char print)
{
char response;
printf("Run Loop Forwards (1), Backwards (2), Exit (0)\nMove modwheel to return to menu\n");
scanf("%c", &response);
return response;
}
and you need to assign it in the main path of your code:
response = read(print);
I'd like to point out that you should really declare response as a char since that is what you are returning from read. Also, I can't see print being used anywhere so I'm not sure of the purpose of passing it to read.