From ec745f5cc938707733da83a9797c2c30b75db6b5 Mon Sep 17 00:00:00 2001 From: Martin Preuss Date: Thu, 10 Aug 2023 18:03:24 +0200 Subject: [PATCH] Improved code sharing. we now have a base url handler which handles listing, adding and editing any objects including permission management. --- apps/aqhome-storage/0BUILD | 5 + apps/aqhome-storage/u_base.c | 71 ++++ apps/aqhome-storage/u_base.h | 27 ++ apps/aqhome-storage/u_objects.c | 458 +++++++++++++++++++++++ apps/aqhome-storage/u_objects.h | 45 +++ apps/aqhome-storage/u_objects_p.h | 37 ++ apps/aqhome-storage/u_rooms.c | 585 +++++++++--------------------- 7 files changed, 805 insertions(+), 423 deletions(-) create mode 100644 apps/aqhome-storage/u_base.c create mode 100644 apps/aqhome-storage/u_base.h create mode 100644 apps/aqhome-storage/u_objects.c create mode 100644 apps/aqhome-storage/u_objects.h create mode 100644 apps/aqhome-storage/u_objects_p.h diff --git a/apps/aqhome-storage/0BUILD b/apps/aqhome-storage/0BUILD index 4dc0482..995a96d 100644 --- a/apps/aqhome-storage/0BUILD +++ b/apps/aqhome-storage/0BUILD @@ -43,7 +43,10 @@ loop.h loop_http.h cleanup.h + u_base.h u_login.h + u_objects.h + u_objects_p.h u_rooms.h u_static.h u_static_p.h @@ -61,7 +64,9 @@ loop.c loop_http.c cleanup.c + u_base.c u_login.c + u_objects.c u_rooms.c u_static.c main.c diff --git a/apps/aqhome-storage/u_base.c b/apps/aqhome-storage/u_base.c new file mode 100644 index 0000000..c28d387 --- /dev/null +++ b/apps/aqhome-storage/u_base.c @@ -0,0 +1,71 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + + +#include "./u_base.h" +#include "./aqhomehttp.h" +#include "aqhome/http/httpservice_http.h" + +#include +#include + + + + + +/* ------------------------------------------------------------------------------------------------ + * defines + * ------------------------------------------------------------------------------------------------ + */ + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + + + +GWEN_MSG *AQH_BaseHttpUrlHandler_CreateResponseForErrorCode(AQH_HTTP_URLHANDLER *uh, + AQH_HTTP_REQUEST *rq, + int rv, + AQH_HTTP_URLHANDLER_WRITEPAGE_CB cb, + GWEN_DB_NODE *db) +{ + if (rv<0) { + switch(rv) { + case GWEN_ERROR_INVALID: + return AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Missing fields"), 1, db, cb); + case GWEN_ERROR_FOUND: + return AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Object already exists"), 1, db, cb); + case GWEN_ERROR_NOT_FOUND: + return AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Object not found"), 1, db, cb); + case GWEN_ERROR_IO: + case GWEN_ERROR_INTERNAL: + default: + return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), + 500, "Internal error", + AQH_HttpRequest_GetProtocol(rq), NULL); + } + } + return NULL; +} + + diff --git a/apps/aqhome-storage/u_base.h b/apps/aqhome-storage/u_base.h new file mode 100644 index 0000000..f4dbe66 --- /dev/null +++ b/apps/aqhome-storage/u_base.h @@ -0,0 +1,27 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQHOME_STORAGE_U_BASE_H +#define AQHOME_STORAGE_U_BASE_H + + +#include "aqhome/http/urlhandler.h" + + + +GWEN_MSG *AQH_BaseHttpUrlHandler_CreateResponseForErrorCode(AQH_HTTP_URLHANDLER *uh, + AQH_HTTP_REQUEST *rq, + int rv, + AQH_HTTP_URLHANDLER_WRITEPAGE_CB cb, + GWEN_DB_NODE *db); + + + +#endif + + diff --git a/apps/aqhome-storage/u_objects.c b/apps/aqhome-storage/u_objects.c new file mode 100644 index 0000000..b8f5221 --- /dev/null +++ b/apps/aqhome-storage/u_objects.c @@ -0,0 +1,458 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifdef HAVE_CONFIG_H +# include +#endif + + +#include "./u_objects_p.h" +#include "./u_base.h" +#include "./aqhomehttp.h" +#include "aqhome/http/httpservice_http.h" + +#include +#include +#include + + +GWEN_INHERIT(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS); + + + +/* ------------------------------------------------------------------------------------------------ + * forward declarations + * ------------------------------------------------------------------------------------------------ + */ + +static void GWENHYWFAR_CB _freeData(void *bp, void *p); +static int _handleUrl(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); +static GWEN_MSG *_handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); +static GWEN_MSG *_handlePost(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); + +static void _handleGetList(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf); + +static void _handleGetAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf); +static void _handleGetEdit(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id, GWEN_BUFFER *pageBuf); +static GWEN_MSG *_handlePostAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); +static GWEN_MSG *_handlePostEdit(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id); +static int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); +static int _writeEditPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); +static GWEN_MSG *_addOrEditAndCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id, AQH_HTTP_URLHANDLER_WRITEPAGE_CB cb); +static int _addOrEditObject(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *db, int id); +static GWEN_DB_NODE *_findObjectByIdAndReturnAsDb(AQH_HTTP_URLHANDLER *uh, int id); +static void _listObjectsIntoBuffer(AQH_HTTP_URLHANDLER *uh, GWEN_BUFFER *pageBuf); + + + +/* ------------------------------------------------------------------------------------------------ + * implementations + * ------------------------------------------------------------------------------------------------ + */ + +AQH_HTTP_URLHANDLER *AQH_ObjectsHttpUrlHandler_new(AQH_SERVICE *sv, + uint32_t neededPermsList, + uint32_t neededPermsAdd, + uint32_t neededPermsDel, + uint32_t neededPermsEdit, + const char *urlForObjectList) +{ + AQH_HTTP_URLHANDLER *uh; + AQH_URLHANDLER_OBJECTS *xuh; + + uh=AQH_HttpUrlHandler_new(sv); + GWEN_NEW_OBJECT(AQH_URLHANDLER_OBJECTS, xuh); + GWEN_INHERIT_SETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh, xuh, _freeData); + + AQH_HttpUrlHandler_SetHandleFn(uh, _handleUrl); + + xuh->neededPermsList=neededPermsList; + xuh->neededPermsAdd=neededPermsAdd; + xuh->neededPermsDel=neededPermsDel; + xuh->neededPermsEdit=neededPermsEdit; + xuh->urlForObjectList=urlForObjectList?strdup(urlForObjectList):NULL; + + return uh; +} + + + +void _freeData(void *bp, void *p) +{ + AQH_URLHANDLER_OBJECTS *xuh; + + xuh=(AQH_URLHANDLER_OBJECTS*)p; + free(xuh->urlForObjectList); + GWEN_FREE_OBJECT(xuh); +} + + + +void AQH_ObjectsHttpUrlHandler_SetAddOrEditObjectFn(AQH_HTTP_URLHANDLER *uh, AQH_OBJECTSHTTPURLHANDLER_ADDOREDITOBJECT_FN fn) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + + if (xuh) { + xuh->addOrEditObjectFn=fn; + } +} + + + +void AQH_ObjectsHttpUrlHandler_SetFindObjectByIdAndReturnAsDbFn(AQH_HTTP_URLHANDLER *uh, + AQH_OBJECTSHTTPURLHANDLER_FINDOBJECTBYIDANDRETURNASDB_FN fn) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + + if (xuh) { + xuh->findObjectByIdAndReturnAsDbFn=fn; + } +} + + + +void AQH_ObjectsHttpUrlHandler_SetWriteAddPageFn(AQH_HTTP_URLHANDLER *uh, AQH_OBJECTSHTTPURLHANDLER_WRITEADDPAGE_FN fn) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + + if (xuh) { + xuh->writeAddPageFn=fn; + } +} + + + +void AQH_ObjectsHttpUrlHandler_SetWriteEditPageFn(AQH_HTTP_URLHANDLER *uh, AQH_OBJECTSHTTPURLHANDLER_WRITEEDITPAGE_FN fn) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + + if (xuh) { + xuh->writeEditPageFn=fn; + } +} + + + +void AQH_ObjectsHttpUrlHandler_SetListObjectsIntoBufferFn(AQH_HTTP_URLHANDLER *uh, + AQH_OBJECTSHTTPURLHANDLER_LISTOBJECTSINTOBUFFER_FN fn) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + + if (xuh) { + xuh->listObjectsIntoBufferFn=fn; + } +} + + + + +int _handleUrl(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) +{ + if (GWEN_INHERIT_ISOFTYPE(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh)) { + const char *protocol; + const char *cmd; + GWEN_MSG *msgOut; + + AQH_HttpService_SetupModuleAndPerms(AQH_HttpUrlHandler_GetHttpService(uh), rq, "aqhome"); + protocol=AQH_HttpRequest_GetProtocol(rq); + + AQH_HttpRequest_SetupUrlPathMembers(rq); + if (AQH_HttpRequest_GetUrlPathMembers(rq)==NULL) { + msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL); + AQH_HttpRequest_SetResponseMsg(rq, msgOut); + return 0; + } + + cmd=AQH_HttpRequest_GetCommand(rq); + if (cmd && *cmd) { + if (strcasecmp(cmd, "GET")==0) + msgOut=_handleGet(uh, rq); + else if (strcasecmp(cmd, "POST")==0) + msgOut=_handlePost(uh, rq); + else { + msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 405, "Method not allowed", protocol, NULL); + } + AQH_HttpRequest_SetResponseMsg(rq, msgOut); + return 0; + } + else { + DBG_ERROR(AQH_LOGDOMAIN, "No command in request"); + return GWEN_ERROR_INVALID; + } + } + else { + DBG_ERROR(NULL, "Not an AQH_URLHANDLER_OBJECTS object"); + return GWEN_ERROR_INTERNAL; + } +} + + + +GWEN_MSG *_handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) +{ + GWEN_BUFFER *pageBuf; + int rv; + GWEN_MSG *msgOut=NULL; + const char *protocol; + const GWEN_STRINGLIST *sl; + const char *s; + + protocol=AQH_HttpRequest_GetProtocol(rq); + pageBuf=GWEN_Buffer_new(0, 256, 0, 1); + /* header */ + rv=AQH_HttpUrlHandler_AddContentHeaders(uh, AQH_HTTP_CONTENT_MODE_DESKTOP, pageBuf); + if (rv<0) { + DBG_ERROR(AQH_LOGDOMAIN, "Error adding headers"); + GWEN_Buffer_free(pageBuf); + return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL); + } + + /* middle part (header - middle - footer) */ + sl=AQH_HttpRequest_GetUrlPathMembers(rq); + + s=GWEN_StringList_StringAt(sl, 1); + if (!(s && *s)) + s="list"; + + if (strcasecmp(s, "list")==0) + _handleGetList(uh, rq, pageBuf); + else if (strcasecmp(s, "add")==0) + _handleGetAdd(uh, rq, pageBuf); + else if (strcasecmp(s, "edit")==0) + _handleGetEdit(uh, rq, GWEN_StringList_StringAsIntAt(sl, 2, 0), pageBuf); + else { + DBG_ERROR(NULL, "Invalid url (2nd member is [%s])", s); + GWEN_Buffer_free(pageBuf); + return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL); + } + + /* footer */ + rv=AQH_HttpUrlHandler_AddContentFooters(uh, AQH_HTTP_CONTENT_MODE_DESKTOP, pageBuf); + if (rv<0) { + DBG_ERROR(AQH_LOGDOMAIN, "Error adding footers"); + GWEN_Buffer_free(pageBuf); + return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL); + } + + msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 200, "OK", protocol, GWEN_Buffer_GetStart(pageBuf)); + GWEN_Buffer_free(pageBuf); + return msgOut; +} + + + +GWEN_MSG *_handlePost(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) +{ + GWEN_DB_NODE *db; + const GWEN_STRINGLIST *sl; + const char *protocol; + const char *s; + + DBG_ERROR(NULL, "POST:"); + db=AQH_HttpRequest_GetDbPostBody(rq); + GWEN_DB_Dump(db, 2); + + protocol=AQH_HttpRequest_GetProtocol(rq); + sl=AQH_HttpRequest_GetUrlPathMembers(rq); + + s=GWEN_StringList_StringAt(sl, 1); + if (s && *s) { + if (strcasecmp(s, "add")==0) + return _handlePostAdd(uh, rq); + else if (strcasecmp(s, "edit")==0) + return _handlePostEdit(uh, rq, GWEN_StringList_StringAsIntAt(sl, 2, 0)); + else { + DBG_ERROR(NULL, "Invalid url (2nd member is [%s])", s); + return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL); + } + } + else { + DBG_ERROR(NULL, "Invalid url (2nd member missing)"); + return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL); + } +} + + + +void _handleGetList(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + uint32_t perms; + + DBG_ERROR(NULL, "LIST"); + perms=AQH_HttpRequest_GetModulePerms(rq); + if (perms & xuh->neededPermsList) { + _listObjectsIntoBuffer(uh, pageBuf); + } + else { + GWEN_Buffer_AppendArgs(pageBuf, "

