/**************************************************************************** * 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 "./mservice_p.h" #include "aqhome-cgi/service/module.h" #include /* ------------------------------------------------------------------------------------------------ * defs and enums * ------------------------------------------------------------------------------------------------ */ #define AQH_MOD_SERVICE_HEADERFILE "header.html" #define AQH_MOD_SERVICE_FOOTERFILE "footer.html" /* ------------------------------------------------------------------------------------------------ * global vars * ------------------------------------------------------------------------------------------------ */ GWEN_INHERIT(AQH_MODULE, AQH_MOD_SERVICE) /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static void GWENHYWFAR_CB _freeData(void *bp, void *p); static void _calcUserModPerms(AQH_MODULE *m, const AQH_USER *user); static uint32_t _calcRolePerms(const AQH_MODULE *m, const AQH_MODULE_PERMS *modPerms); /* ------------------------------------------------------------------------------------------------ * code * ------------------------------------------------------------------------------------------------ */ void AQH_ModService_Extend(AQH_MODULE *m, AQH_SERVICE *sv, const char *baseFolder) { AQH_MOD_SERVICE *xm; GWEN_NEW_OBJECT(AQH_MOD_SERVICE, xm); GWEN_INHERIT_SETDATA(AQH_MODULE, AQH_MOD_SERVICE, m, xm, _freeData); xm->service=sv; xm->baseFolder=(baseFolder && *baseFolder)?strdup(baseFolder):NULL; } void _freeData(GWEN_UNUSED void *bp, void *p) { AQH_MOD_SERVICE *xm; xm=(AQH_MOD_SERVICE*) p; free(xm->baseFolder); GWEN_FREE_OBJECT(xm); } AQH_SERVICE *AQH_ModService_GetService(const AQH_MODULE *m) { if (m) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { return xm->service; } } return NULL; } const char *AQH_ModService_GetBaseFolder(const AQH_MODULE *m) { if (m) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { return xm->baseFolder; } } return NULL; } uint32_t AQH_ModService_GetUserPerms(const AQH_MODULE *m) { if (m) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { return xm->userPerms; } } return 0; } void AQH_ModService_SetHandleRequestFn(AQH_MODULE *m, AQH_MODSERVICE_HANDLEREQUEST_FN fn) { if (m) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { xm->handleRequestFn=fn; } } } void AQH_ModService_SetLoadSubModuleFn(AQH_MODULE *m, AQH_MODSERVICE_LOADSUBMODULE_FN fn) { if (m) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { xm->loadSubModuleFn=fn; } } } void AQH_ModService_SetAddHeaderFn(AQH_MODULE *m, AQH_MODSERVICE_ADDHEADER_FN fn) { if (m) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { xm->addHeaderFn=fn; } } } void AQH_ModService_SetAddFooterFn(AQH_MODULE *m, AQH_MODSERVICE_ADDFOOTER_FN fn) { if (m) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { xm->addFooterFn=fn; } } } void AQH_ModService_AddHeader(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf) { if (m && dbuf) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { if (xm->addHeaderFn) xm->addHeaderFn(m, lang, dbuf); else { AQH_MODULE *mParent; mParent=AQH_Module_Tree2_GetParent(m); if (mParent) AQH_ModService_AddHeader(mParent, lang, dbuf); AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_HEADERFILE, dbuf); } } } } void AQH_ModService_AddFooter(AQH_MODULE *m, const char *lang, GWEN_BUFFER *dbuf) { if (m && dbuf) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { if (xm->addFooterFn) xm->addFooterFn(m, lang, dbuf); else { AQH_MODULE *mParent; AQH_ModService_ReadStaticFile(m, lang, AQH_MOD_SERVICE_FOOTERFILE, dbuf); mParent=AQH_Module_Tree2_GetParent(m); if (mParent) AQH_ModService_AddFooter(mParent, lang, dbuf); } } } } int AQH_ModService_RespondWithFile(AQH_MODULE *m, AQCGI_REQUEST *rq, const char *lang, const char *sFilename) { GWEN_BUFFER *buf; int rv; buf=GWEN_Buffer_new(0, 256, 0, 1); AQH_ModService_AddHeader(m, lang, buf); rv=AQH_ModService_ReadStaticFile(m, lang, sFilename, buf); if (rv<0) { AQCGI_SendResponseWithStatus(rq, 500, "Internal error"); GWEN_Buffer_free(buf); return GWEN_ERROR_INTERNAL; } AQH_ModService_AddFooter(m, lang, buf); AQCGI_Request_SetBufferResponseBody(rq, buf); AQCGI_Request_AddResponseHeaderData(rq, "Content-type: text/html"); AQCGI_SendResponseWithStatus(rq, 200, "Ok"); return 0; } int AQH_ModService_HandleRequest(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sLastPathElem) { if (m) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm && xm->handleRequestFn) return xm->handleRequestFn(m, rq, session, sLastPathElem); } return GWEN_ERROR_NOT_IMPLEMENTED; } AQH_MODULE *AQH_ModService_LoadSubModule(AQH_MODULE *m, AQCGI_REQUEST *rq, AQH_SESSION *session, const char *sModuleName) { if (m) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm && xm->loadSubModuleFn) { AQH_MODULE *mReturn; mReturn=xm->loadSubModuleFn(m, rq, session, sModuleName); if (mReturn) AQH_ModService_CalcSessionModPerms(mReturn, session); return mReturn; } } return NULL; } int AQH_ModService_ReadStaticFile(AQH_MODULE *m, const char *lang, const char *filename, GWEN_BUFFER *dbuf) { if (m && filename && dbuf) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { GWEN_BUFFER *fbuf; int rv; fbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendString(fbuf, xm->baseFolder); GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S); GWEN_Buffer_AppendString(fbuf, (lang && *lang)?lang:"en"); GWEN_Buffer_AppendString(fbuf, GWEN_DIR_SEPARATOR_S); GWEN_Buffer_AppendString(fbuf, filename); DBG_ERROR(NULL, "Reading file \"%s\"", GWEN_Buffer_GetStart(fbuf)); rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(fbuf), dbuf); if (rv<0) { DBG_ERROR(NULL, "Read(%s): %d", GWEN_Buffer_GetStart(fbuf), rv); GWEN_Buffer_free(fbuf); return rv; } GWEN_Buffer_free(fbuf); return 0; } } DBG_ERROR(NULL, "Any arg is missing (or is not a AQH_MOD_SERVICE object)"); return GWEN_ERROR_INTERNAL; } AQH_SESSION *AQH_ModService_ReadSession(AQH_MODULE *m, AQCGI_REQUEST *rq) { AQH_SERVICE *sv; GWEN_DB_NODE *db; const char *s; sv=AQH_ModService_GetService(m); db=AQCGI_Request_GetDbRequestHeader(rq); s=GWEN_DB_GetCharValue(db, "cookies/session", 0, NULL); if (s && *s) { AQH_SESSION *session; session=AQH_Service_LoadSession(sv, s); if (session==NULL) { DBG_ERROR(NULL, "Session \"%s\" not found", s); return NULL; } else { const char *sUserName; sUserName=AQH_Session_GetUserAlias(session); if (sUserName && *sUserName) { AQH_USER *user; user=AQH_Service_LoadUser(sv, sUserName); if (user==NULL) { DBG_ERROR(NULL, "User \"%s\" not found", sUserName); AQH_Session_free(session); return NULL; } else { DBG_ERROR(NULL, "User is \"%s\"", sUserName); } AQH_Session_SetUser(session, user); } return session; } } else { DBG_ERROR(NULL, "No session cookie"); } return NULL; } void AQH_ModService_CalcSessionModPerms(AQH_MODULE *m, const AQH_SESSION *session) { const AQH_USER *user; user=session?AQH_Session_GetUser(session):NULL; _calcUserModPerms(m, user); } void _calcUserModPerms(AQH_MODULE *m, const AQH_USER *user) { if (m) { AQH_MOD_SERVICE *xm; xm=GWEN_INHERIT_GETDATA(AQH_MODULE, AQH_MOD_SERVICE, m); if (xm) { uint32_t perms=0; if (user) { if (AQH_User_GetFlags(user) & AQH_USER_FLAGS_ADMIN) perms=0xffffffff; else { const char *sModName; const AQH_MODULE_PERMS_LIST *modPermsList; AQH_MODULE_PERMS *modPerms; sModName=AQH_Module_GetName(m); modPermsList=AQH_User_GetModulePermList(user); modPerms=(sModName && modPermsList)?AQH_ModulePerms_List_GetByModuleId(modPermsList, sModName):NULL; if (modPerms) perms=_calcRolePerms(m, modPerms); else perms=AQH_Module_GetGuestPerms(m); } } /* if (user) */ else perms=AQH_Module_GetGuestPerms(m); xm->userPerms=perms; } } /* if (m) */ } uint32_t _calcRolePerms(const AQH_MODULE *m, const AQH_MODULE_PERMS *modPerms) { uint32_t perms=0; const AQH_ROLE_LIST *roleList; roleList=AQH_Module_GetRoleList(m); if (roleList) { int roleArraySize; int i; uint32_t explAddPerms=0; uint32_t explDelPerms=0; roleArraySize=AQH_ModulePerms_GetRoleArrayArraySize(); for (i=0; i