/**************************************************************************** * This file is part of the project AqHome. * AqHome (c) by 2025 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 "./madmin.h" #include "aqhome-cgi/service/module.h" #include #include /* ------------------------------------------------------------------------------------------------ * defs and enums * ------------------------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------------------------ * global vars * ------------------------------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName); static int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem); static int _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); static int _handleRqEditMod(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); static int _handleRqEditModGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); static int _handleRqEditModPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); static int _handleRqEditPerm(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); static int _handleRqEditPermGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); static int _handleRqEditPermPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf); static void _writePermissionsToForm(const AQH_PERMDEF_LIST *permDefList, uint32_t perms, GWEN_BUFFER *dbuf); static uint32_t _readPermissionsFromForm(GWEN_DB_NODE *dbPost, const AQH_PERMDEF_LIST *permDefList); /* ------------------------------------------------------------------------------------------------ * code * ------------------------------------------------------------------------------------------------ */ void AQH_ModAdmModules_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder) { AQH_ModService_Extend(m, sv, baseFolder); AQH_ModService_SetHandleRequestFn(m, _handleRequest); AQH_ModService_SetLoadSubModuleFn(m, _loadSubModule); } AQH_MODULE *_loadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName) { /* no sub-modules */ return NULL; } int _handleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem) { GWEN_BUFFER *dbuf; int rv; dbuf=GWEN_Buffer_new(0, 256, 0, 1); AQH_ModService_AddHeader(m, "en", dbuf); if (strcasecmp(sLastPathElem, "index.html")==0) rv=_handleRqIndex(m, rq, session, dbuf); else if (strcasecmp(sLastPathElem, "editmodule.html")==0) rv=_handleRqEditMod(m, rq, session, dbuf); else if (strcasecmp(sLastPathElem, "editperm.html")==0) rv=_handleRqEditPerm(m, rq, session, dbuf); else { AQH_ModService_AddFooter(m, "en", dbuf); AQCGI_Request_SetBufferResponseBody(rq, dbuf); AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html"); AQCGI_SendResponseWithStatus(rq, 404, "Not Found"); GWEN_Buffer_free(dbuf); return GWEN_ERROR_NOT_IMPLEMENTED; } AQH_ModService_AddFooter(m, "en", dbuf); AQCGI_Request_SetBufferResponseBody(rq, dbuf); AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html"); if (rv==1) AQCGI_SendResponseWithStatus(rq, 302, "See other"); else AQCGI_SendResponseWithStatus(rq, 200, "Ok"); GWEN_Buffer_free(dbuf); return 0; } int _handleRqIndex(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) { AQH_SERVICE *sv; GWEN_STRINGLIST *slModules; sv=AQH_ModService_GetService(m); slModules=AQH_Service_ListModules(sv); if (slModules) { GWEN_STRINGLISTENTRY *se; GWEN_Buffer_AppendString(dbuf, "

Modules

\n"); GWEN_Buffer_AppendString(dbuf, "\n" "" "" "" "" "" "" "" "\n" "\n"); se=GWEN_StringList_FirstEntry(slModules); while(se) { const char *sModName; sModName=GWEN_StringListEntry_Data(se); if (sModName && *sModName) { AQH_MODULE *currentMod; currentMod=AQH_Service_LoadModule(sv, sModName); if (currentMod) { const char *s; const char *sName; sName=AQH_Module_GetName(currentMod); GWEN_Buffer_AppendString(dbuf, ""); /* id */ GWEN_Buffer_AppendArgs(dbuf, "", (unsigned long int) AQH_Module_GetId(currentMod)); GWEN_Buffer_AppendArgs(dbuf, "", sName?sName:""); s=AQH_Module_GetDescr(currentMod); GWEN_Buffer_AppendArgs(dbuf, "", s?s:""); GWEN_Buffer_AppendArgs(dbuf, "", sName?sName:""); GWEN_Buffer_AppendArgs(dbuf, "\n"); AQH_Module_free(currentMod); } } se=GWEN_StringListEntry_Next(se); } GWEN_Buffer_AppendString(dbuf, "\n" "
IdNameDescriptionActions
%lu%s%s
\n"); GWEN_StringList_free(slModules); } GWEN_Buffer_AppendString(dbuf, "
Add Module"); return 0; } int _handleRqEditMod(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) { if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET) return _handleRqEditModGet(m, rq, session, dbuf); else if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_POST) return _handleRqEditModPost(m, rq, session, dbuf); else { DBG_ERROR(NULL, "Invalid request method %d", AQCGI_Request_GetRequestMethod(rq)); AQCGI_SendResponseWithStatus(rq, 405, "Method No Allowed"); return GWEN_ERROR_INVALID; } return 0; } int _handleRqEditModGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) { AQH_SERVICE *sv; GWEN_DB_NODE *dbQuery; sv=AQH_ModService_GetService(m); dbQuery=AQCGI_Request_GetDbQuery(rq); if (dbQuery) { const char *sModName; sModName=GWEN_DB_GetCharValue(dbQuery, "name", 0, NULL); if (sModName && *sModName) { AQH_MODULE *currentMod; currentMod=AQH_Service_LoadModule(sv, sModName); if (currentMod) { const char *sName; const char *sDescr; const AQH_PERMDEF_LIST *permDefList; permDefList=AQH_Module_GetPermDefList(currentMod); sName=AQH_Module_GetName(currentMod); sDescr=AQH_Module_GetDescr(currentMod); GWEN_Buffer_AppendString(dbuf, "

Module Info

\n"); GWEN_Buffer_AppendArgs(dbuf, "
\n" "\n" "" "" "" "\n" "" "" "" "\n", sName?sName:"", sDescr?sDescr:""); if (permDefList) { GWEN_Buffer_AppendArgs(dbuf, "" "\n" "" ""); } GWEN_Buffer_AppendString(dbuf, "
"); _writePermissionsToForm(permDefList, AQH_Module_GetGuestPerms(currentMod), dbuf); GWEN_Buffer_AppendArgs(dbuf, "
\n"); GWEN_Buffer_AppendArgs(dbuf, "\n", sModName?sModName:""); GWEN_Buffer_AppendString(dbuf, "\n
\n\n"); GWEN_Buffer_AppendString(dbuf, "

Permission Definitions

\n"); if (permDefList) { const AQH_PERMDEF *permDef; GWEN_Buffer_AppendString(dbuf, "\n" "" "\n" "\n" "\n"); permDef=AQH_PermDef_List_First(permDefList); while(permDef) { const char *sId; const char *s; GWEN_Buffer_AppendString(dbuf, ""); /* id */ sId=AQH_PermDef_GetId(permDef); GWEN_Buffer_AppendArgs(dbuf, "", sId?sId:""); /* mask */ GWEN_Buffer_AppendArgs(dbuf, "", AQH_PermDef_GetMask(permDef)); /* description */ s=AQH_PermDef_GetDescr(permDef); GWEN_Buffer_AppendArgs(dbuf, "", s?s:""); /* actions */ GWEN_Buffer_AppendArgs(dbuf, ""); GWEN_Buffer_AppendString(dbuf, "\n"); permDef=AQH_PermDef_List_Next(permDef); } GWEN_Buffer_AppendString(dbuf, "\n" "
IdMaskDescriptionActions
%s0x%x%s"); GWEN_Buffer_AppendArgs(dbuf, "" "", sModName?sModName:"", sId?sId:""); GWEN_Buffer_AppendArgs(dbuf, "" "", sModName?sModName:"", sId?sId:""); GWEN_Buffer_AppendArgs(dbuf, "
\n"); } else { GWEN_Buffer_AppendString(dbuf, "none"); } GWEN_Buffer_AppendArgs(dbuf, "" "Add Permission\n", sModName?sModName:""); return 0; } } } AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html"); return 1; /* redirect */ } int _handleRqEditModPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) { AQH_SERVICE *sv; GWEN_DB_NODE *dbPost; DBG_ERROR(NULL, "Post request received"); sv=AQH_ModService_GetService(m); dbPost=AQCGI_Request_GetDbPostBody(rq); if (dbPost) { const char *sModName; sModName=GWEN_DB_GetCharValue(dbPost, "module", 0, NULL); if (sModName && *sModName) { AQH_MODULE *currentMod; currentMod=AQH_Service_LoadModule(sv, sModName); if (currentMod) { const char *sNewModName; const char *sDescr; int rv; uint32_t perms; const AQH_PERMDEF_LIST *permDefList; permDefList=AQH_Module_GetPermDefList(currentMod); sNewModName=GWEN_DB_GetCharValue(dbPost, "name", 0, NULL); sDescr=GWEN_DB_GetCharValue(dbPost, "descr", 0, NULL); perms=_readPermissionsFromForm(dbPost, permDefList); if (sNewModName && *sNewModName) AQH_Module_SetName(currentMod, sNewModName); AQH_Module_SetDescr(currentMod, sDescr); AQH_Module_SetGuestPerms(currentMod, perms); rv=AQH_Service_SaveModule(sv, currentMod); if (rv<0) { GWEN_Buffer_AppendString(dbuf, "

Error

Error saving module

"); DBG_ERROR(NULL, "Could not save module \"%s\"", sModName); return 0; } else { DBG_ERROR(NULL, "Module \"%s\" saved", sModName); } AQH_Module_free(currentMod); } else { DBG_ERROR(NULL, "Could not load module \"%s\"", sModName); } } else { DBG_ERROR(NULL, "No module name"); } } else { DBG_ERROR(NULL, "dbPost missing"); } AQCGI_Request_AddResponseHeaderData(rq, "Location: index.html"); return 1; /* redirect! */ } int _handleRqEditPerm(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) { if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_GET) return _handleRqEditPermGet(m, rq, session, dbuf); else if (AQCGI_Request_GetRequestMethod(rq)==AQCGI_REQUEST_METHOD_POST) return _handleRqEditPermPost(m, rq, session, dbuf); else { DBG_ERROR(NULL, "Invalid request method %d", AQCGI_Request_GetRequestMethod(rq)); AQCGI_SendResponseWithStatus(rq, 405, "Method Not Allowed"); return GWEN_ERROR_INVALID; } return 0; } int _handleRqEditPermGet(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) { AQH_SERVICE *sv; GWEN_DB_NODE *dbQuery; const char *sModName; const char *sId; const char *sDescr; uint32_t mask; AQH_MODULE *currentMod; const AQH_PERMDEF_LIST *permDefList; const AQH_PERMDEF *permDef; sv=AQH_ModService_GetService(m); dbQuery=AQCGI_Request_GetDbQuery(rq); sModName=dbQuery?GWEN_DB_GetCharValue(dbQuery, "mod", 0, NULL):NULL; sId=dbQuery?GWEN_DB_GetCharValue(dbQuery, "id", 0, NULL):NULL; currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL; permDefList=currentMod?AQH_Module_GetPermDefList(currentMod):NULL; permDef=(permDefList && sId && *sId)?AQH_PermDef_List_GetById(permDefList, sId):NULL; sDescr=permDef?AQH_PermDef_GetDescr(permDef):NULL; mask=permDef?AQH_PermDef_GetMask(permDef):0; if (permDef) { GWEN_Buffer_AppendArgs(dbuf, "

Edit Permission Definition for Module %s

\n", sModName?sModName:""); GWEN_Buffer_AppendArgs(dbuf, "
\n" "\n" "" "" "" "\n" "\n" "" "" "\n" "" "" "" "\n", sId, (unsigned long int) mask, sDescr?sDescr:""); GWEN_Buffer_AppendString(dbuf, "
\n"); GWEN_Buffer_AppendArgs(dbuf, "\n", sModName?sModName:""); GWEN_Buffer_AppendArgs(dbuf, "\n", sId?sId:""); GWEN_Buffer_AppendString(dbuf, "\n"); GWEN_Buffer_AppendString(dbuf, "
\n\n"); return 0; } else { GWEN_BUFFER *tbuf; tbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendArgs(tbuf, "Location: editmodule.html?name=%s", sModName?sModName:""); AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(tbuf)); GWEN_Buffer_free(tbuf); return 1; /* redirect */ } } int _handleRqEditPermPost(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, GWEN_BUFFER *dbuf) { AQH_SERVICE *sv; GWEN_DB_NODE *dbPost; const char *sModName; AQH_MODULE *currentMod; const char *sOldId; const char *sNewId; const char *sDescr; const char *sMask; uint32_t mask=0; AQH_PERMDEF_LIST *permDefList; AQH_PERMDEF *permDef; long int i; int rv; GWEN_BUFFER *tbuf; /* sample data */ sv=AQH_ModService_GetService(m); dbPost=AQCGI_Request_GetDbPostBody(rq); sModName=dbPost?GWEN_DB_GetCharValue(dbPost, "mod", 0, NULL):NULL; currentMod=(sModName && *sModName)?AQH_Service_LoadModule(sv, sModName):NULL; sOldId=dbPost?GWEN_DB_GetCharValue(dbPost, "oldId", 0, NULL):NULL; sNewId=dbPost?GWEN_DB_GetCharValue(dbPost, "id", 0, NULL):NULL; sDescr=dbPost?GWEN_DB_GetCharValue(dbPost, "descr", 0, NULL):NULL; sMask=dbPost?GWEN_DB_GetCharValue(dbPost, "mask", 0, NULL):NULL; if (sMask && *sMask && 1==sscanf(sMask, "%li", &i)) mask=i; permDefList=currentMod?AQH_Module_GetPermDefList(currentMod):NULL; permDef=(permDefList && sOldId)?AQH_PermDef_List_GetById(permDefList, sOldId):NULL; /* validate */ if (mask==0) { DBG_ERROR(NULL, "Invalid value for mask"); } if (permDef==NULL) { DBG_ERROR(NULL, "PermDef %s not found", sOldId?sOldId:NULL); } /* set new values */ AQH_PermDef_SetId(permDef, sNewId); AQH_PermDef_SetMask(permDef, mask); AQH_PermDef_SetDescr(permDef, sDescr); /* save module */ rv=AQH_Service_SaveModule(sv, currentMod); if (rv<0) { GWEN_Buffer_AppendString(dbuf, "

Error

Error saving module

"); DBG_ERROR(NULL, "Could not save module \"%s\"", sModName); return 0; } tbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendArgs(tbuf, "Location: editmodule.html?name=%s", sModName?sModName:""); AQCGI_Request_AddResponseHeaderData(rq, GWEN_Buffer_GetStart(tbuf)); GWEN_Buffer_free(tbuf); return 1; /* redirect */ } void _writePermissionsToForm(const AQH_PERMDEF_LIST *permDefList, uint32_t perms, GWEN_BUFFER *dbuf) { if (permDefList) { const AQH_PERMDEF *permDef; permDef=AQH_PermDef_List_First(permDefList); while(permDef) { const char *s; uint32_t mask; s=AQH_PermDef_GetId(permDef); mask=AQH_PermDef_GetMask(permDef); if (perms & mask) GWEN_Buffer_AppendArgs(dbuf, "", s?s:""); else GWEN_Buffer_AppendArgs(dbuf, "", s?s:""); GWEN_Buffer_AppendArgs(dbuf, "", s?s:"", s?s:""); permDef=AQH_PermDef_List_Next(permDef); } } } uint32_t _readPermissionsFromForm(GWEN_DB_NODE *dbPost, const AQH_PERMDEF_LIST *permDefList) { uint32_t result=0; if (permDefList) { const AQH_PERMDEF *permDef; permDef=AQH_PermDef_List_First(permDefList); while(permDef) { const char *id; uint32_t mask; const char *s; id=AQH_PermDef_GetId(permDef); mask=AQH_PermDef_GetMask(permDef); s=GWEN_DB_GetCharValue(dbPost, id, 0, NULL); if (s && *s) result|=mask; permDef=AQH_PermDef_List_Next(permDef); } } return result; }