%s

", I18N("No permissions to see list of objects.")); + } +} + + + +void _handleGetAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + uint32_t perms; + + DBG_ERROR(NULL, "ADD"); + perms=AQH_HttpRequest_GetModulePerms(rq); + if (perms & xuh->neededPermsAdd) { + _writeAddPage(uh, rq, NULL, pageBuf); + } + else { + DBG_INFO(NULL, "No permissions to add."); + GWEN_Buffer_AppendArgs(pageBuf, "

%s

", I18N("No permissions to add an object.")); + } +} + + + +void _handleGetEdit(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id, GWEN_BUFFER *pageBuf) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + uint32_t perms; + + DBG_ERROR(NULL, "EDIT"); + perms=AQH_HttpRequest_GetModulePerms(rq); + if (perms & xuh->neededPermsEdit) { + if (id>0) { + GWEN_DB_NODE *db; + + db=_findObjectByIdAndReturnAsDb(uh, id); + if (db) { + _writeEditPage(uh, rq, db, pageBuf); + GWEN_DB_Group_free(db); + } + else { + DBG_ERROR(NULL, "Object %d not found", id); + GWEN_Buffer_AppendArgs(pageBuf, "

%s

", I18N("Object not found.")); + } + } + else { + DBG_ERROR(NULL, "Missing object id"); + GWEN_Buffer_AppendArgs(pageBuf, "

