Compare commits

4 Commits

Author SHA1 Message Date
Martin Preuss
0eea29ca2b service: completed header file. 2026-05-31 01:43:39 +02:00
Martin Preuss
ee823eeb3d service: more functions for www<->object 2026-05-31 01:28:58 +02:00
Martin Preuss
10475ec8af added service code (used by AqHome). 2026-05-30 18:56:14 +02:00
Martin Preuss
aeb0974043 increased buffer size, added acceptable character. 2026-05-29 16:15:52 +02:00
19 changed files with 2059 additions and 4 deletions

4
0BUILD
View File

@@ -13,8 +13,8 @@
<gwbuild requiredVersion="5.6.0" >
<!-- use vtag=beta for beta versions -->
<project name="aqcgi"
vmajor="0" vminor="0" vpatchlevel="4" vbuild="0"
so_current="0" so_age="0" so_revision="4"
vmajor="0" vminor="1" vpatchlevel="0" vbuild="0"
so_current="1" so_age="0" so_revision="0"
write_config_h="TRUE"
>

View File

@@ -85,6 +85,7 @@
<useTargets>
aqhcgi_service
</useTargets>
@@ -94,6 +95,7 @@
<subdirs>
service
</subdirs>

View File

@@ -205,7 +205,7 @@ int AQCGI_ParseUrlEncoded(const char *s, int contentLength, GWEN_DB_NODE *dbDeco
if (nameLen && valueLen) {
char sNameBuf[32];
char sValueBuf[64];
char sValueBuf[128];
if (_unescapeUrlEncoded(sNameStart, nameLen, sNameBuf, sizeof(sNameBuf))>=0 &&
_unescapeUrlEncoded(sValueStart, valueLen, sValueBuf, sizeof(sValueBuf))>=0)
@@ -373,7 +373,8 @@ int _unescapeUrlEncoded(const char *src, unsigned int srclen, char *buffer, unsi
x=='?' ||
x=='+' ||
x=='-' ||
x=='_'
x=='_' ||
x=='/'
) {
if (size<(maxsize-1)) {
buffer[size++]=(x=='+')?' ':x;

99
src/aqcgi/service/0BUILD Normal file
View File

@@ -0,0 +1,99 @@
<?xml?>
<gwbuild>
<target type="ConvenienceLibrary" name="aqhcgi_service" >
<includes type="c" >
$(gwenhywfar_cflags)
-I$(topsrcdir)/src
-I$(topbuilddir)/src
-I$(topbuilddir)
-I$(topsrcdir)
-I$(srcdir)
</includes>
<includes type="tm2" >
--include=$(builddir)
--include=$(srcdir)
</includes>
<define name="BUILDING_AQCGI" />
<setVar name="local/cflags">$(visibility_cflags)</setVar>
<setVar name="tm2flags" >
--api=AQCGI_API
</setVar>
<setVar name="local/typefiles" >
module.t2d
moduleperms.t2d
role.t2d
user.t2d
session.t2d
permdef.t2d
object.t2d
objectdef.t2d
objectfielddef.t2d
</setVar>
<setVar name="local/built_sources" >
</setVar>
<setVar name="local/built_headers_pub">
module.h
moduleperms.h
role.h
user.h
session.h
permdef.h
object.h
objectdef.h
objectfielddef.h
</setVar>
<setVar name="local/built_headers_priv" >
</setVar>
<headers dist="false" install="$(pkgincludedir)/service" >
$(local/built_headers_pub)
</headers>
<headers dist="true" install="$(pkgincludedir)/service" >
object_html.h
service.h
</headers>
<headers dist="true" >
service_p.h
</headers>
<sources>
$(local/typefiles)
object_html.c
service.c
</sources>
<extradist>
</extradist>
<useTargets>
</useTargets>
<subdirs>
</subdirs>
</target>
</gwbuild>

20
src/aqcgi/service/README Normal file
View File

@@ -0,0 +1,20 @@
- service:
- userList
- rootModule
- sessionList
- user:
- modulePerms
- module:
- roleList
- permDefList
- session

View File

@@ -0,0 +1,103 @@
<?xml?>
<tm2>
<type id="AQCGI_MODULE" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQCGI_MODULE</identifier>
<prefix>AQCGI_Module</prefix>
<baseFileName>module</baseFileName>
<flags>
with_inherit
with_xml
with_db
with_list1
with_list2
with_tree2
nodup
nocopy
</flags>
<headers>
<header type="sys" loc="pre">aqcgi/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
<header type="sys" loc="post">aqcgi/service/role.h</header>
<header type="sys" loc="post">aqcgi/service/permdef.h</header>
</headers>
<inlines>
</inlines>
</lang>
<defines>
<define id="AQCGI_MODULE_FLAGS" prefix="AQCGI_MODULE_FLAGS_">
<item name="ACTIVE" value="0x00000001" />
</define>
</defines>
<members>
<member name="id" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember sortbymember</flags>
</member>
<member name="flags" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_flags</flags>
</member>
<member name="name" type="char_ptr" maxlen="16">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own with_getbymember sortbymember</flags>
</member>
<member name="descr" type="char_ptr" maxlen="256">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="guestPerms" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
<member name="roleList" type="AQCGI_ROLE_LIST" elementName="role" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<getflags>none</getflags>
<setflags>none</setflags>
</member>
<member name="permDefList" type="AQCGI_PERMDEF_LIST" elementName="permdef" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<getflags>none</getflags>
<setflags>none</setflags>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,67 @@
<?xml?>
<tm2>
<type id="AQCGI_MODULE_PERMS" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQCGI_MODULE_PERMS</identifier>
<prefix>AQCGI_ModulePerms</prefix>
<baseFileName>moduleperms</baseFileName>
<flags>
with_inherit
with_xml
with_db
with_list1
with_list2
</flags>
<headers>
<header type="sys" loc="pre">aqcgi/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
<header type="sys" loc="post">aqcgi/service/role.h</header>
</headers>
<inlines>
</inlines>
</lang>
<members>
<member name="moduleId" type="char_ptr" maxlen="256">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember sortbymember</flags>
</member>
<member name="explAddPerms" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
<member name="explDelPerms" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
<member name="roleArray" type="uint8_t_array" maxlen="16">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,75 @@
<?xml?>
<tm2>
<type id="AQCGI_OBJECT" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQCGI_OBJECT</identifier>
<prefix>AQCGI_Object</prefix>
<baseFileName>object</baseFileName>
<flags>
with_xml
with_db
with_list1
with_list2
</flags>
<headers>
<header type="sys" loc="pre">aqcgi/api.h</header>
<header type="sys" loc="pre">aqcgi/service/objectdef.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
</headers>
<inlines>
</inlines>
</lang>
<members>
<member name="id" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember sortbymember</flags>
</member>
<member name="creationTime" type="uint64_t" maxlen="8">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
<member name="vars" type="GWEN_DB_NODE">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
<getflags>none</getflags>
<setflags>nocopy</setflags>
</member>
<member name="text" type="char_ptr" maxlen="65536" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="filePath" type="char_ptr" maxlen="256" >
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,443 @@
/****************************************************************************
* This file is part of the project AqCGI.
* AqCGI (c) by 2026 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 <config.h>
#endif
//#define DISABLE_DEBUGLOG
#include "aqcgi/service/object_html.h"
#include <gwenhywfar/stringlist.h>
#include <gwenhywfar/text.h>
#include <gwenhywfar/gwendate.h>
#include <gwenhywfar/timestamp.h>
#include <gwenhywfar/debug.h>
/* ------------------------------------------------------------------------------------------------
* defs and enums
* ------------------------------------------------------------------------------------------------
*/
#define GBAS GWEN_Buffer_AppendString
#define GBAA GWEN_Buffer_AppendArgs
#define I18N(msg) msg
/* ------------------------------------------------------------------------------------------------
* forward declarations
* ------------------------------------------------------------------------------------------------
*/
static int _fieldToForm(const AQCGI_OBJECT *o, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf);
static int _writeBool(GWEN_DB_NODE *db, const char *n, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf);
static int _writeInt(GWEN_DB_NODE *db, const char *n, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf);
static int _writeString(GWEN_DB_NODE *db, const char *n, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf);
static int _writeDate(GWEN_DB_NODE *db, const char *n, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf);
static int _writeChoice(GWEN_DB_NODE *db, const char *n, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf);
static int _writeText(const AQCGI_OBJECT *o, GWEN_BUFFER *dbuf);
static int _fieldFromPostRq(AQCGI_OBJECT *o, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost);
static int _readBool(GWEN_DB_NODE *db, const char *n, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost);
static int _readInt(GWEN_DB_NODE *db, const char *n, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost);
static int _readString(GWEN_DB_NODE *db, const char *n, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost);
static int _readDate(GWEN_DB_NODE *db, const char *n, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost);
static int _readChoice(GWEN_DB_NODE *db, const char *n, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost);
static int _readText(AQCGI_OBJECT *o, GWEN_DB_NODE *dbPost);
/* ------------------------------------------------------------------------------------------------
* implementation
* ------------------------------------------------------------------------------------------------
*/
int AQCGI_ObjectHtml_toForm(const AQCGI_OBJECT *o, const AQCGI_OBJECT_DEF *odef, GWEN_BUFFER *dbuf)
{
const AQCGI_FIELD_DEF_LIST *fdefList;
uint32_t flags;
flags=AQCGI_ObjectDef_GetFlags(odef);
fdefList=AQCGI_ObjectDef_GetFieldDefList(odef);
if (fdefList && AQCGI_FieldDef_List_GetCount(fdefList)) {
const AQCGI_FIELD_DEF *fdef;
GBAS(dbuf,"<table>\n");
fdef=AQCGI_FieldDef_List_First(fdefList);
while(fdef) {
int rv;
rv=_fieldToForm(o, odef, fdef, dbuf);
if (rv<0) {
DBG_INFO(AQCGI_LOGDOMAIN, "here (%d)", rv);
return rv;
}
fdef=AQCGI_FieldDef_List_Next(fdef);
}
GBAS(dbuf,"</table>\n");
}
if (flags & AQCGI_OBJECT_FLAGS_HASTEXT)
_writeText(o, dbuf);
return 0;
}
int AQCGI_ObjectHtml_fromPostRq(AQCGI_OBJECT *o, const AQCGI_OBJECT_DEF *odef, GWEN_DB_NODE *dbPost)
{
const AQCGI_FIELD_DEF_LIST *fdefList;
uint32_t flags;
flags=AQCGI_ObjectDef_GetFlags(odef);
fdefList=AQCGI_ObjectDef_GetFieldDefList(odef);
if (fdefList && AQCGI_FieldDef_List_GetCount(fdefList)) {
const AQCGI_FIELD_DEF *fdef;
fdef=AQCGI_FieldDef_List_First(fdefList);
while(fdef) {
int rv;
rv=_fieldFromPostRq(o, odef, fdef, dbPost);
if (rv<0) {
DBG_INFO(AQCGI_LOGDOMAIN, "here (%d)", rv);
return rv;
}
fdef=AQCGI_FieldDef_List_Next(fdef);
}
}
if (flags & AQCGI_OBJECT_FLAGS_HASTEXT)
_readText(o, dbPost);
return 0;
}
int _fieldToForm(const AQCGI_OBJECT *o, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf)
{
GWEN_DB_NODE *db;
db=AQCGI_Object_GetVars(o);
if (db) {
int t;
int rv=GWEN_ERROR_GENERIC;
const char *sName;
const char *sLabel;
/* write label */
sName=AQCGI_FieldDef_GetName(fdef);
sLabel=AQCGI_FieldDef_GetLabel(fdef);
GBAA(dbuf, "<tr><td><label for\"%s\">%s</label></td><td>", sName?sName:"", sLabel?sLabel:"");
/* write field */
t=AQCGI_FieldDef_GetDataType(fdef);
switch(t) {
case AQCGI_ObjectFieldType_Unknown: rv=GWEN_ERROR_BAD_DATA; break;
case AQCGI_ObjectFieldType_Bool: rv=_writeBool(db, sName, odef, fdef, dbuf); break;
case AQCGI_ObjectFieldType_Int: rv=_writeInt(db, sName, odef, fdef, dbuf); break;
case AQCGI_ObjectFieldType_String: rv=_writeString(db, sName, odef, fdef, dbuf); break;
case AQCGI_ObjectFieldType_Date: rv=_writeDate(db, sName, odef, fdef, dbuf); break;
case AQCGI_ObjectFieldType_Choice: rv=_writeChoice(db, sName, odef, fdef, dbuf); break;
}
GBAS(dbuf, "</td></tr>\n");
return rv;
}
else {
DBG_ERROR(AQCGI_LOGDOMAIN, "No vars");
return GWEN_ERROR_NO_DATA;
}
}
int _writeBool(GWEN_DB_NODE *db, const char *sName, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf)
{
int v;
v=GWEN_DB_GetIntValue(db, sName, 0, 0);
GBAA(dbuf, "<input type=\"checkbox\" name=\"%s\" %s/>", sName, v?"checked":"");
return 0;
}
int _writeInt(GWEN_DB_NODE *db, const char *sName, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf)
{
int v;
uint32_t flags;
flags=AQCGI_FieldDef_GetFlags(fdef);
v=GWEN_DB_GetIntValue(db, sName, 0, 0);
GBAA(dbuf, "<input type=\"number\" name=\"%s\" value=\"%d\"", sName, v);
if (flags & AQCGI_FIELD_FLAGS_USEMIN)
GBAA(dbuf, " min=\"%d\"", AQCGI_FieldDef_GetMinValue(fdef));
if (flags & AQCGI_FIELD_FLAGS_USEMAX)
GBAA(dbuf, " max=\"%d\"", AQCGI_FieldDef_GetMaxValue(fdef));
if (flags & AQCGI_FIELD_FLAGS_REQUIRED)
GBAS(dbuf, " required");
GBAS(dbuf, "/>");
return 0;
}
int _writeString(GWEN_DB_NODE *db, const char *sName, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf)
{
const char *v;
uint32_t flags;
flags=AQCGI_FieldDef_GetFlags(fdef);
v=GWEN_DB_GetCharValue(db, sName, 0, NULL);
GBAA(dbuf, "<input type=\"text\" name=\"%s\" value=\"%s\"", sName, v?v:"");
if (flags & AQCGI_FIELD_FLAGS_USEMIN)
GBAA(dbuf, " minlength=\"%d\"", AQCGI_FieldDef_GetMinValue(fdef));
if (flags & AQCGI_FIELD_FLAGS_USEMAX)
GBAA(dbuf, " maxlength=\"%d\"", AQCGI_FieldDef_GetMaxValue(fdef));
if (flags & AQCGI_FIELD_FLAGS_REQUIRED)
GBAS(dbuf, " required");
GBAS(dbuf, "/>");
return 0;
}
int _writeDate(GWEN_DB_NODE *db, const char *sName, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf)
{
int64_t v;
GWEN_TIMESTAMP *ts;
GWEN_DATE *dt;
v=(int64_t) GWEN_DB_GetIntValue(db, sName, 0, 0);
ts=GWEN_Timestamp_fromInt64(v);
dt=ts?GWEN_Date_fromLocalTime(GWEN_Timestamp_toTimeT(ts)):GWEN_Date_CurrentDate();
GWEN_Timestamp_free(ts);
GBAA(dbuf, "<input type=\"date\" name=\"%s\" value=\"", sName);
GWEN_Date_toStringWithTemplate(dt, "YYYY-MM-DD", dbuf);
GBAS(dbuf, "\"/>");
GWEN_Date_free(dt);
return 0;
}
int _writeChoice(GWEN_DB_NODE *db, const char *sName, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_BUFFER *dbuf)
{
int v;
const char *sChoices;
v=GWEN_DB_GetIntValue(db, sName, 0, 0);
sChoices=AQCGI_FieldDef_GetChoices(fdef);
if (sChoices && *sChoices) {
GWEN_STRINGLIST *sl;
sl=GWEN_StringList_fromString2(sChoices, ";", 0, GWEN_TEXT_FLAGS_DEL_QUOTES | GWEN_TEXT_FLAGS_CHECK_BACKSLASH);
if (sl) {
GWEN_STRINGLISTENTRY *se;
int i=0;
GBAA(dbuf, "<td><select name=\"%s\">", sName?sName:"");
se=GWEN_StringList_FirstEntry(sl);
while(se) {
const char *s;
s=GWEN_StringListEntry_Data(se);
GBAA(dbuf, "<option value=\"%s\" %s>%s</option>", s, (i==v)?"selected":"", s);
i++;
se=GWEN_StringListEntry_Next(se);
}
GWEN_StringList_free(sl);
}
}
return 0;
}
int _writeText(const AQCGI_OBJECT *o, GWEN_BUFFER *dbuf)
{
const char *v;
v=AQCGI_Object_GetText(o);
GBAS(dbuf, "<textarea name=\"text\">");
if (v)
GBAS(dbuf, v);
GBAS(dbuf, "</textarea>\n");
return 0;
}
int _fieldFromPostRq(AQCGI_OBJECT *o, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost)
{
GWEN_DB_NODE *db;
int t;
int rv=GWEN_ERROR_GENERIC;
const char *sName;
db=AQCGI_Object_GetVars(o);
if (db==NULL) {
db=GWEN_DB_Group_new("vars");
AQCGI_Object_SetVars(o, db);
}
sName=AQCGI_FieldDef_GetName(fdef);
/* read field */
t=AQCGI_FieldDef_GetDataType(fdef);
switch(t) {
case AQCGI_ObjectFieldType_Unknown: rv=GWEN_ERROR_BAD_DATA; break;
case AQCGI_ObjectFieldType_Bool: rv=_readBool(db, sName, odef, fdef, dbPost); break;
case AQCGI_ObjectFieldType_Int: rv=_readInt(db, sName, odef, fdef, dbPost); break;
case AQCGI_ObjectFieldType_String: rv=_readString(db, sName, odef, fdef, dbPost); break;
case AQCGI_ObjectFieldType_Date: rv=_readDate(db, sName, odef, fdef, dbPost); break;
case AQCGI_ObjectFieldType_Choice: rv=_readChoice(db, sName, odef, fdef, dbPost); break;
}
return rv;
}
int _readBool(GWEN_DB_NODE *db, const char *sName, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost)
{
const char *v;
v=GWEN_DB_GetCharValue(dbPost, sName, 0, NULL);
GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, sName, v?1:0);
return 0;
}
int _readInt(GWEN_DB_NODE *db, const char *sName, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost)
{
int v;
v=GWEN_DB_GetIntValue(dbPost, sName, 0, 0);
GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, sName, v);
return 0;
}
int _readString(GWEN_DB_NODE *db, const char *sName, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost)
{
const char *v;
v=GWEN_DB_GetCharValue(dbPost, sName, 0, NULL);
if (v && *v)
GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, sName, v);
else
GWEN_DB_DeleteVar(db, sName);
return 0;
}
int _readDate(GWEN_DB_NODE *db, const char *sName, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost)
{
const char *v;
int64_t i=0;
v=GWEN_DB_GetCharValue(dbPost, sName, 0, NULL);
if (v && *v) {
GWEN_DATE *dt;
dt=GWEN_Date_fromStringWithTemplate(v, "YYYY-MM-DD");
if (dt) {
GWEN_TIMESTAMP *ts;
ts=GWEN_Timestamp_fromLocalTime(GWEN_Date_toLocalTime(dt));
i=ts?GWEN_Timestamp_toInt64(ts):0;
GWEN_Timestamp_free(ts);
GWEN_Date_free(dt);
}
}
GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, sName, i);
return 0;
}
int _readChoice(GWEN_DB_NODE *db, const char *sName, const AQCGI_OBJECT_DEF *odef, const AQCGI_FIELD_DEF *fdef, GWEN_DB_NODE *dbPost)
{
const char *v;
int i=0;
v=GWEN_DB_GetCharValue(dbPost, sName, 0, NULL);
if (v && *v) {
const char *sChoices;
sChoices=AQCGI_FieldDef_GetChoices(fdef);
if (sChoices && *sChoices) {
GWEN_STRINGLIST *sl;
sl=GWEN_StringList_fromString2(sChoices, ";", 0, GWEN_TEXT_FLAGS_DEL_QUOTES | GWEN_TEXT_FLAGS_CHECK_BACKSLASH);
if (sl) {
GWEN_STRINGLISTENTRY *se;
int i=0;
se=GWEN_StringList_FirstEntry(sl);
while(se) {
const char *s;
s=GWEN_StringListEntry_Data(se);
if (s && *s && strcasecmp(s, v)==0)
break;
i++;
se=GWEN_StringListEntry_Next(se);
}
GWEN_StringList_free(sl);
}
}
}
GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, sName, i);
return 0;
}
int _readText(AQCGI_OBJECT *o, GWEN_DB_NODE *dbPost)
{
const char *v;
v=GWEN_DB_GetCharValue(dbPost, "text", 0, NULL);
AQCGI_Object_SetText(o, v);
return 0;
}

