reading and writing config file works

main
Steffen Pohle 2 years ago
parent b9f3b8e32c
commit 3171c860a5

@ -1,7 +1,13 @@
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include <string>
#include "configuration.h" #include "configuration.h"
#include "miniwebcam.h" #include "miniwebcam.h"
#include "json.h"
Configuration config; Configuration config;
@ -11,6 +17,7 @@ Configuration config;
Configuration::Configuration() { Configuration::Configuration() {
http_port = DEFAULT_HTTP_PORT; http_port = DEFAULT_HTTP_PORT;
https_port = DEFAULT_HTTPS_PORT; https_port = DEFAULT_HTTPS_PORT;
filename = DEFAULT_CONFIG_FILE;
runasdaemon = 0; runasdaemon = 0;
initflags = 0; initflags = 0;
@ -23,40 +30,99 @@ Configuration::~Configuration() {
/* /*
* print current configuration * print current configuration
*/ */
int Configuration::Print() { int Configuration::PrintConfig() {
printf ("#\n# default ports for http and https\n"); JSONParse jp;
if (http_port == DEFAULT_HTTP_PORT) printf ("# ");
printf ("http_port %d\n", http_port); //
if (https_port == DEFAULT_HTTPS_PORT) printf ("# "); // save current language and set to default C
printf ("https_port %d\n", https_port); std::string savedlocale = setlocale(LC_ALL, NULL);
setlocale (LC_ALL, "C");
jp.AddObject("http_port", http_port);
jp.AddObject("https_port", https_port);
//
// output the json string
printf ("%s\n", jp.ToString().c_str());
//
// restore language
setlocale (LC_ALL, savedlocale.c_str());
return 1;
};
int Configuration::LoadFile(std::string fn) {
JSONParse jp;
int i;
//
// save current language and set to default C
std::string savedlocale = setlocale(LC_ALL, NULL);
setlocale (LC_ALL, "C");
// read from file
if (jp.LoadFromFile(fn) != 0) {
fprintf (stderr, "Could not read json file '%s'. Error: %s\n", fn.c_str(), strerror(errno));
return 0; return 0;
} }
if (jp.GetValueInt("http_port", &i)) http_port = i;
if (jp.GetValueInt("https_port", &i)) https_port = i;
//
// restore language
setlocale (LC_ALL, savedlocale.c_str());
return 1;
}
int Configuration::LoadArgs(int argc, char **argv) { int Configuration::LoadArgs(int argc, char **argv) {
for (int i = 1; i < argc; i++) { for (int i = 1; i < argc; i++) {
if (strcmp(argv[i], "-F") == 0) runasdaemon = 0; if (strcmp(argv[i], "-F") == 0) runasdaemon = 0;
if (strcmp(argv[i], "-D") == 0) runasdaemon = 1; if (strcmp(argv[i], "-D") == 0) runasdaemon = 1;
if (strcmp(argv[i], "-dump_config") == 0) initflags |= CONF_INITFLAGS_PRINT; if (strcmp(argv[i], "-dump_config") == 0) initflags |= CONF_INITFLAGS_PRINT;
if (strcmp(argv[i], "-config") == 0) {
if (++i < argc) {
filename = argv[i];
}
else
ErrorExit("config file missing", -1);
}
if (strcmp(argv[i], "-h") == 0) initflags |= CONF_INITFLAGS_HELP; if (strcmp(argv[i], "-h") == 0) initflags |= CONF_INITFLAGS_HELP;
if (strcmp(argv[i], "-http_port") == 0) { if (strcmp(argv[i], "-http_port") == 0) {
if (++i < argc) { if (++i < argc) {
http_port = atoi(argv[i]);
} }
else else
ErrorExit("missing port parameter", -1); ErrorExit("missing port parameter", -1);
} }
if (strcmp(argv[i], "-https_port") == 0) {
if (++i < argc) {
https_port = atoi(argv[i]);
}
else
ErrorExit("missing port parameter", -1);
} }
return 0;
} }
return 1;
};
void Configuration::Help() { void Configuration::Help() {
printf ("Parameters:\n"); printf ("Parameters:\n");
printf (" -F run in foreground\n"); printf (" -F run in foreground\n");
printf (" -D run as daemon\n"); printf (" -D run as daemon\n");
printf ("\n"); printf ("\n");
printf (" -http_port INT port to listen for http connections\n");
printf (" -https_port INT port to listen for https connections\n");
printf ("\n");
printf (" -config FILE load this configfile\n");
printf (" -dump_config print the config file\n"); printf (" -dump_config print the config file\n");
printf ("\n"); printf ("\n");
printf (" -H print this help\n"); printf (" -H print this help\n");

@ -2,8 +2,11 @@
#ifndef _CONFIGURATION_H_ #ifndef _CONFIGURATION_H_
#define _CONFIGURATION_H_ #define _CONFIGURATION_H_
#include <string>
#define DEFAULT_HTTP_PORT 10080 #define DEFAULT_HTTP_PORT 10080
#define DEFAULT_HTTPS_PORT 10081 #define DEFAULT_HTTPS_PORT 10081
#define DEFAULT_CONFIG_FILE "/etc/miniwebcam.conf.json"
#define CONF_INITFLAGS_PRINT 0x0001 #define CONF_INITFLAGS_PRINT 0x0001
#define CONF_INITFLAGS_HELP 0x0002 #define CONF_INITFLAGS_HELP 0x0002
@ -13,18 +16,23 @@ private:
int http_port; int http_port;
int https_port; int https_port;
int runasdaemon; int runasdaemon;
std::string filename;
int initflags; int initflags;
public: public:
Configuration(); Configuration();
~Configuration(); ~Configuration();
int LoadArgs(int argc, char **argv); int LoadArgs(int argc, char **argv);
int Print(); // print current configuration int LoadFile(std::string fn);
void Help(); // print Help
int GetInitFlags() { return initflags; }; int GetInitFlags() { return initflags; };
std::string GetFilename() { return filename; };
int PrintConfig(); // print current configuration
void Help(); // print Help
//
}; };
extern Configuration config; extern Configuration config;

@ -0,0 +1,534 @@
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fstream>
#include <list>
#include <string>
#include "json.h"
/***********************************************************************
***********************************************************************
*
* JSONParse
*
***********************************************************************
***********************************************************************
*/
enum {
STEP_NONE = 0,
STEP_STARTNAME,
STEP_NAME,
STEP_STARTVALUE,
STEP_VALUE,
STEP_END
};
/*
* clear out all data
*/
void JSONParse::Clear() {
jsondata = "";
names.clear();
}
/*
* read every element and keep only this in memory.
*/
int JSONParse::Set(string json) {
int i;
int step;
int level;
bool ignorenext;
JSONElement jelement;
Clear();
// find start and read until end
for (step = STEP_NONE, i = 0, ignorenext = false; (unsigned int)i < json.length(); i++) {
// need to copy next character
if (ignorenext) {
ignorenext = false;
if (step == STEP_NAME) jelement.name += json[i];
if (step == STEP_VALUE) jelement.value += json[i];
}
// searching for startname
else if (step == STEP_NONE) {
if (json[i] == '{') {
step = STEP_STARTNAME;
continue;
}
}
// searching for startname
else if (step == STEP_STARTNAME) {
if (json[i] == '"') {
step = STEP_NAME;
continue;
}
}
// copy name
else if (step == STEP_NAME) {
if (json[i] == '"') {
step = STEP_STARTVALUE;
continue;
}
else {
jelement.name += json[i];
continue;
}
}
// searching for startvalue
else if (step == STEP_STARTVALUE) {
if (json[i] == '"') {
step = STEP_VALUE;
jelement.type = JSON_T_STRING;
continue;
}
if (json[i] == '{') {
step = STEP_VALUE;
level = 0;
jelement.type = JSON_T_OBJECT;
jelement.value = "{";
continue;
}
if (json[i] == '[') {
step = STEP_VALUE;
level = 0;
jelement.type = JSON_T_ARRAY;
jelement.value = "[";
continue;
}
if ((json[i] >= '0' && json[i] <= '9') ||
(json[i] == '+' || json[i] == '-')) {
step = STEP_VALUE;
level = 0;
jelement.type = JSON_T_NUMBER;
jelement.value = json[i];
continue;
}
}
// copy value
else if (step == STEP_VALUE) {
if (jelement.type == JSON_T_STRING) {
if (json[i] == '"') step = STEP_END;
else jelement.value += json[i];
continue;
}
else if (jelement.type == JSON_T_OBJECT) {
if (json[i] == '}' && level == 0) {
jelement.value += json[i];
step = STEP_END;
}
else {
if (json[i] == '{') level++; // increase level
if (json[i] == '}') level--; // decrease level
jelement.value += json[i];
}
continue;
}
else if (jelement.type == JSON_T_ARRAY) {
if (json[i] == ']' && level == 0) {
jelement.value += json[i];
step = STEP_END;
}
else {
if (json[i] == '[') level++; // increase level
if (json[i] == ']') level--; // decrease level
jelement.value += json[i];
}
continue;
}
else if (jelement.type == JSON_T_NUMBER) {
if ((json[i] < '0' || json[i] > '9') && json[i] != '.' &&
json[i] != '+' && json[i] != 'e' && json[i] != 'E') step = STEP_END;
else {
jelement.value += json[i];
continue;
}
}
}
// another element?
if (step == STEP_END) {
if (json[i] == ',') {
if (jelement.type != JSON_T_NONE) {
names.push_back (jelement);
}
jelement.Clear();
step = STEP_STARTNAME;
}
continue;
}
}
if (jelement.type != JSON_T_NONE) {
names.push_back (jelement);
}
return 0;
};
int JSONParse::GetValue(string varname, string *dest) {
list<JSONElement>::iterator iter;
if (dest == NULL) return 0;
*dest = "";
for (iter = names.begin(); iter != names.end(); iter++) {
if (varname.compare(iter->name) == 0) {
*dest = iter->value;
return 1;
}
}
return 0;
};
int JSONParse::GetValueInt(string varname, int *dest) {
string s;
int res = GetValue(varname, &s);
if (res) {
*dest = atoi (s.c_str());
return 1;
}
return 0;
};
int JSONParse::GetValueDouble(string varname, double *dest) {
string s;
int res = GetValue(varname, &s);
if (res) {
*dest = atof (s.c_str());
return 1;
}
return 0;
};
int JSONParse::GetValueInt64(string varname, int64_t *dest) {
string s;
int res = GetValue(varname, &s);
if (res) {
*dest = atol (s.c_str());
return 1;
}
return 0;
};
int JSONParse::GetObjectJson(string varname, JSONParse *dest) {
list<JSONElement>::iterator iter;
if (dest == NULL) return 0;
for (iter = names.begin(); iter != names.end(); iter++) {
if (varname.compare(iter->name) == 0) {
dest->Set(iter->value);
return 1;
}
}
return 0;
};
#define MAXRECURSIVE 255
int JSONParse::GetIdx(string src, int idx, string *dest) {
char recursive[MAXRECURSIVE];
int i = 0, rcnt = 0, cnt = 0;
(*dest) = "";
for (i = 0; i < MAXRECURSIVE; i++) recursive[i] = 0;
for (i = 0; (unsigned int) i < src.length() && rcnt < MAXRECURSIVE && cnt <= idx; i++) {
if (src[i] == '[') {
recursive[rcnt++] = src[i];
continue;
}
else if (src[i] == '{' && recursive[rcnt] != '"') recursive[++rcnt] = src[i];
else if (src[i] == '}' && recursive[rcnt] == '{') rcnt--;
else if (src[i] == '"' && recursive[rcnt] == '"') rcnt--;
else if (src[i] == '"') recursive[++rcnt] = src[i];
else if (src[i] == ',' && rcnt == 1) {
cnt++;
continue;
}
else if (src[i] == ']' && rcnt == 1) {
continue;
}
if (rcnt > 0 && cnt == idx) {
(*dest) += src[i];
if (src[i] == '\\') (*dest) += src[i];
}
else {
if (src[i] == '\\')i++;
}
}
//
// final checks
if (cnt == 0 && idx == 0 && // empty source/array?
dest->size() == 0) return 0; //
if (cnt >= idx) return 1; // found the right element
return 0; // element not found
}
#undef MAXRECURSIVE
int JSONParse::GetValueIdx(string varname, int idx, string *dest) {
list<JSONElement>::iterator iter;
if (dest == NULL) return 0;
for (iter = names.begin(); iter != names.end(); iter++) {
if (varname.compare(iter->name) == 0) {
return GetIdx(iter->value, idx, dest);
}
}
return 0;
};
int JSONParse::GetObjectIdx(string varname, int idx, JSONParse *dest) {
list<JSONElement>::iterator iter;
string deststr;
int ret = 0;
if (dest == NULL) return 0;
for (iter = names.begin(); iter != names.end(); iter++) {
if (varname.compare(iter->name) == 0) {
ret = GetIdx(iter->value, idx, &deststr);
if (ret == 1) dest->Set(deststr);
return ret;
}
}
return 0;
};
list<JSONElement> JSONParse::GetElements() {
list<JSONElement> l;
list<JSONElement>::iterator iter;
l.clear();
for (iter = names.begin(); iter != names.end(); iter++) {
l.push_back(*iter);
}
return l;
};
void JSONParse::AddObject (JSONElement element) {
names.push_back (element);
};
void JSONParse::AddObject (string name, JSONParse jp) {
JSONElement je;
je.SetObject(name, jp.ToString());
names.push_back(je);
};
void JSONParse::AddObject (string name, int val) {
JSONElement je;
je.Set(name, val);
names.push_back(je);
};
void JSONParse::AddObject (string name, int64_t val) {
JSONElement je;
je.Set(name, val);
names.push_back(je);
};
void JSONParse::AddObject (string name, string val) {
JSONElement je;
je.Set(name, val);
names.push_back(je);
};
void JSONParse::AddObject (string name, double val) {
JSONElement je;
je.Set(name, val);
names.push_back(je);
};
string JSONParse::ToString() {
list<JSONElement>::iterator iter;
string output;
int level, i;
output = "{";
for (level = 1, iter = names.begin(); iter != names.end(); iter++) {
if (iter != names.begin()) output += ",";
output += "\n";
for (i = 0; i < 4*level; i++) output += " ";
output += iter->GetString();
}
output += "\n}\n";
return output;
};
/*
* Load/Save elements to a file.
* Return Value: -1 .. on Error, errno will be set
* 0 .. on Success
*/
int JSONParse::LoadFromFile(string filename) {
int fd;
struct stat fs;
char *buffer;
if (stat(filename.c_str(), &fs) != 0) return -1;
buffer = (char *) malloc (fs.st_size+1);
memset (buffer, 0x0, fs.st_size+1);
fd = open(filename.c_str(), O_RDONLY);
if (fd < 0) return -1;
read (fd, buffer, fs.st_size);
close (fd);
Set(buffer);
free (buffer);
return 0;
};
int JSONParse::SaveToFile(string filename) {
ofstream out(filename);
if (!out) return -1;
out << ToString();
out.close();
return 0;
};
/***********************************************************************
***********************************************************************
*
* JSONElement
*
***********************************************************************
***********************************************************************
*/
void JSONElement::Set (string n, double v) {
name = n;
value = to_string(v);
type = JSON_T_NUMBER;
};
void JSONElement::Set (string n, int v) {
name = n;
value = to_string(v);
type = JSON_T_NUMBER;
};
void JSONElement::Set (string n, int64_t v) {
name = n;
value = to_string(v);
type = JSON_T_NUMBER;
};
void JSONElement::Set (string n, string v) {
name = n;
value = v;
type = JSON_T_STRING;
};
void JSONElement::SetArray (string n, list<JSONElement> *l) {
list<JSONElement>::iterator iter;
name = n;
value = "[";
type = JSON_T_STRING;
for (iter = l->begin(); iter != l->end(); iter++) {
if (iter != l->begin()) value += ",";
value += iter->GetString();
}
value += "]";
};
void JSONElement::SetObject (string n, string s) {
name = n;
value = s;
type = JSON_T_OBJECT;
};
string JSONElement::GetString () {
string output = "";
string filename = __FILE__;
switch (type) {
case(JSON_T_NUMBER):
output += "\"" + name + "\" : " + value;
break;
case(JSON_T_STRING):
if (value.length()==0) {
output += "\"" + name + "\" : \"\"";
}
else if (value[0] != '"') {
output += "\"" + name + "\" : \"" + value + "\"";
}
else output += "\"" + name + "\" : " + value;
break;
case(JSON_T_OBJECT):
output += "\"" + name + "\" : " + value;
break;
case(JSON_T_ARRAY):
if (value.length()==0) {
output += "\"" + name + "\" : []";
}
else if (value[0] != '[') {
output += "\"" + name + "\" : [" + value + "]";
}
else output += "\"" + name + "\" : " + value;
break;
default:
output += "\"error\" : \""+ filename + ":" + to_string(__LINE__) + " JSONElement unknown type error\"("+to_string(type)+")";
break;
}
return output;
};

@ -0,0 +1,80 @@
//
//
//
#ifndef _JSON_H_
#define _JSON_H_
#include <list>
#include <string>
#include <string.h>
using namespace std;
enum {
JSON_T_NONE,
JSON_T_STRING,
JSON_T_NUMBER,
JSON_T_OBJECT,
JSON_T_ARRAY
};
class JSONElement {
public:
int type;
string name;
string value;
JSONElement() { Clear(); };
~JSONElement() {};
void Clear() { type = JSON_T_NONE; name = ""; value = ""; };
void Set (string n, double v);
void Set (string n, int v);
void Set (string n, int64_t v);
void Set (string n, string v);
void SetArray (string n, list<JSONElement> *l);
void SetObject (string n, string s);
string GetString();
};
class JSONParse {
private:
string jsondata;
list<JSONElement> names;
public:
JSONParse() { Set("{}"); };
JSONParse(string json) { Set(json); };
~JSONParse() {};
void Clear();
int Set(string json);
int GetValue(string varname, string *dest);
int GetValueInt(string varname, int *dest);
int GetValueDouble(string varname, double *dest);
int GetValueInt64(string varname, int64_t *dest);
int GetObjectJson(string varname, JSONParse *dest);
int GetIdx(string src, int idx, string *dest);
int GetValueIdx(string varname, int idx, string *dest);
int GetObjectIdx(string varname, int idx, JSONParse *dest);
list<JSONElement> GetElements();
void AddObject (JSONElement element);
void AddObject (string name, int val);
void AddObject (string name, int64_t val);
void AddObject (string name, string val);
void AddObject (string name, double val);
void AddObject (string name, JSONParse jp);
int LoadFromFile(string filename);
int SaveToFile(string filename);
string ToString();
};
#endif // _JSON_H_

@ -1,7 +1,9 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string> #include <string>
#include "configuration.h" #include "configuration.h"
#include "miniwebcam.h" #include "miniwebcam.h"
@ -12,8 +14,9 @@ void ErrorExit(std::string text, int errorcode) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
config.LoadArgs (argc, argv); config.LoadArgs (argc, argv);
config.LoadFile (config.GetFilename());
if (config.GetInitFlags() & CONF_INITFLAGS_PRINT) { if (config.GetInitFlags() & CONF_INITFLAGS_PRINT) {
config.Print(); config.PrintConfig();
return 0; return 0;
} }

@ -6,12 +6,14 @@ project('miniwebcam', 'cpp', default_options: [
miniwebcam_src = [ miniwebcam_src = [
'main.cc', 'main.cc',
'configuration.cc', 'configuration.cc',
'webserver.cc' 'webserver.cc',
'json.cc'
] ]
miniwebcam_headers = [ miniwebcam_headers = [
'configuration.h', 'configuration.h',
'miniwebcam.h' 'miniwebcam.h',
'json.h'
] ]

Loading…
Cancel
Save