%s

", I18N("Missing or invalid object id.")); + } + } + else { + DBG_INFO(NULL, "No permissions to edit."); + GWEN_Buffer_AppendArgs(pageBuf, "

%s

", I18N("No permissions to edit.")); + } +} + + + +GWEN_MSG *_handlePostAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + uint32_t perms; + + perms=AQH_HttpRequest_GetModulePerms(rq); + if (perms & xuh->neededPermsAdd) + return _addOrEditAndCreateResponse(uh, rq, 0, _writeAddPage); + else { + DBG_INFO(NULL, "No perms to add object"); + return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 403, "Forbidden", + AQH_HttpRequest_GetProtocol(rq), NULL); + } +} + + + +GWEN_MSG *_handlePostEdit(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + uint32_t perms; + + perms=AQH_HttpRequest_GetModulePerms(rq); + if (perms & xuh->neededPermsEdit) { + return _addOrEditAndCreateResponse(uh, rq, id, _writeEditPage); + } + else { + DBG_INFO(NULL, "No perms to edit"); + return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 403, "Forbidden", + AQH_HttpRequest_GetProtocol(rq), NULL); + } +} + + + +GWEN_MSG *_addOrEditAndCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id, AQH_HTTP_URLHANDLER_WRITEPAGE_CB cb) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + AQH_SERVICE *sv; + GWEN_DB_NODE *db; + int rv; + + sv=AQH_HttpUrlHandler_GetHttpService(uh); + db=AQH_HttpRequest_GetDbPostBody(rq); + rv=_addOrEditObject(uh, db, id); + if (rv<0) + return AQH_BaseHttpUrlHandler_CreateResponseForErrorCode(uh, rq, rv, cb, db); + return AQH_HttpService_CreateRedirectingResponseMsg(sv, AQH_HttpRequest_GetProtocol(rq), xuh->urlForObjectList); +} + + + +int _addOrEditObject(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *db, int id) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + + if (xuh->addOrEditObjectFn) + return xuh->addOrEditObjectFn(uh, db, id); + return GWEN_ERROR_NOT_IMPLEMENTED; +} + + + +GWEN_DB_NODE *_findObjectByIdAndReturnAsDb(AQH_HTTP_URLHANDLER *uh, int id) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + + if (xuh->findObjectByIdAndReturnAsDbFn) + return xuh->findObjectByIdAndReturnAsDbFn(uh, id); + return NULL; +} + + + +int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + + if (xuh->writeAddPageFn) + return xuh->writeAddPageFn(uh, rq, dbValues, pageBuf); + return GWEN_ERROR_NOT_IMPLEMENTED; +} + + + +int _writeEditPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + + if (xuh->writeEditPageFn) + return xuh->writeEditPageFn(uh, rq, dbValues, pageBuf); + return GWEN_ERROR_NOT_IMPLEMENTED; +} + + + +void _listObjectsIntoBuffer(AQH_HTTP_URLHANDLER *uh, GWEN_BUFFER *pageBuf) +{ + AQH_URLHANDLER_OBJECTS *xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_OBJECTS, uh); + + if (xuh->listObjectsIntoBufferFn) + xuh->listObjectsIntoBufferFn(uh, pageBuf); +} + + + + + diff --git a/apps/aqhome-storage/u_objects.h b/apps/aqhome-storage/u_objects.h new file mode 100644 index 0000000..7dc70f1 --- /dev/null +++ b/apps/aqhome-storage/u_objects.h @@ -0,0 +1,45 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQHOME_STORAGE_U_OBJECTS_H +#define AQHOME_STORAGE_U_OBJECTS_H + + +#include "aqhome/http/urlhandler.h" + + + +AQH_HTTP_URLHANDLER *AQH_ObjectsHttpUrlHandler_new(AQH_SERVICE *sv, + uint32_t neededPermsList, + uint32_t neededPermsAdd, + uint32_t neededPermsDel, + uint32_t neededPermsEdit, + const char *urlForObjectList); + + +typedef int (*AQH_OBJECTSHTTPURLHANDLER_ADDOREDITOBJECT_FN)(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *db, int id); +typedef GWEN_DB_NODE* (*AQH_OBJECTSHTTPURLHANDLER_FINDOBJECTBYIDANDRETURNASDB_FN)(AQH_HTTP_URLHANDLER *uh, int id); +typedef int (*AQH_OBJECTSHTTPURLHANDLER_WRITEADDPAGE_FN)(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, + GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); +typedef int (*AQH_OBJECTSHTTPURLHANDLER_WRITEEDITPAGE_FN)(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, + GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); +typedef void (*AQH_OBJECTSHTTPURLHANDLER_LISTOBJECTSINTOBUFFER_FN)(AQH_HTTP_URLHANDLER *uh, GWEN_BUFFER *pageBuf); + + +void AQH_ObjectsHttpUrlHandler_SetAddOrEditObjectFn(AQH_HTTP_URLHANDLER *uh, AQH_OBJECTSHTTPURLHANDLER_ADDOREDITOBJECT_FN fn); +void AQH_ObjectsHttpUrlHandler_SetFindObjectByIdAndReturnAsDbFn(AQH_HTTP_URLHANDLER *uh, + AQH_OBJECTSHTTPURLHANDLER_FINDOBJECTBYIDANDRETURNASDB_FN fn); +void AQH_ObjectsHttpUrlHandler_SetWriteAddPageFn(AQH_HTTP_URLHANDLER *uh, AQH_OBJECTSHTTPURLHANDLER_WRITEADDPAGE_FN fn); +void AQH_ObjectsHttpUrlHandler_SetWriteEditPageFn(AQH_HTTP_URLHANDLER *uh, AQH_OBJECTSHTTPURLHANDLER_WRITEEDITPAGE_FN fn); +void AQH_ObjectsHttpUrlHandler_SetListObjectsIntoBufferFn(AQH_HTTP_URLHANDLER *uh, + AQH_OBJECTSHTTPURLHANDLER_LISTOBJECTSINTOBUFFER_FN fn); + + +#endif + + diff --git a/apps/aqhome-storage/u_objects_p.h b/apps/aqhome-storage/u_objects_p.h new file mode 100644 index 0000000..23c92c8 --- /dev/null +++ b/apps/aqhome-storage/u_objects_p.h @@ -0,0 +1,37 @@ +/**************************************************************************** + * This file is part of the project AqHome. + * AqHome (c) by 2023 Martin Preuss, all rights reserved. + * + * The license for this file can be found in the file COPYING which you + * should have received along with this file. + ****************************************************************************/ + +#ifndef AQHOME_STORAGE_U_OBJECTS_P_H +#define AQHOME_STORAGE_U_OBJECTS_P_H + + +#include "./u_objects.h" + +#include + + +typedef struct AQH_URLHANDLER_OBJECTS AQH_URLHANDLER_OBJECTS; +struct AQH_URLHANDLER_OBJECTS { + uint32_t neededPermsList; + uint32_t neededPermsAdd; + uint32_t neededPermsDel; + uint32_t neededPermsEdit; /* e.g. AQHOME_HTTP_PERMS_EDIT_ROOM */ + + char *urlForObjectList; + + AQH_OBJECTSHTTPURLHANDLER_ADDOREDITOBJECT_FN addOrEditObjectFn; + AQH_OBJECTSHTTPURLHANDLER_FINDOBJECTBYIDANDRETURNASDB_FN findObjectByIdAndReturnAsDbFn; + AQH_OBJECTSHTTPURLHANDLER_WRITEADDPAGE_FN writeAddPageFn; + AQH_OBJECTSHTTPURLHANDLER_WRITEEDITPAGE_FN writeEditPageFn; + AQH_OBJECTSHTTPURLHANDLER_LISTOBJECTSINTOBUFFER_FN listObjectsIntoBufferFn; +}; + + +#endif + + diff --git a/apps/aqhome-storage/u_rooms.c b/apps/aqhome-storage/u_rooms.c index 8c125ae..499a439 100644 --- a/apps/aqhome-storage/u_rooms.c +++ b/apps/aqhome-storage/u_rooms.c @@ -12,10 +12,8 @@ #include "./u_rooms.h" +#include "./u_objects.h" #include "./aqhomehttp.h" -#include "aqhome/http/httpservice.h" -#include "aqhome/http/httpservice_http.h" -#include "aqhome/http/httpservice_conf.h" #include #include @@ -35,20 +33,14 @@ * ------------------------------------------------------------------------------------------------ */ -static int _handleUrl(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); -static GWEN_MSG *_handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); -static GWEN_MSG *_handlePost(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); - -static void _handleGetList(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf); - -static void _handleGetAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf); -static void _handleGetEdit(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id, GWEN_BUFFER *pageBuf); -static GWEN_MSG *_handlePostAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq); -static GWEN_MSG *_handlePostEdit(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id); +static int _addOrEditObject(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *db, int id); +static GWEN_DB_NODE *_findObjectByIdAndReturnAsDb(AQH_HTTP_URLHANDLER *uh, int id); static int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); static int _writeEditPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); -static GWEN_MSG *_addOrEditAndCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id); -static int _addOrEditRoom(AQH_HTTP_URLHANDLER *uh, const AQH_ROOM *newRoom, int id); +static void _listObjectsIntoBuffer(AQH_HTTP_URLHANDLER *uh, GWEN_BUFFER *pageBuf); + +static void _writeEditingTable(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf); +static void _setFromObject(AQH_ROOM *r, const AQH_ROOM *srcRoom); @@ -61,453 +53,83 @@ AQH_HTTP_URLHANDLER *AQH_RoomsHttpUrlHandler_new(AQH_SERVICE *sv) { AQH_HTTP_URLHANDLER *uh; - uh=AQH_HttpUrlHandler_new(sv); - AQH_HttpUrlHandler_SetHandleFn(uh, _handleUrl); + uh=AQH_ObjectsHttpUrlHandler_new(sv, + AQHOME_HTTP_PERMS_LIST_ROOMS, + AQHOME_HTTP_PERMS_ADD_ROOM, + AQHOME_HTTP_PERMS_DEL_ROOM, + AQHOME_HTTP_PERMS_EDIT_ROOM, + "/rooms/list"); + AQH_ObjectsHttpUrlHandler_SetAddOrEditObjectFn(uh, _addOrEditObject); + AQH_ObjectsHttpUrlHandler_SetFindObjectByIdAndReturnAsDbFn(uh, _findObjectByIdAndReturnAsDb); + AQH_ObjectsHttpUrlHandler_SetWriteAddPageFn(uh, _writeAddPage); + AQH_ObjectsHttpUrlHandler_SetWriteEditPageFn(uh, _writeEditPage); + AQH_ObjectsHttpUrlHandler_SetListObjectsIntoBufferFn(uh, _listObjectsIntoBuffer); return uh; } -int _handleUrl(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) -{ - const char *protocol; - const char *cmd; - GWEN_MSG *msgOut; - - AQH_HttpService_SetupModuleAndPerms(AQH_HttpUrlHandler_GetHttpService(uh), rq, "aqhome"); - AQH_HttpRequest_SetupUrlPathMembers(rq); - - protocol=AQH_HttpRequest_GetProtocol(rq); - cmd=AQH_HttpRequest_GetCommand(rq); - if (cmd && *cmd) { - if (strcasecmp(cmd, "GET")==0) - msgOut=_handleGet(uh, rq); - else if (strcasecmp(cmd, "POST")==0) - msgOut=_handlePost(uh, rq); - else { - msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 405, "Method not allowed", protocol, NULL); - } - AQH_HttpRequest_SetResponseMsg(rq, msgOut); - return 0; - } - else { - DBG_ERROR(AQH_LOGDOMAIN, "No command in request"); - return GWEN_ERROR_INVALID; - } -} - - - -GWEN_MSG *_handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) -{ - GWEN_BUFFER *pageBuf; - int rv; - GWEN_MSG *msgOut=NULL; - const char *protocol; - const GWEN_STRINGLIST *sl; - - protocol=AQH_HttpRequest_GetProtocol(rq); - pageBuf=GWEN_Buffer_new(0, 256, 0, 1); - rv=AQH_HttpUrlHandler_AddContentHeaders(uh, AQH_HTTP_CONTENT_MODE_DESKTOP, pageBuf); - if (rv<0) { - DBG_ERROR(AQH_LOGDOMAIN, "Error adding headers"); - GWEN_Buffer_free(pageBuf); - return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL); - } - - /* handle middle part (header - middle - footer) */ - sl=AQH_HttpRequest_GetUrlPathMembers(rq); - if (sl) { - const char *s; - - s=GWEN_StringList_StringAt(sl, 1); - if (!(s && *s)) - s="list"; - - if (strcasecmp(s, "list")==0) - _handleGetList(uh, rq, pageBuf); - else if (strcasecmp(s, "add")==0) - _handleGetAdd(uh, rq, pageBuf); - else if (strcasecmp(s, "edit")==0) - _handleGetEdit(uh, rq, GWEN_StringList_StringAsIntAt(sl, 2, 0), pageBuf); - else { - DBG_ERROR(NULL, "Invalid url (2nd member is [%s])", s); - GWEN_Buffer_free(pageBuf); - return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL); - } - } - else { - DBG_ERROR(NULL, "No list of url members"); - GWEN_Buffer_free(pageBuf); - return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL); - } - - rv=AQH_HttpUrlHandler_AddContentFooters(uh, AQH_HTTP_CONTENT_MODE_DESKTOP, pageBuf); - if (rv<0) { - DBG_ERROR(AQH_LOGDOMAIN, "Error adding footers"); - GWEN_Buffer_free(pageBuf); - return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL); - } - - msgOut=AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 200, "OK", protocol, GWEN_Buffer_GetStart(pageBuf)); - GWEN_Buffer_free(pageBuf); - return msgOut; -} - - - -GWEN_MSG *_handlePost(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) -{ - GWEN_DB_NODE *db; - const GWEN_STRINGLIST *sl; - const char *protocol; - - DBG_ERROR(NULL, "POST:"); - db=AQH_HttpRequest_GetDbPostBody(rq); - GWEN_DB_Dump(db, 2); - - protocol=AQH_HttpRequest_GetProtocol(rq); - sl=AQH_HttpRequest_GetUrlPathMembers(rq); - if (sl) { - const char *s; - - s=GWEN_StringList_StringAt(sl, 1); - if (s && *s) { - if (strcasecmp(s, "add")==0) - return _handlePostAdd(uh, rq); - else if (strcasecmp(s, "edit")==0) - return _handlePostEdit(uh, rq, GWEN_StringList_StringAsIntAt(sl, 2, 0)); - else { - DBG_ERROR(NULL, "Invalid url (2nd member is [%s])", s); - return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL); - } - } - else { - DBG_ERROR(NULL, "Invalid url (2nd member missing)"); - return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL); - } - } - else { - DBG_ERROR(NULL, "No list of url members"); - return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL); - } -} - - - -void _handleGetList(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf) -{ - AQH_SERVICE *sv; - uint32_t perms; - - DBG_ERROR(NULL, "LIST"); - perms=AQH_HttpRequest_GetModulePerms(rq); - if (perms & AQHOME_HTTP_PERMS_LIST_ROOMS) { - AQH_STORAGE *sto; - - sv=AQH_HttpUrlHandler_GetHttpService(uh); - sto=AqHomeHttpService_GetStorage(sv); - if (sto) { - const AQH_ROOM_LIST *rl; - - GWEN_Buffer_AppendArgs(pageBuf, - "