View File

@@ -0,0 +1,24 @@
/****************************************************************************
* This file is part of the project AqCGI.
* AqCGI (c) by 2026 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 AQCGI_SERVICE_OBJECT_HTML_H
#define AQCGI_SERVICE_OBJECT_HTML_H
#include "aqcgi/service/object.h"
#include "aqcgi/service/objectdef.h"
AQCGI_API int AQCGI_ObjectHtml_toForm(const AQCGI_OBJECT *o, const AQCGI_OBJECT_DEF *odef, GWEN_BUFFER *dbuf);
AQCGI_API int AQCGI_ObjectHtml_fromPostRq(AQCGI_OBJECT *o, const AQCGI_OBJECT_DEF *odef, GWEN_DB_NODE *dbPost);
#endif

View File

@@ -0,0 +1,72 @@
<?xml?>
<tm2>
<type id="AQCGI_OBJECT_DEF" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQCGI_OBJECT_DEF</identifier>
<prefix>AQCGI_ObjectDef</prefix>
<baseFileName>objectdef</baseFileName>
<flags>
with_xml
with_db
with_list1
with_list2
</flags>
<headers>
<header type="sys" loc="pre">aqcgi/api.h</header>
<header type="sys" loc="pre">aqcgi/service/objectfielddef.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
</headers>
<inlines>
</inlines>
</lang>
<defines>
<define id="AQCGI_OBJECT_FLAGS" prefix="AQCGI_OBJECT_FLAGS_">
<item name="HASTEXT" value="0x00000001" />
</define>
</defines>
<members>
<member name="name" type="char_ptr" maxlen="16">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="label" type="char_ptr" maxlen="64">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="flags" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_flags</flags>
</member>
<member name="fieldDefList" type="AQCGI_FIELD_DEF_LIST" maxlen="4">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,124 @@
<?xml?>
<tm2>
<type id="AQCGI_FIELD_DEF" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQCGI_FIELD_DEF</identifier>
<prefix>AQCGI_FieldDef</prefix>
<baseFileName>objectfielddef</baseFileName>
<flags>
with_xml
with_db
with_list1
with_list2
</flags>
<headers>
<header type="sys" loc="pre">aqcgi/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
</headers>
<inlines>
</inlines>
</lang>
<defines>
<define id="AQCGI_FIELD_FLAGS" prefix="AQCGI_FIELD_FLAGS_">
<item name="IMMUTABLE" value="0x00000001" />
<item name="REQUIRED" value="0x00000002" />
<item name="USEMIN" value="0x00000004" />
<item name="USEMAX" value="0x00000008" />
</define>
</defines>
<enums>
<enum id="AQCGI_FIELD_TYPE" prefix="AQCGI_ObjectFieldType_">
<item name="bool">
<descr>boolean</descr>
</item>
<item name="int">
<descr>Integer</descr>
</item>
<item name="string">
<descr>string</descr>
</item>
<item name="date">
<descr>date</descr>
</item>
<item name="choice">
<descr>choice</descr>
</item>
</enum>
</enums>
<members>
<member name="name" type="char_ptr" maxlen="16">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own with_getbymember</flags>
</member>
<member name="label" type="char_ptr" maxlen="64">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="flags" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_flags</flags>
</member>
<member name="dataType" type="int" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
<member name="minValue" type="int" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
<member name="maxValue" type="int" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
<member name="choices" type="char_ptr" maxlen="256">
<descr>Semicolon separated list of choices</descr>
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,65 @@
<?xml?>
<tm2>
<type id="AQCGI_PERMDEF" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQCGI_PERMDEF</identifier>
<prefix>AQCGI_PermDef</prefix>
<baseFileName>permdef</baseFileName>
<flags>
with_xml
with_db
with_list1
nodup
nocopy
</flags>
<headers>
<header type="sys" loc="pre">aqcgi/api.h</header>
</headers>
<inlines>
</inlines>
</lang>
<members>
<member name="id" type="char_ptr" maxlen="32">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own with_getbymember</flags>
</member>
<member name="name" type="char_ptr" maxlen="32">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own with_getbymember</flags>
</member>
<member name="mask" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own with_getbymember</flags>
</member>
<member name="descr" type="char_ptr" maxlen="256">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
</member>
</members>
</type>
</tm2>

View File

@@ -0,0 +1,79 @@
<?xml?>
<tm2>
<type id="AQCGI_ROLE" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQCGI_ROLE</identifier>
<prefix>AQCGI_Role</prefix>
<baseFileName>role</baseFileName>
<flags>
with_xml
with_db
with_list1
with_list2
</flags>
<headers>
<header type="sys" loc="pre">aqcgi/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
</headers>
<inlines>
</inlines>
</lang>
<members>
<member name="id" type="uint8_t" maxlen="1">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember</flags>
</member>
<member name="name" type="char_ptr" maxlen="16">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="descr" type="char_ptr" maxlen="256">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="perms" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
<member name="explAddPerms" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
<member name="explDelPerms" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
</members>
</type>
</tm2>

432
src/aqcgi/service/service.c Normal file
View File

@@ -0,0 +1,432 @@
/****************************************************************************
* This file is part of the project AqCGI.
* AqCGI (c) by 2026 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 <config.h>
#endif
//#define DISABLE_DEBUGLOG
#include "aqcgi/service/service_p.h"
#include <gwenhywfar/stringlist.h>
#include <gwenhywfar/text.h>
#include <gwenhywfar/debug.h>
GWEN_INHERIT_FUNCTIONS(AQCGI_SERVICE);
GWEN_LIST_FUNCTIONS(AQCGI_SERVICE, AQCGI_Service);
AQCGI_SERVICE *AQCGI_Service_new(const char *baseFolder, const char *baseUrl)
{
AQCGI_SERVICE *sv;
GWEN_NEW_OBJECT(AQCGI_SERVICE, sv);
GWEN_INHERIT_INIT(AQCGI_SERVICE, sv);
GWEN_LIST_INIT(AQCGI_SERVICE, sv);
sv->baseUrl=baseUrl?strdup(baseUrl):NULL;
sv->baseFolder=baseFolder?strdup(baseFolder):NULL;
if (sv->baseFolder) {
GWEN_BUFFER *dbuf;
uint32_t pos;
dbuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendArgs(dbuf, "%s%s", sv->baseFolder, GWEN_DIR_SEPARATOR_S);
pos=GWEN_Buffer_GetPos(dbuf);
/* data folder */
GWEN_Buffer_AppendString(dbuf, "data");
sv->runtimeFolder=strdup(GWEN_Buffer_GetStart(dbuf));
DBG_ERROR(NULL, "Runtime folder: %s", GWEN_Buffer_GetStart(dbuf));
GWEN_Buffer_Crop(dbuf, 0, pos);
/* cache folder */
GWEN_Buffer_AppendString(dbuf, "cache");
sv->cacheFolder=strdup(GWEN_Buffer_GetStart(dbuf));
DBG_ERROR(NULL, "Cache folder: %s", GWEN_Buffer_GetStart(dbuf));
GWEN_Buffer_Crop(dbuf, 0, pos);
GWEN_Buffer_free(dbuf);
}
return sv;
}
void AQCGI_Service_free(AQCGI_SERVICE *sv)
{
if (sv) {
GWEN_LIST_FINI(AQCGI_SERVICE, sv);
GWEN_INHERIT_FINI(AQCGI_SERVICE, sv);
free(sv->baseUrl);
free(sv->baseFolder);
free(sv->runtimeFolder);
free(sv->cacheFolder);
free(sv->loginUrl);
GWEN_FREE_OBJECT(sv);
}
}
const char *AQCGI_Service_GetBaseUrl(const AQCGI_SERVICE *sv)
{
return sv?sv->baseUrl:NULL;
}
const char *AQCGI_Service_GetBaseFolder(const AQCGI_SERVICE *sv)
{
return sv?sv->baseFolder:NULL;
}
const char *AQCGI_Service_GetRuntimeFolder(const AQCGI_SERVICE *sv)
{
return sv?sv->runtimeFolder:NULL;
}
const char *AQCGI_Service_GetCacheFolder(const AQCGI_SERVICE *sv)
{
return sv?sv->cacheFolder:NULL;
}
const char *AQCGI_Service_GetLoginUrl(const AQCGI_SERVICE *sv)
{
return sv?sv->loginUrl:NULL;
}
void AQCGI_Service_SetLoginUrl(AQCGI_SERVICE *sv, const char *s)
{
if (sv) {
free(sv->loginUrl);
sv->loginUrl=s?strdup(s):NULL;
}
}
#if 0
AQCGI_MODULE *AQCGI_Service_GetModuleByPath(const AQCGI_SERVICE *sv, const char *s)
{
if (sv && s && *s) {
GWEN_STRINGLIST *sl;
sl=GWEN_StringList_fromString2(s, "/", 0,
GWEN_TEXT_FLAGS_DEL_QUOTES |
GWEN_TEXT_FLAGS_DEL_LEADING_BLANKS |
GWEN_TEXT_FLAGS_DEL_MULTIPLE_BLANKS |
GWEN_TEXT_FLAGS_DEL_TRAILING_BLANKS);
if (sl) {
GWEN_STRINGLISTENTRY *se;
AQCGI_MODULE *m;
m=sv->rootModule;
se=GWEN_StringList_FirstEntry(sl);
while(se && m) {
const char *sWantedName;
sWantedName=GWEN_StringListEntry_Data(se);
if (sWantedName && *sWantedName) {
AQCGI_MODULE *mTemp;
mTemp=AQCGI_Module_Tree2_GetFirstChild(m);
while(mTemp) {
const char *sModName;
sModName=AQCGI_Module_GetName(mTemp);
if (sModName && *sModName && 0==strcasecmp(sModName, sWantedName))
break;
mTemp=AQCGI_Module_Tree2_GetNext(mTemp);
}
if (mTemp==NULL) {
DBG_ERROR(NULL, "Module \%s\" not found", sWantedName);
GWEN_StringList_free(sl);
return NULL;
}
m=mTemp;
}
else {
DBG_ERROR(NULL, "Empty path element in \"%s\"", s);
GWEN_StringList_free(sl);
return NULL;
}
se=GWEN_StringListEntry_Next(se);
} /* while(se && m) */
GWEN_StringList_free(sl);
return m;
}
else {
DBG_ERROR(NULL, "Bad path \"%s\"", s);
}
}
return NULL;
}
#endif
int AQCGI_Service_HandleRequest(AQCGI_SERVICE *sv, AQCGI_REQUEST *req)
{
return (sv && sv->handleRequestFn)?(sv->handleRequestFn(sv, req)):GWEN_ERROR_NOT_IMPLEMENTED;
}
AQCGI_USER *AQCGI_Service_LoadUser(AQCGI_SERVICE *sv, const char *s)
{
return (sv && sv->loadUserFn)?(sv->loadUserFn(sv, s)):NULL;
}
int AQCGI_Service_SaveUser(AQCGI_SERVICE *sv, AQCGI_USER *user)
{
return (sv && sv->saveUserFn)?(sv->saveUserFn(sv, user)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQCGI_Service_AddUser(AQCGI_SERVICE *sv, AQCGI_USER *user)
{
return (sv && sv->addUserFn)?(sv->addUserFn(sv, user)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQCGI_Service_DelUser(AQCGI_SERVICE *sv, const char *s)
{
return (sv && sv->delUserFn)?(sv->delUserFn(sv, s)):GWEN_ERROR_NOT_IMPLEMENTED;
}
GWEN_STRINGLIST *AQCGI_Service_ListUsers(AQCGI_SERVICE *sv)
{
return (sv && sv->listUsersFn)?(sv->listUsersFn(sv)):NULL;
}
AQCGI_MODULE *AQCGI_Service_LoadModule(AQCGI_SERVICE *sv, const char *s)
{
return (sv && sv->loadModuleFn)?(sv->loadModuleFn(sv, s)):NULL;
}
int AQCGI_Service_SaveModule(AQCGI_SERVICE *sv, AQCGI_MODULE *module)
{
return (sv && sv->saveModuleFn)?(sv->saveModuleFn(sv, module)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQCGI_Service_AddModule(AQCGI_SERVICE *sv, AQCGI_MODULE *module)
{
return (sv && sv->addModuleFn)?(sv->addModuleFn(sv, module)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQCGI_Service_DelModule(AQCGI_SERVICE *sv, const char *s)
{
return (sv && sv->delModuleFn)?(sv->delModuleFn(sv, s)):GWEN_ERROR_NOT_IMPLEMENTED;
}
GWEN_STRINGLIST *AQCGI_Service_ListModules(AQCGI_SERVICE *sv)
{
return (sv && sv->listModulesFn)?(sv->listModulesFn(sv)):NULL;
}
AQCGI_SESSION* AQCGI_Service_LoadSession(AQCGI_SERVICE *sv, const char *s)
{
return (sv && sv->loadSessionFn)?(sv->loadSessionFn(sv, s)):NULL;
}
int AQCGI_Service_SaveSession(AQCGI_SERVICE *sv, AQCGI_SESSION *session)
{
return (sv && sv->saveSessionFn)?(sv->saveSessionFn(sv, session)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQCGI_Service_AddSession(AQCGI_SERVICE *sv, AQCGI_SESSION *session)
{
return (sv && sv->addSessionFn)?(sv->addSessionFn(sv, session)):GWEN_ERROR_NOT_IMPLEMENTED;
}
int AQCGI_Service_DelSession(AQCGI_SERVICE *sv, const char *s)
{
return (sv && sv->delSessionFn)?(sv->delSessionFn(sv, s)):GWEN_ERROR_NOT_IMPLEMENTED;
}
void AQCGI_Service_SetHandleRequestFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_HANDLEREQUEST_FN f)
{
if (sv)
sv->handleRequestFn=f;
}
void AQCGI_Service_SetLoadUserFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LOADUSER_FN f)
{
if (sv)
sv->loadUserFn=f;
}
void AQCGI_Service_SetSaveUserFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_SAVEUSER_FN f)
{
if (sv)
sv->saveUserFn=f;
}
void AQCGI_Service_SetAddUserFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_ADDUSER_FN f)
{
if (sv)
sv->addUserFn=f;
}
void AQCGI_Service_SetDelUserFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_DELUSER_FN f)
{
if (sv)
sv->delUserFn=f;
}
void AQCGI_Service_SetListUsersFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LISTUSERS_FN f)
{
if (sv)
sv->listUsersFn=f;
}
void AQCGI_Service_SetLoadModuleFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LOADMODULE_FN f)
{
if (sv)
sv->loadModuleFn=f;
}
void AQCGI_Service_SetSaveModuleFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_SAVEMODULE_FN f)
{
if (sv)
sv->saveModuleFn=f;
}
void AQCGI_Service_SetAddModuleFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_ADDMODULE_FN f)
{
if (sv)
sv->addModuleFn=f;
}
void AQCGI_Service_SetDelModuleFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_DELMODULE_FN f)
{
if (sv)
sv->delModuleFn=f;
}
void AQCGI_Service_SetListModulesFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LISTMODULES_FN f)
{
if (sv)
sv->listModulesFn=f;
}
void AQCGI_Service_SetLoadSessionFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LOADSESSION_FN f)
{
if (sv)
sv->loadSessionFn=f;
}
void AQCGI_Service_SetSaveSessionFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_SAVESESSION_FN f)
{
if (sv)
sv->saveSessionFn=f;
}
void AQCGI_Service_SetAddSessionFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_ADDSESSION_FN f)
{
if (sv)
sv->addSessionFn=f;
}
void AQCGI_Service_SetDelSessionFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_DELSESSION_FN f)
{
if (sv)
sv->delSessionFn=f;
}
void AQCGI_Service_SetListSessionsFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LISTSESSIONS_FN f)
{
if (sv)
sv->listSessionsFn=f;
}

