/**************************************************************************** * 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 //#define DISABLE_DEBUGLOG #include "./service_file_p.h" #include #include /* ------------------------------------------------------------------------------------------------ * defs and enums * ------------------------------------------------------------------------------------------------ */ #define AQH_SERVICE_FILE_GROUP_USERS "users" #define AQH_SERVICE_FILE_GROUP_MODULES "modules" #define AQH_SERVICE_FILE_GROUP_SESSIONS "sessions" /* ------------------------------------------------------------------------------------------------ * global vars * ------------------------------------------------------------------------------------------------ */ GWEN_INHERIT(AQH_SERVICE, AQH_SERVICE_FILE) /* ------------------------------------------------------------------------------------------------ * forward declarations * ------------------------------------------------------------------------------------------------ */ static void GWENHYWFAR_CB _freeData(void *bp, void *p); static AQH_USER *_loadUser(AQH_SERVICE *sv, const char *s); static int _saveUser(AQH_SERVICE *sv, AQH_USER *user); static int _addUser(AQH_SERVICE *sv, AQH_USER *user); static int _delUser(AQH_SERVICE *sv, const char *s); static GWEN_STRINGLIST *_listUsers(AQH_SERVICE *sv); static AQH_MODULE *_loadModule(AQH_SERVICE *sv, const char *s); static int _saveModule(AQH_SERVICE *sv, AQH_MODULE *module); static int _addModule(AQH_SERVICE *sv, AQH_MODULE *module); static int _delModule(AQH_SERVICE *sv, const char *s); static GWEN_STRINGLIST *_listModules(AQH_SERVICE *sv); static AQH_SESSION* _loadSession(AQH_SERVICE *sv, const char *s); static int _saveSession(AQH_SERVICE *sv, AQH_SESSION *session); static int _addSession(AQH_SERVICE *sv, AQH_SESSION *session); static int _delSession(AQH_SERVICE *sv, const char *s); static GWEN_STRINGLIST *_listSessions(AQH_SERVICE *sv); static GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName); static int _saveGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db); static int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db); static int _deleteGroup(AQH_SERVICE *sv, const char *groupName, const char *subGroupName); static GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName); //static void _logGroup(const char *groupName, const char *subGroupName, GWEN_DB_NODE *db); /* ------------------------------------------------------------------------------------------------ * code * ------------------------------------------------------------------------------------------------ */ AQH_SERVICE *AQH_ServiceFiles_new(const char *baseFolder) { AQH_SERVICE *sv; AQH_SERVICE_FILE *xs; GWEN_BUFFER *dbuf; sv=AQH_Service_new(); GWEN_NEW_OBJECT(AQH_SERVICE_FILE, xs); GWEN_INHERIT_SETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv, xs, _freeData); xs->baseFolder=strdup(baseFolder); AQH_Service_SetLoadUserFn(sv, _loadUser); AQH_Service_SetSaveUserFn(sv, _saveUser); AQH_Service_SetAddUserFn(sv, _addUser); AQH_Service_SetDelUserFn(sv, _delUser); AQH_Service_SetListUsersFn(sv, _listUsers); AQH_Service_SetLoadModuleFn(sv, _loadModule); AQH_Service_SetSaveModuleFn(sv, _saveModule); AQH_Service_SetAddModuleFn(sv, _addModule); AQH_Service_SetDelModuleFn(sv, _delModule); AQH_Service_SetListModulesFn(sv, _listModules); AQH_Service_SetLoadSessionFn(sv, _loadSession); AQH_Service_SetSaveSessionFn(sv, _saveSession); AQH_Service_SetAddSessionFn(sv, _addSession); AQH_Service_SetDelSessionFn(sv, _delSession); AQH_Service_SetListSessionsFn(sv, _listSessions); dbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_Buffer_AppendArgs(dbuf, "dir://%s", baseFolder); DBG_ERROR(NULL, "Creating config mgr \"%s\"", GWEN_Buffer_GetStart(dbuf)); xs->configMgr=GWEN_ConfigMgr_Factory(GWEN_Buffer_GetStart(dbuf)); if (xs->configMgr==NULL) { DBG_ERROR(NULL, "Error creating config mgr \"%s\"", GWEN_Buffer_GetStart(dbuf)); GWEN_Buffer_free(dbuf); AQH_Service_free(sv); return NULL; } GWEN_Buffer_free(dbuf); return sv; } void GWENHYWFAR_CB _freeData(GWEN_UNUSED void *bp, void *p) { AQH_SERVICE_FILE *xs; xs=(AQH_SERVICE_FILE*) p; GWEN_ConfigMgr_free(xs->configMgr); free(xs->baseFolder); GWEN_FREE_OBJECT(xs); } AQH_USER *_loadUser(AQH_SERVICE *sv, const char *s) { GWEN_DB_NODE *db; db=_loadGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s); if (db) { AQH_USER *user; user=AQH_User_fromDb(db); GWEN_DB_Group_free(db); return user; } return NULL; } int _saveUser(AQH_SERVICE *sv, AQH_USER *user) { const char *s; s=AQH_User_GetAlias(user); if (s && *s) { GWEN_DB_NODE *db; int rv; db=GWEN_DB_Group_new(s); rv=AQH_User_toDb(user, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } //_logGroup(AQH_SERVICE_FILE_GROUP_USERS, s, db); rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } GWEN_DB_Group_free(db); return 0; } return GWEN_ERROR_INVALID; } int _addUser(AQH_SERVICE *sv, AQH_USER *user) { const char *s; s=AQH_User_GetAlias(user); if (s && *s) { GWEN_DB_NODE *db; int rv; db=GWEN_DB_Group_new(s); rv=AQH_User_toDb(user, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } rv=_addGroupLocked(sv, AQH_SERVICE_FILE_GROUP_USERS, s, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } GWEN_DB_Group_free(db); return 0; } return GWEN_ERROR_INVALID; } int _delUser(AQH_SERVICE *sv, const char *s) { return _deleteGroup(sv, AQH_SERVICE_FILE_GROUP_USERS, s); } GWEN_STRINGLIST *_listUsers(AQH_SERVICE *sv) { return _listGroup(sv, AQH_SERVICE_FILE_GROUP_USERS); } AQH_MODULE *_loadModule(AQH_SERVICE *sv, const char *s) { GWEN_DB_NODE *db; db=_loadGroupLocked(sv, AQH_SERVICE_FILE_GROUP_MODULES, s); if (db) { AQH_MODULE *module; module=AQH_Module_fromDb(db); GWEN_DB_Group_free(db); return module; } return NULL; } int _saveModule(AQH_SERVICE *sv, AQH_MODULE *module) { const char *s; s=AQH_Module_GetName(module); if (s && *s) { GWEN_DB_NODE *db; int rv; db=GWEN_DB_Group_new(s); rv=AQH_Module_toDb(module, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_MODULES, s, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } GWEN_DB_Group_free(db); return 0; } return GWEN_ERROR_INVALID; } int _addModule(AQH_SERVICE *sv, AQH_MODULE *module) { const char *s; s=AQH_Module_GetName(module); if (s && *s) { GWEN_DB_NODE *db; int rv; db=GWEN_DB_Group_new(s); rv=AQH_Module_toDb(module, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } rv=_addGroupLocked(sv, AQH_SERVICE_FILE_GROUP_MODULES, s, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } GWEN_DB_Group_free(db); return 0; } return GWEN_ERROR_INVALID; } int _delModule(AQH_SERVICE *sv, const char *s) { return _deleteGroup(sv, AQH_SERVICE_FILE_GROUP_MODULES, s); } GWEN_STRINGLIST *_listModules(AQH_SERVICE *sv) { return _listGroup(sv, AQH_SERVICE_FILE_GROUP_MODULES); } AQH_SESSION* _loadSession(AQH_SERVICE *sv, const char *s) { GWEN_DB_NODE *db; db=_loadGroupLocked(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s); if (db) { AQH_SESSION *session; session=AQH_Session_fromDb(db); GWEN_DB_Group_free(db); return session; } return NULL; } int _saveSession(AQH_SERVICE *sv, AQH_SESSION *session) { const char *s; s=AQH_Session_GetUid(session); if (s && *s) { GWEN_DB_NODE *db; int rv; db=GWEN_DB_Group_new(s); rv=AQH_Session_toDb(session, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } rv=_saveGroupLocked(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } GWEN_DB_Group_free(db); return 0; } return GWEN_ERROR_INVALID; } int _addSession(AQH_SERVICE *sv, AQH_SESSION *session) { const char *s; s=AQH_Session_GetUid(session); if (s && *s) { GWEN_DB_NODE *db; int rv; db=GWEN_DB_Group_new(s); rv=AQH_Session_toDb(session, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } rv=_addGroupLocked(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s, db); if (rv<0) { DBG_ERROR(NULL, "here (%d)", rv); GWEN_DB_Group_free(db); return rv; } GWEN_DB_Group_free(db); return 0; } return GWEN_ERROR_INVALID; } int _delSession(AQH_SERVICE *sv, const char *s) { return _deleteGroup(sv, AQH_SERVICE_FILE_GROUP_SESSIONS, s); } GWEN_STRINGLIST *_listSessions(AQH_SERVICE *sv) { return _listGroup(sv, AQH_SERVICE_FILE_GROUP_SESSIONS); } GWEN_DB_NODE *_loadGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName) { DBG_ERROR(NULL, "Lock and load group %s/%s", groupName, subGroupName); if (sv && groupName && subGroupName) { AQH_SERVICE_FILE *xs; xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv); if (xs) { GWEN_DB_NODE *db=NULL; int rv; DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName); rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName); if (rv<0) { DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv); return NULL; } DBG_ERROR(NULL, "Loading group %s/%s", groupName, subGroupName); rv=GWEN_ConfigMgr_GetGroup(xs->configMgr, groupName, subGroupName, &db); if (rv<0) { DBG_ERROR(NULL, "Error reading group \"%s/%s\": %d", groupName, subGroupName, rv); GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName); return NULL; } DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName); rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName); if (rv<0) { DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv); GWEN_DB_Group_free(db); return NULL; } return db; } } else { DBG_ERROR(NULL, "Missing argument"); } return NULL; } int _saveGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db) { if (sv && groupName && subGroupName && db) { AQH_SERVICE_FILE *xs; xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv); if (xs) { int rv; DBG_ERROR(NULL, "Locking group %s/%s", groupName, subGroupName); rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName); if (rv<0) { DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv); return rv; } DBG_ERROR(NULL, "Writing group %s/%s", groupName, subGroupName); rv=GWEN_ConfigMgr_SetGroup(xs->configMgr, groupName, subGroupName, db); if (rv<0) { DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv); return rv; } DBG_ERROR(NULL, "Unlocking group %s/%s", groupName, subGroupName); rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName); if (rv<0) { DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv); return rv; } return 0; } } return GWEN_ERROR_INVALID; } int _addGroupLocked(AQH_SERVICE *sv, const char *groupName, const char *subGroupName, GWEN_DB_NODE *db) { if (sv && groupName && subGroupName && db) { AQH_SERVICE_FILE *xs; xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv); if (xs) { int rv; rv=GWEN_ConfigMgr_HasGroup(xs->configMgr, groupName, subGroupName); if (rv>=0) { DBG_ERROR(NULL, "Group \"%s/%s\" already exists", groupName, subGroupName); return GWEN_ERROR_FOUND; } rv=GWEN_ConfigMgr_LockGroup(xs->configMgr, groupName, subGroupName); if (rv<0) { DBG_ERROR(NULL, "Error locking group \"%s/%s\": %d", groupName, subGroupName, rv); return rv; } rv=GWEN_ConfigMgr_SetGroup(xs->configMgr, groupName, subGroupName, db); if (rv<0) { DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv); return rv; } rv=GWEN_ConfigMgr_UnlockGroup(xs->configMgr, groupName, subGroupName); if (rv<0) { DBG_ERROR(NULL, "Error unlocking group \"%s/%s\": %d", groupName, subGroupName, rv); return rv; } return 0; } } return GWEN_ERROR_INVALID; } int _deleteGroup(AQH_SERVICE *sv, const char *groupName, const char *subGroupName) { if (sv && groupName && subGroupName) { AQH_SERVICE_FILE *xs; xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv); if (xs) { int rv; rv=GWEN_ConfigMgr_DeleteGroup(xs->configMgr, groupName, subGroupName); if (rv<0) { DBG_ERROR(NULL, "Error writing group \"%s/%s\": %d", groupName, subGroupName, rv); return rv; } return 0; } } return GWEN_ERROR_INVALID; } GWEN_STRINGLIST *_listGroup(AQH_SERVICE *sv, const char *groupName) { if (sv && groupName) { AQH_SERVICE_FILE *xs; xs=GWEN_INHERIT_GETDATA(AQH_SERVICE, AQH_SERVICE_FILE, sv); if (xs) { GWEN_STRINGLIST *sl; int rv; sl=GWEN_StringList_new(); rv=GWEN_ConfigMgr_ListSubGroups(xs->configMgr, groupName, sl); if (rv<0) { DBG_ERROR(NULL, "Error listing group \"%s\": %d", groupName, rv); GWEN_StringList_free(sl); return NULL; } if (GWEN_StringList_Count(sl)==0) { GWEN_StringList_free(sl); return NULL; } return sl; } } return NULL; } #if 0 void _logGroup(const char *groupName, const char *subGroupName, GWEN_DB_NODE *db) { if (db) { GWEN_BUFFER *dbuf; dbuf=GWEN_Buffer_new(0, 256, 0, 1); GWEN_DB_WriteToBuffer(db, dbuf, GWEN_DB_FLAGS_DEFAULT); DBG_ERROR(NULL, "Group %s/%s:\n%s", groupName?groupName:"", subGroupName?subGroupName:"", GWEN_Buffer_GetStart(dbuf)); GWEN_Buffer_free(dbuf); } else { DBG_ERROR(NULL, "Group %s/%s empty", groupName?groupName:"", subGroupName?subGroupName:""); } } #endif