#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <ctype.h>
#include "common.h"
#include "sensor.h"
FCGI_BeginJSON(context, STATUS_OK);
FCGI_JSONPair("description", "MCTX3420 Server API (2013)");
FCGI_JSONPair("build_date", __DATE__ " " __TIME__);
- struct timespec t;
- t.tv_sec = 0; t.tv_nsec = 0;
+ struct timespec t = {0};
clock_getres(CLOCK_MONOTONIC, &t);
FCGI_JSONDouble("clock_getres", TIMEVAL_TO_DOUBLE(t));
FCGI_JSONLong("api_version", API_VERSION);
if (i > 0) {
FCGI_JSONValue(",\n\t\t");
}
- FCGI_JSONValue("\"%d\" : \"%s\"", i, Sensor_GetName(i));
+ DataPoint d = Sensor_LastData(i);
+ FCGI_JSONValue("\"%d\" : {\"name\" : \"%s\", \"value\" : [%f,%f] }",
+ i, Sensor_GetName(i), d.time_stamp, d.value);
}
FCGI_JSONValue("\n\t}");
}
if (i > 0) {
FCGI_JSONValue(",\n\t\t");
}
- FCGI_JSONValue("\"%d\" : \"%s\"", i, Actuator_GetName(i));
+
+ DataPoint d = Actuator_LastData(i);
+ FCGI_JSONValue("\"%d\" : {\"name\" : \"%s\", \"value\" : [%f, %f] }", i, Actuator_GetName(i), d.time_stamp, d.value);
}
FCGI_JSONValue("\n\t}");
}
return buf;
}
+/**
+ * Unescapes a URL encoded string in-place. The string
+ * must be NULL terminated.
+ * (e.g this%2d+string --> this- string)
+ * @param buf The buffer to decode. Will be modified in-place.
+ * @return The same buffer.
+ */
+char *FCGI_URLDecode(char *buf)
+{
+ char *head = buf, *tail = buf;
+ char val, hex[3] = {0};
+
+ while (*tail) {
+ if (*tail == '%') { //%hh hex to char
+ tail++;
+ if (isxdigit(*tail) && isxdigit(*(tail+1))) {
+ hex[0] = *tail++;
+ hex[1] = *tail++;
+ char val = (char)strtol(hex, NULL, 16);
+ //Control codes --> Space character
+ *head++ = (val < 0x20) ? 0x20 : val;
+ } else { //Not valid format; keep original
+ head++;
+ }
+ } else if (*tail == '+') { //Plus to space
+ tail++;
+ *head++ = ' ';
+ } else { //Anything else
+ *head++ = *tail++;
+ }
+ }
+ *head = 0; //NULL-terminate at new end point
+
+ return buf;
+}
+
/**
* Main FCGI request loop that receives/responds to client requests.
* @param data Reserved.
//strncpy doesn't zero-truncate properly
snprintf(module, BUFSIZ, "%s", getenv("DOCUMENT_URI_LOCAL"));
+
+ //Get the GET query string
snprintf(params, BUFSIZ, "%s", getenv("QUERY_STRING"));
+ //URL decode the parameters
+ FCGI_URLDecode(params);
FCGI_GetControlCookie(context.received_key);
Log(LOGDEBUG, "Got request #%d - Module %s, params %s", context.response_number, module, params);
context.current_module = module;
context.response_number++;
- if (module_handler)
- {
- if (module_handler != Login_Handler && module_handler != IdentifyHandler && module_handler)
- //if (false) // Testing
- {
+ if (module_handler) {
+ if (module_handler == IdentifyHandler) {
+ FCGI_EscapeText(params);
+ } else if (module_handler != Login_Handler) {
if (!FCGI_HasControl(&context))
{
- FCGI_RejectJSON(&context, "Please login. Invalid control key.");
- continue;
+ if (g_options.auth_method == AUTH_NONE) { //:(
+ Log(LOGWARN, "Locking control (no auth!)");
+ FCGI_LockControl(&context, NOAUTH_USERNAME, USER_ADMIN);
+ FCGI_SendControlCookie(&context, true);
+ }
+ else {
+ FCGI_RejectJSON(&context, "Please login. Invalid control key.");
+ continue;
+ }
}
-
+
//Escape all special characters.
//Don't escape for login (password may have special chars?)
FCGI_EscapeText(params);
+ } else { //Only for Login handler.
+ //If GET data is empty, use POST instead.
+ if (*params == '\0') {
+ Log(LOGDEBUG, "Using POST!");
+ fgets(params, BUFSIZ, stdin);
+ FCGI_URLDecode(params);
+ }
}
module_handler(&context, params);
}
- else
- {
+ else {
FCGI_RejectJSON(&context, "Unhandled module");
}
}