109
src/aqcgi/service/service.h Normal file
View File

@@ -0,0 +1,109 @@
/****************************************************************************
* This file is part of the project AqCGI.
* AqCGI (c) by 2026 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 AQCGI_SERVICE_SERVICE_H
#define AQCGI_SERVICE_SERVICE_H
#include <aqcgi/api.h>
#include <gwenhywfar/inherit.h>
#include <gwenhywfar/list.h>
#include <gwenhywfar/stringlist.h>
typedef struct AQCGI_SERVICE AQCGI_SERVICE;
GWEN_INHERIT_FUNCTION_LIB_DEFS(AQCGI_SERVICE, AQCGI_API);
GWEN_LIST_FUNCTION_LIB_DEFS(AQCGI_SERVICE, AQCGI_Service, AQCGI_API);
#include "aqcgi/service/user.h"
#include "aqcgi/service/module.h"
#include "aqcgi/service/session.h"
#include <aqcgi/cgi.h>
typedef int (*AQCGI_SERVICE_HANDLEREQUEST_FN)(AQCGI_SERVICE *sv, AQCGI_REQUEST *req);
typedef AQCGI_USER* (*AQCGI_SERVICE_LOADUSER_FN)(AQCGI_SERVICE *sv, const char *s);
typedef int (*AQCGI_SERVICE_SAVEUSER_FN)(AQCGI_SERVICE *sv, AQCGI_USER *user);
typedef int (*AQCGI_SERVICE_ADDUSER_FN)(AQCGI_SERVICE *sv, AQCGI_USER *user);
typedef int (*AQCGI_SERVICE_DELUSER_FN)(AQCGI_SERVICE *sv, const char *s);
typedef GWEN_STRINGLIST* (*AQCGI_SERVICE_LISTUSERS_FN)(AQCGI_SERVICE *sv);
typedef AQCGI_MODULE* (*AQCGI_SERVICE_LOADMODULE_FN)(AQCGI_SERVICE *sv, const char *s);
typedef int (*AQCGI_SERVICE_SAVEMODULE_FN)(AQCGI_SERVICE *sv, AQCGI_MODULE *module);
typedef int (*AQCGI_SERVICE_ADDMODULE_FN)(AQCGI_SERVICE *sv, AQCGI_MODULE *module);
typedef int (*AQCGI_SERVICE_DELMODULE_FN)(AQCGI_SERVICE *sv, const char *s);
typedef GWEN_STRINGLIST* (*AQCGI_SERVICE_LISTMODULES_FN)(AQCGI_SERVICE *sv);
typedef AQCGI_SESSION* (*AQCGI_SERVICE_LOADSESSION_FN)(AQCGI_SERVICE *sv, const char *s);
typedef int (*AQCGI_SERVICE_SAVESESSION_FN)(AQCGI_SERVICE *sv, AQCGI_SESSION *session);
typedef int (*AQCGI_SERVICE_ADDSESSION_FN)(AQCGI_SERVICE *sv, AQCGI_SESSION *session);
typedef int (*AQCGI_SERVICE_DELSESSION_FN)(AQCGI_SERVICE *sv, const char *s);
typedef GWEN_STRINGLIST* (*AQCGI_SERVICE_LISTSESSIONS_FN)(AQCGI_SERVICE *sv);
AQCGI_API AQCGI_SERVICE *AQCGI_Service_new(const char *baseFolder, const char *baseUrl);
AQCGI_API void AQCGI_Service_free(AQCGI_SERVICE *sv);
AQCGI_API const char *AQCGI_Service_GetBaseUrl(const AQCGI_SERVICE *sv);
AQCGI_API const char *AQCGI_Service_GetLoginUrl(const AQCGI_SERVICE *sv);
AQCGI_API void AQCGI_Service_SetLoginUrl(AQCGI_SERVICE *sv, const char *s);
AQCGI_API const char *AQCGI_Service_GetBaseFolder(const AQCGI_SERVICE *sv);
AQCGI_API const char *AQCGI_Service_GetRuntimeFolder(const AQCGI_SERVICE *sv);
AQCGI_API const char *AQCGI_Service_GetCacheFolder(const AQCGI_SERVICE *sv);
AQCGI_API int AQCGI_Service_HandleRequest(AQCGI_SERVICE *sv, AQCGI_REQUEST *req);
AQCGI_API AQCGI_USER *AQCGI_Service_LoadUser(AQCGI_SERVICE *sv, const char *s);
AQCGI_API int AQCGI_Service_SaveUser(AQCGI_SERVICE *sv, AQCGI_USER *user);
AQCGI_API int AQCGI_Service_AddUser(AQCGI_SERVICE *sv, AQCGI_USER *user);
AQCGI_API int AQCGI_Service_DelUser(AQCGI_SERVICE *sv, const char *s);
AQCGI_API GWEN_STRINGLIST *AQCGI_Service_ListUsers(AQCGI_SERVICE *sv);
AQCGI_API AQCGI_MODULE *AQCGI_Service_LoadModule(AQCGI_SERVICE *sv, const char *s);
AQCGI_API int AQCGI_Service_SaveModule(AQCGI_SERVICE *sv, AQCGI_MODULE *module);
AQCGI_API int AQCGI_Service_AddModule(AQCGI_SERVICE *sv, AQCGI_MODULE *module);
AQCGI_API int AQCGI_Service_DelModule(AQCGI_SERVICE *sv, const char *s);
AQCGI_API GWEN_STRINGLIST *AQCGI_Service_ListModules(AQCGI_SERVICE *sv);
AQCGI_API AQCGI_SESSION* AQCGI_Service_LoadSession(AQCGI_SERVICE *sv, const char *s);
AQCGI_API int AQCGI_Service_SaveSession(AQCGI_SERVICE *sv, AQCGI_SESSION *session);
AQCGI_API int AQCGI_Service_AddSession(AQCGI_SERVICE *sv, AQCGI_SESSION *session);
AQCGI_API int AQCGI_Service_DelSession(AQCGI_SERVICE *sv, const char *s);
AQCGI_API GWEN_STRINGLIST *AQCGI_Service_ListSessions(AQCGI_SERVICE *sv);
AQCGI_API void AQCGI_Service_SetHandleRequestFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_HANDLEREQUEST_FN f);
AQCGI_API void AQCGI_Service_SetLoadUserFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LOADUSER_FN f);
AQCGI_API void AQCGI_Service_SetSaveUserFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_SAVEUSER_FN f);
AQCGI_API void AQCGI_Service_SetAddUserFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_ADDUSER_FN f);
AQCGI_API void AQCGI_Service_SetDelUserFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_DELUSER_FN f);
AQCGI_API void AQCGI_Service_SetListUsersFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LISTUSERS_FN f);
AQCGI_API void AQCGI_Service_SetLoadModuleFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LOADMODULE_FN f);
AQCGI_API void AQCGI_Service_SetSaveModuleFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_SAVEMODULE_FN f);
AQCGI_API void AQCGI_Service_SetAddModuleFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_ADDMODULE_FN f);
AQCGI_API void AQCGI_Service_SetDelModuleFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_DELMODULE_FN f);
AQCGI_API void AQCGI_Service_SetListModulesFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LISTMODULES_FN f);
AQCGI_API void AQCGI_Service_SetLoadSessionFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LOADSESSION_FN f);
AQCGI_API void AQCGI_Service_SetSaveSessionFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_SAVESESSION_FN f);
AQCGI_API void AQCGI_Service_SetAddSessionFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_ADDSESSION_FN f);
AQCGI_API void AQCGI_Service_SetDelSessionFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_DELSESSION_FN f);
AQCGI_API void AQCGI_Service_SetListSessionsFn(AQCGI_SERVICE *sv, AQCGI_SERVICE_LISTSESSIONS_FN f);
#endif

View File

@@ -0,0 +1,52 @@
/****************************************************************************
* This file is part of the project AqCGI.
* AqCGI (c) by 2026 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 AQCGI_SERVICE_SERVICE_P_H
#define AQCGI_SERVICE_SERVICE_P_H
#include "aqcgi/service/service.h"
struct AQCGI_SERVICE {
GWEN_INHERIT_ELEMENT(AQCGI_SERVICE);
GWEN_LIST_ELEMENT(AQCGI_SERVICE);
char *baseUrl;
char *baseFolder;
char *runtimeFolder;
char *cacheFolder;
char *loginUrl;
AQCGI_SERVICE_HANDLEREQUEST_FN handleRequestFn;
AQCGI_SERVICE_LOADUSER_FN loadUserFn;
AQCGI_SERVICE_SAVEUSER_FN saveUserFn;
AQCGI_SERVICE_ADDUSER_FN addUserFn;
AQCGI_SERVICE_DELUSER_FN delUserFn;
AQCGI_SERVICE_LISTUSERS_FN listUsersFn;
AQCGI_SERVICE_LOADMODULE_FN loadModuleFn;
AQCGI_SERVICE_SAVEMODULE_FN saveModuleFn;
AQCGI_SERVICE_ADDMODULE_FN addModuleFn;
AQCGI_SERVICE_DELMODULE_FN delModuleFn;
AQCGI_SERVICE_LISTMODULES_FN listModulesFn;
AQCGI_SERVICE_LOADSESSION_FN loadSessionFn;
AQCGI_SERVICE_SAVESESSION_FN saveSessionFn;
AQCGI_SERVICE_ADDSESSION_FN addSessionFn;
AQCGI_SERVICE_DELSESSION_FN delSessionFn;
AQCGI_SERVICE_LISTSESSIONS_FN listSessionsFn;
};
#endif

View File

@@ -0,0 +1,117 @@
<?xml?>
<tm2>
<type id="AQCGI_SESSION" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQCGI_SESSION</identifier>
<prefix>AQCGI_Session</prefix>
<baseFileName>session</baseFileName>
<flags>
with_xml
with_db
with_list1
with_list2
nodup
nocopy
</flags>
<headers>
<header type="sys" loc="pre">aqcgi/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
<header type="sys" loc="pre">gwenhywfar/timestamp.h</header>
<header type="sys" loc="post">aqcgi/service/user.h</header>
</headers>
<inlines>
</inlines>
</lang>
<defines>
<define id="AQCGI_SESSION_RTFLAGS" prefix="AQCGI_SESSION_RTFLAGS_">
<item name="MODIFIED" value="0x00000001" />
</define>
</defines>
<members>
<member name="uid" type="char_ptr" maxlen="64">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own with_getbymember</flags>
</member>
<member name="flags" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_flags</flags>
</member>
<member name="userAlias" type="char_ptr" maxlen="64">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="state" type="int" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags></flags>
</member>
<member name="tempToken" type="char_ptr" maxlen="64">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="timestampCreation" type="gwen_timestamp" maxlen="8">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="timestampLastAccess" type="gwen_timestamp" maxlen="8">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="user" type="AQCGI_USER">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<setflags>assign</setflags>
<getflags>none</getflags>
<flags>volatile nodup nocopy</flags>
</member>
<member name="runtimeFlags" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_flags volatile</flags>
</member>
</members>
</type>
</tm2>

171
src/aqcgi/service/user.t2d Normal file
View File

@@ -0,0 +1,171 @@
<?xml?>
<tm2>
<type id="AQCGI_USER" type="pointer">
<descr>
</descr>
<lang id="c">
<identifier>AQCGI_USER</identifier>
<prefix>AQCGI_User</prefix>
<baseFileName>user</baseFileName>
<flags>
with_xml
with_db
with_list1
with_list2
with_refcount
nodup
nocopy
</flags>
<headers>
<header type="sys" loc="pre">aqcgi/api.h</header>
<header type="sys" loc="pre">gwenhywfar/error.h</header>
<header type="sys" loc="pre">gwenhywfar/timestamp.h</header>
<header type="sys" loc="post">aqcgi/service/moduleperms.h</header>
</headers>
<inlines>
</inlines>
</lang>
<defines>
<define id="AQCGI_USER_FLAGS" prefix="AQCGI_USER_FLAGS_">
<item name="ADMIN" value="0x00000001" />
</define>
<define id="AQCGI_USER_RTFLAGS" prefix="AQCGI_USER_RTFLAGS_">
<item name="MODIFIED" value="0x00000001" />
<item name="PERMSCALC" value="0x00000002" />
</define>
</defines>
<enums>
<enum id="AQCGI_USER_STATE" prefix="AQCGI_UserState_">
<item name="suspended">
<descr>User suspended</descr>
</item>
<item name="waitForConfirmation">
<descr>Waiting for email confirmation</descr>
</item>
<item name="waitForApproval">
<descr>Waiting for approval by admin</descr>
</item>
<item name="active">
<descr>User active</descr>
</item>
</enum>
</enums>
<members>
<member name="id" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_getbymember sortbymember</flags>
</member>
<member name="flags" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>with_flags</flags>
</member>
<member name="state" type="int" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>sortbymember</flags>
</member>
<member name="name" type="char_ptr" maxlen="16">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own sortbymember</flags>
</member>
<member name="alias" type="char_ptr" maxlen="16">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own with_getbymember sortbymember</flags>
</member>
<member name="lang" type="char_ptr" maxlen="16">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="hashedPassword" type="char_ptr" maxlen="128">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="email" type="char_ptr" maxlen="128">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own with_getbymember sortbymember</flags>
</member>
<member name="notes" type="char_ptr" maxlen="256">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>own</flags>
</member>
<member name="timestampCreation" type="gwen_timestamp" maxlen="8">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own sortbymember</flags>
</member>
<member name="timestampLastLogin" type="gwen_timestamp" maxlen="8">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<flags>own sortbymember</flags>
</member>
<member name="modulePermList" type="AQCGI_MODULE_PERMS_LIST">
<default>NULL</default>
<preset>NULL</preset>
<access>public</access>
<getflags>none</getflags>
<setflags>none</setflags>
<flags>own</flags>
</member>
<member name="runtimeFlags" type="uint32_t" maxlen="4">
<default>0</default>
<preset>0</preset>
<access>public</access>
<flags>volatile with_flags</flags>
</member>
</members>
</type>
</tm2>