%s

" - "" - "" - " " - "", - I18N("Rooms"), - I18N("Name"), - I18N("Description")); - GWEN_Buffer_AppendString(pageBuf, ""); - rl=AQH_Storage_GetRoomList(sto); - if (rl) { - const AQH_ROOM *r; - - r=AQH_Room_List_First(rl); - while(r) { - long unsigned int id; - const char *name; - const char *descr; - - id=(long unsigned int) AQH_Room_GetId(r); - name=AQH_Room_GetName(r); - descr=AQH_Room_GetDescription(r); - GWEN_Buffer_AppendArgs(pageBuf, - "" - "" - "", - id, name?name:"", descr?descr:"", id); - - r=AQH_Room_List_Next(r); - } - } - GWEN_Buffer_AppendString(pageBuf, ""); - GWEN_Buffer_AppendArgs(pageBuf, "
Id%s%s
%lu%s%s" - "
%s
", I18N("Add Room")); - } - else { - GWEN_Buffer_AppendString(pageBuf, "

Internal error.

"); - } - } - else { - GWEN_Buffer_AppendArgs(pageBuf, "

%s

", I18N("No permissions to see list of rooms.")); - } -} - - - -void _handleGetAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *pageBuf) -{ - uint32_t perms; - - DBG_ERROR(NULL, "ADD"); - perms=AQH_HttpRequest_GetModulePerms(rq); - if (perms & AQHOME_HTTP_PERMS_ADD_ROOM) { - _writeAddPage(uh, rq, NULL, pageBuf); - } - else { - DBG_INFO(NULL, "No permissions to add a room."); - GWEN_Buffer_AppendArgs(pageBuf, "

