/* * Copyright (c) 2018 Markus Hennecke * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include #include #include #include #include #include #include "../db.h" #include "../util.h" enum key { KEY_TEMP, KEY_HUMIDITY, KEY_PRESSURE, KEY_BATTERY, KEY_DEVICE, KEY_TIMESTAMP, KEY_ERRORMSG, KEY__MAX }; static const struct kvalid keys[KEY__MAX] = { { kvalid_double, "temp" }, { kvalid_double, "humidity" }, { kvalid_double, "pressure" }, { kvalid_double, "battery" }, { validate_device, "device" }, { validate_timestamp, "timestamp" }, { kvalid_string, "errormsg" }, }; enum pg { PG_DATA, PG_ERROR, PG__MAX }; static const char *pages[PG__MAX] = { "data", "error", }; int main(void) { struct kreq r; enum kcgi_err er; if ((pledge("cpath getpw stdio proc wpath rpath dns inet", NULL)) == (-1)) err(EXIT_FAILURE, "pledge"); er = khttp_parse(&r, keys, KEY__MAX, pages, PG__MAX, PG_DATA); if (KCGI_OK != er) return EXIT_FAILURE; /* * Accept POST and GET... */ if (KMETHOD_OPTIONS == r.method) { khttp_head(&r, kresps[KRESP_ALLOW], "OPTIONS POST GET"); response(&r, KHTTP_200, r.mime, NULL); } else if ((KMETHOD_POST == r.method) || (KMETHOD_GET == r.method)) { switch (r.page) { case PG_DATA: { const char *temp = parameter(&r, KEY_TEMP); const char *humidity = parameter(&r, KEY_HUMIDITY); const char *pressure = parameter(&r, KEY_PRESSURE); const char *battery = parameter(&r, KEY_BATTERY); if (db_add_data(&r, temp, humidity, pressure, battery)) response(&r, KHTTP_200, KMIME_TEXT_PLAIN, "1 success"); else response(&r, KHTTP_503, KMIME_TEXT_PLAIN, "0 internal error"); break; } case PG_ERROR: { const char *device = parameter(&r, KEY_DEVICE); const char *timestamp = parameter(&r, KEY_TIMESTAMP); const char *errormsg = parameter(&r, KEY_ERRORMSG); if (db_add_error(&r, device, timestamp, errormsg)) response(&r, KHTTP_200, KMIME_TEXT_PLAIN, "1 success"); else response(&r, KHTTP_503, KMIME_TEXT_PLAIN, "0 internal error"); } break; default: break; } } else response(&r, KHTTP_404, r.mime, "0 page not found"); khttp_free(&r); return EXIT_SUCCESS; }