%s

", I18N("No permissions to add a room.")); - } -} - - - -void _handleGetEdit(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id, GWEN_BUFFER *pageBuf) -{ - uint32_t perms; - - DBG_ERROR(NULL, "EDIT"); - perms=AQH_HttpRequest_GetModulePerms(rq); - if (perms & AQHOME_HTTP_PERMS_EDIT_ROOM) { - AQH_SERVICE *sv; - AQH_STORAGE *sto; - - sv=AQH_HttpUrlHandler_GetHttpService(uh); - sto=AqHomeHttpService_GetStorage(sv); - if (id>0) { - const AQH_ROOM *r; - - r=AQH_Storage_GetRoomById(sto, id); - if (r) { - GWEN_DB_NODE *db; - - db=GWEN_DB_Group_new("room"); - AQH_Room_toDb(r, db); - _writeEditPage(uh, rq, db, pageBuf); - GWEN_DB_Group_free(db); - } - else { - DBG_ERROR(NULL, "Room %d not found", id); - GWEN_Buffer_AppendArgs(pageBuf, "

%s

", I18N("Room not found.")); - } - } - else { - DBG_ERROR(NULL, "Missing room id"); - GWEN_Buffer_AppendArgs(pageBuf, "

%s

", I18N("Missing or invalid room id.")); - } - } - else { - DBG_INFO(NULL, "No permissions to edit a room."); - GWEN_Buffer_AppendArgs(pageBuf, "

%s

", I18N("No permissions to edit a room.")); - } -} - - - -int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf) -{ - const char *name=NULL; - const char *descr=NULL; - - if (dbValues) { - name=GWEN_DB_GetCharValue(dbValues, "name", 0, NULL); - descr=GWEN_DB_GetCharValue(dbValues, "description", 0, NULL); - } - GWEN_Buffer_AppendArgs(pageBuf, - "

%s


\n" - "
" - " " - " " - " " - " " - " " - " " - " " - " " - " " - "
" - " " - "
", - I18N("Create a Room"), - I18N("Room Name"), - name?name:"", - I18N("Description"), - descr?descr:"", - I18N("Add Room")); - return 0; -} - - - -int _writeEditPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf) -{ - unsigned long int id=0; - const char *name=NULL; - const char *descr=NULL; - - if (dbValues) { - id=GWEN_DB_GetIntValue(dbValues, "id", 0, 0); - name=GWEN_DB_GetCharValue(dbValues, "name", 0, NULL); - descr=GWEN_DB_GetCharValue(dbValues, "description", 0, NULL); - } - GWEN_Buffer_AppendArgs(pageBuf, - "

%s


\n" - "
" - " " - " " - " " - " " - " " - " " - " " - " " - " " - "
" - " " - "
", - I18N("Edit a Room"), - id, - I18N("Room Name"), - name?name:"", - I18N("Description"), - descr?descr:"", - I18N("Submit")); - return 0; -} - - - -GWEN_MSG *_handlePostAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq) -{ - const char *protocol; - AQH_SERVICE *sv; - uint32_t perms; - - protocol=AQH_HttpRequest_GetProtocol(rq); - sv=AQH_HttpUrlHandler_GetHttpService(uh); - perms=AQH_HttpRequest_GetModulePerms(rq); - if (perms & AQHOME_HTTP_PERMS_ADD_ROOM) - return _addOrEditAndCreateResponse(uh, rq, 0); - else { - return AQH_HttpService_CreateResponseMsg(sv, 403, "Forbidden", protocol, NULL); - } -} - - - -GWEN_MSG *_handlePostEdit(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id) -{ - const char *protocol; - AQH_SERVICE *sv; - uint32_t perms; - - protocol=AQH_HttpRequest_GetProtocol(rq); - sv=AQH_HttpUrlHandler_GetHttpService(uh); - perms=AQH_HttpRequest_GetModulePerms(rq); - if (perms & AQHOME_HTTP_PERMS_EDIT_ROOM) { - return _addOrEditAndCreateResponse(uh, rq, id); - } - else { - return AQH_HttpService_CreateResponseMsg(sv, 403, "Forbidden", protocol, NULL); - } -} - - - -GWEN_MSG *_addOrEditAndCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id) -{ - AQH_SERVICE *sv; - const char *protocol; - GWEN_DB_NODE *db; - AQH_ROOM *r; - int rv; - - sv=AQH_HttpUrlHandler_GetHttpService(uh); - protocol=AQH_HttpRequest_GetProtocol(rq); - db=AQH_HttpRequest_GetDbPostBody(rq); - - r=AQH_Room_fromDb(db); - rv=_addOrEditRoom(uh, r, id); - AQH_Room_free(r); - if (rv<0) { - switch(rv) { - case GWEN_ERROR_INVALID: - return AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Missing fields"), 1, db, _writeAddPage); - case GWEN_ERROR_FOUND: - return AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Room already exists"), 1, db, _writeEditPage); - case GWEN_ERROR_NOT_FOUND: - return AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Room not found"), 1, db, _writeEditPage); - case GWEN_ERROR_IO: - case GWEN_ERROR_INTERNAL: - default: - return AQH_HttpService_CreateResponseMsg(sv, 500, "Internal error", protocol, NULL); - } - } - return AQH_HttpService_CreateRedirectingResponseMsg(sv, protocol, "/rooms/list"); -} - - - -int _addOrEditRoom(AQH_HTTP_URLHANDLER *uh, const AQH_ROOM *newRoom, int id) +int _addOrEditObject(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *db, int id) { AQH_SERVICE *sv; AQH_STORAGE *sto; + AQH_ROOM *newRoom; const char *roomName; int rv; sv=AQH_HttpUrlHandler_GetHttpService(uh); sto=AqHomeHttpService_GetStorage(sv); + newRoom=AQH_Room_fromDb(db); + roomName=AQH_Room_GetName(newRoom); if (!(roomName && *roomName)) { DBG_INFO(NULL, "Missing room name"); + AQH_Room_free(newRoom); return GWEN_ERROR_INVALID; } rv=AqHomeHttpService_LockStorage(sv); if (rv<0) { DBG_ERROR(NULL, "Error locking storage"); + AQH_Room_free(newRoom); return GWEN_ERROR_IO; } if (id>0) { AQH_ROOM *r; + DBG_INFO(NULL, "Edit existing room"); r=AQH_Storage_GetRoomById(sto, id); if (r==NULL) { AqHomeHttpService_UnlockStorage(sv); DBG_ERROR(NULL, "Room %d not found", id); + AQH_Room_free(newRoom); return GWEN_ERROR_NOT_FOUND; } AQH_Room_SetId(r, id); - AQH_Room_SetName(r, roomName); - AQH_Room_SetDescription(r, AQH_Room_GetDescription(newRoom)); + _setFromObject(r, newRoom); AQH_Storage_AddRuntimeFlags(sto, AQH_STORAGE_RTFLAGS_MODIFIED); } else { AQH_ROOM *r; + DBG_INFO(NULL, "Adding new room"); r=AQH_Storage_GetRoomByName(sto, roomName); if (r) { + AqHomeHttpService_UnlockStorage(sv); DBG_ERROR(NULL, "Room %s exists", roomName); + AQH_Room_free(newRoom); return GWEN_ERROR_FOUND; } + r=AQH_Room_new(); + AQH_Room_SetId(r, 0); + _setFromObject(r, newRoom); AQH_Storage_AddRoom(sto, r); AQH_Storage_AddRuntimeFlags(sto, AQH_STORAGE_RTFLAGS_MODIFIED); } + AQH_Room_free(newRoom); rv=AqHomeHttpService_UnlockStorage(sv); if (rv<0) { @@ -519,15 +141,132 @@ int _addOrEditRoom(AQH_HTTP_URLHANDLER *uh, const AQH_ROOM *newRoom, int id) +void _setFromObject(AQH_ROOM *r, const AQH_ROOM *srcRoom) +{ + AQH_Room_SetName(r, AQH_Room_GetName(srcRoom)); + AQH_Room_SetDescription(r, AQH_Room_GetDescription(srcRoom)); +} + + + +GWEN_DB_NODE *_findObjectByIdAndReturnAsDb(AQH_HTTP_URLHANDLER *uh, int id) +{ + AQH_SERVICE *sv; + AQH_STORAGE *sto; + const AQH_ROOM *r; + + sv=AQH_HttpUrlHandler_GetHttpService(uh); + sto=AqHomeHttpService_GetStorage(sv); + + r=AQH_Storage_GetRoomById(sto, id); + if (r) { + GWEN_DB_NODE *db; + + db=GWEN_DB_Group_new("room"); + AQH_Room_toDb(r, db); + return db; + } + return NULL; +} + + + +int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf) +{ + GWEN_Buffer_AppendArgs(pageBuf, + "

%s


\n" + "
", + I18N("Add Room")); + _writeEditingTable(uh, dbValues, pageBuf); + GWEN_Buffer_AppendArgs(pageBuf, "
", I18N("Submit")); + return 0; +} + + + +int _writeEditPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf) +{ + + GWEN_Buffer_AppendArgs(pageBuf, + "

%s


\n" + "
", + I18N("Edit Room"), + (long unsigned int)(dbValues?GWEN_DB_GetIntValue(dbValues, "id", 0, 0):0)); + _writeEditingTable(uh, dbValues, pageBuf); + GWEN_Buffer_AppendArgs(pageBuf, "
", I18N("Submit")); + return 0; +} + + + +void _writeEditingTable(AQH_HTTP_URLHANDLER *uh, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf) +{ + GWEN_Buffer_AppendArgs(pageBuf, + " " + " " + " " + " " + " " + " " + " " + " " + " " + "
", + I18N("Name"), + dbValues?GWEN_DB_GetCharValue(dbValues, "name", 0, ""):"", + I18N("Description"), + dbValues?GWEN_DB_GetCharValue(dbValues, "description", 0, ""):""); +} + + + +void _listObjectsIntoBuffer(AQH_HTTP_URLHANDLER *uh, GWEN_BUFFER *pageBuf) +{ + AQH_SERVICE *sv; + AQH_STORAGE *sto; + const AQH_ROOM_LIST *rl; + + sv=AQH_HttpUrlHandler_GetHttpService(uh); + sto=AqHomeHttpService_GetStorage(sv); + + GWEN_Buffer_AppendArgs(pageBuf, + "

%s

" + "" + "" + " " + "", + I18N("Rooms"), + I18N("Name"), + I18N("Description")); + GWEN_Buffer_AppendString(pageBuf, ""); + rl=AQH_Storage_GetRoomList(sto); + if (rl) { + const AQH_ROOM *r; + + r=AQH_Room_List_First(rl); + while(r) { + long unsigned int id; + const char *name; + const char *descr; + + id=(long unsigned int) AQH_Room_GetId(r); + name=AQH_Room_GetName(r); + descr=AQH_Room_GetDescription(r); + GWEN_Buffer_AppendArgs(pageBuf, + "" + "" + "", + name?name:"", descr?descr:"", id); + + r=AQH_Room_List_Next(r); + } + } + GWEN_Buffer_AppendString(pageBuf, ""); + GWEN_Buffer_AppendArgs(pageBuf, "
%s%s
%s%s" + "
%s
", I18N("Add Room")); +} + + + + -/* TODO: applyRoom(uh, rq, r, id) - * share code! - * - * check values - * - * if id==0: - * - lookup room - * - add room if not already found - * else - * set room data -*/