addd urlhandler for static content, more reusing of code.

This commit is contained in:
Martin Preuss
2023-08-10 01:45:12 +02:00
parent b9a54b8ffb
commit 9b0122e34c
13 changed files with 624 additions and 31 deletions

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ aqhome.log
aqhomed.vg
aqhome-mqttlog.vg
aqhome-storage.vg
aqhome-storage.pid

View File

@@ -45,6 +45,8 @@
cleanup.h
u_login.h
u_rooms.h
u_static.h
u_static_p.h
aqhomehttp.h
aqhomehttp_p.h
</headers>
@@ -61,6 +63,7 @@
cleanup.c
u_login.c
u_rooms.c
u_static.c
main.c
aqhomehttp.c
</sources>

View File

@@ -32,6 +32,7 @@
#define AQHOME_STORAGE_SITEHEADER "site-header.html"
#define AQHOME_STORAGE_SITEFOOTER "site-footer.html"
#define AQHOME_STORAGE_STATIC_RELFOLDER "static"
struct AQHOME_STORAGE {

View File

@@ -16,6 +16,7 @@
#include "./aqhomehttp.h"
#include "./u_login.h"
#include "./u_rooms.h"
#include "./u_static.h"
#include "aqhome/msg/endpoint_tty.h"
#include "aqhome/ipc/endpoint_ipc.h"
@@ -72,6 +73,7 @@ static GWEN_MSG_ENDPOINT *_acceptHttpFn(GWEN_MSG_ENDPOINT *ep, GWEN_SOCKET *sk,
static int _createUrlHandler_login(AQHOME_STORAGE *aqh);
static int _createUrlHandler_rooms(AQHOME_STORAGE *aqh);
static int _createUrlHandler_static(AQHOME_STORAGE *aqh);
@@ -116,6 +118,12 @@ int AqHomeStorage_SetupHttp(AQHOME_STORAGE *aqh, GWEN_DB_NODE *dbArgs)
return rv;
}
rv=_createUrlHandler_static(aqh);
if (rv<0) {
DBG_INFO(NULL, "here (%d)", rv);
return rv;
}
}
return 0;
}
@@ -241,4 +249,24 @@ int _createUrlHandler_rooms(AQHOME_STORAGE *aqh)
int _createUrlHandler_static(AQHOME_STORAGE *aqh)
{
AQH_HTTP_URLHANDLER *uh;
GWEN_BUFFER *nameBuf;
const char *sourceFolder;
sourceFolder=AQH_HttpService_GetSourceFolder(aqh->httpService);
nameBuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendString(nameBuf, sourceFolder);
GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S AQHOME_STORAGE_STATIC_RELFOLDER GWEN_DIR_SEPARATOR_S "pics");
uh=AQH_StaticHttpUrlHandler_new(aqh->httpService, GWEN_Buffer_GetStart(nameBuf));
GWEN_Buffer_free(nameBuf);
AQH_HttpUrlHandler_AddUrlPattern(uh, "/pics/*");
AQH_HttpService_AddUrlHandler(aqh->httpService, uh);
return 0;
}

View File

@@ -42,9 +42,13 @@ 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 *_addRoomCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq);
static GWEN_MSG *_editRoomCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id);
@@ -125,6 +129,8 @@ GWEN_MSG *_handleGet(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
_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);
@@ -170,6 +176,8 @@ GWEN_MSG *_handlePost(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
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);
@@ -207,7 +215,7 @@ void _handleGetList(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *
"<h2>%s</h2>"
"<table class=\"dataTable\">"
"<thead>"
" <tr><th>Id</th><th>%s</th><th>%s</th></tr>"
" <tr><th>Id</th><th>%s</th><th>%s</th><th></th></tr>"
"</thead>",
I18N("Rooms"),
I18N("Name"),
@@ -226,10 +234,15 @@ void _handleGetList(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *
id=(long unsigned int) AQH_Room_GetId(r);
name=AQH_Room_GetName(r);
descr=AQH_Room_GetDescription(r);
GWEN_Buffer_AppendArgs(pageBuf, "<tr><td>%lu</td><td>%s</td><td>%s</td></tr>", id, name?name:"", descr?descr:"");
GWEN_Buffer_AppendArgs(pageBuf,
"<tr><td>%lu</td><td>%s</td><td>%s</td>"
"<td><a href=\"/rooms/edit/%lu\">"
"<IMG src=\"/pics/edit.png\" width=32 height=32 align=left border=0></a></td>"
"</tr>",
id, name?name:"", descr?descr:"", id);
r=AQH_Room_List_Next(r);
}
r=AQH_Room_List_Next(r);
}
}
GWEN_Buffer_AppendString(pageBuf, "</tbody>");
GWEN_Buffer_AppendArgs(pageBuf, "</table><a href=\"/rooms/add\">%s</a><br>", I18N("Add Room"));
@@ -256,7 +269,61 @@ void _handleGetAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_BUFFER *p
}
else {
DBG_INFO(NULL, "No permissions to add a room.");
GWEN_Buffer_AppendString(pageBuf, "<p>No permissions to add a room.</p>");
GWEN_Buffer_AppendArgs(pageBuf, "<p><font color=\"red\">%s</font></p>", 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 (sto) {
if (id>0) {
const AQH_ROOM *r;
r=AQH_Storage_GetRoomById(sto, id);
if (r) {
GWEN_DB_NODE *db;
int rv;
db=GWEN_DB_Group_new("room");
rv=AQH_Room_toDb(r, db);
if (rv>=0)
_writeEditPage(uh, rq, NULL, pageBuf);
else {
DBG_ERROR(NULL, "Error writing room %d to db", id);
GWEN_Buffer_AppendArgs(pageBuf, "<p><font color=\"red\">%s</font></p>", I18N("Internal error."));
}
GWEN_DB_Group_free(db);
}
else {
DBG_ERROR(NULL, "Room %d not found", id);
GWEN_Buffer_AppendArgs(pageBuf, "<p><font color=\"red\">%s</font></p>", I18N("Room not found."));
}
}
else {
DBG_ERROR(NULL, "Missing room id");
GWEN_Buffer_AppendArgs(pageBuf, "<p><font color=\"red\">%s</font></p>", I18N("Missing or invalid room id."));
}
}
else {
DBG_ERROR(NULL, "No storage");
GWEN_Buffer_AppendArgs(pageBuf, "<p><font color=\"red\">%s</font></p>", I18N("Internal error."));
}
}
else {
DBG_INFO(NULL, "No permissions to edit a room.");
GWEN_Buffer_AppendArgs(pageBuf, "<p>%s</p>", I18N("No permissions to edit a room."));
}
}
@@ -297,6 +364,44 @@ int _writeAddPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *d
int _writeEditPage(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, GWEN_DB_NODE *dbValues, GWEN_BUFFER *pageBuf)
{
unsigned long int id;
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,
"<h2>%s</h2><br>\n"
"<form action=\"/rooms/edit/%lu\" method=\"post\" enctype=\"application/x-www-form-urlencoded\">"
" <table>"
" <tr>"
" <td><label for=\"name\">%s: </label></td>"
" <td><input type=\"text\" name=\"name\" value=\"%s\" required></td>"
" </tr>"
" <tr>"
" <td><label for=\"description\">%s: </label></td>"
" <td><input type=\"text\" name=\"description\" value=\"%s\" ></td>"
" </tr>"
" </table>"
" <input type=\"submit\" value=\"%s\">"
"</form>",
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;
@@ -325,6 +430,34 @@ GWEN_MSG *_handlePostAdd(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
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_ADD_ROOM) {
AQH_STORAGE *sto;
sto=AqHomeHttpService_GetStorage(sv);
if (sto) {
return _editRoomCreateResponse(uh, rq, id);
}
else {
DBG_ERROR(NULL, "No storage");
return AQH_HttpService_CreateResponseMsg(sv, 500, "Internal error", protocol, NULL);
}
}
else {
return AQH_HttpService_CreateResponseMsg(sv, 403, "Forbidden", protocol, NULL);
}
}
GWEN_MSG *_addRoomCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
{
AQH_SERVICE *sv;
@@ -382,4 +515,62 @@ GWEN_MSG *_addRoomCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq)
GWEN_MSG *_editRoomCreateResponse(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_REQUEST *rq, int id)
{
AQH_SERVICE *sv;
const char *protocol;
GWEN_DB_NODE *db;
const char *roomName;
const char *roomDescr;
AQH_STORAGE *sto;
sv=AQH_HttpUrlHandler_GetHttpService(uh);
protocol=AQH_HttpRequest_GetProtocol(rq);
db=AQH_HttpRequest_GetDbPostBody(rq);
roomName=GWEN_DB_GetCharValue(db, "name", 0, NULL);
roomDescr=GWEN_DB_GetCharValue(db, "description", 0, NULL);
if (!(roomName && *roomName)) {
DBG_INFO(NULL, "Missing room name");
return AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Missing room name"), 1, db, _writeAddPage);
}
sto=AqHomeHttpService_GetStorage(sv);
if (sto) {
AQH_ROOM *r;
int rv;
rv=AqHomeHttpService_LockStorage(sv);
if (rv<0) {
DBG_ERROR(NULL, "Error locking storage");
return AQH_HttpService_CreateResponseMsg(sv, 500, "Internal error", protocol, NULL);
}
r=AQH_Storage_GetRoomById(sto, id);
if (r==NULL) {
AqHomeHttpService_UnlockStorage(sv);
DBG_ERROR(NULL, "Room %d not found", id);
return AQH_HttpUrlHandler_CreatePageMessage(uh, rq, "red", I18N("Room not found"), 1, db, _writeEditPage);
}
/* edit room */
AQH_Room_SetName(r, roomName);
if (roomDescr && *roomDescr)
AQH_Room_SetDescription(r, roomDescr);
AQH_Storage_AddRuntimeFlags(sto, AQH_STORAGE_RTFLAGS_MODIFIED);
rv=AqHomeHttpService_UnlockStorage(sv);
if (rv<0) {
DBG_ERROR(NULL, "Error unlocking storage");
return AQH_HttpService_CreateResponseMsg(sv, 500, "Internal error", protocol, NULL);
}
return AQH_HttpService_CreateRedirectingResponseMsg(sv, protocol, "/rooms/list");
}
else
return AQH_HttpService_CreateResponseMsg(sv, 500, "Internal error", protocol, NULL);
}

View File

@@ -0,0 +1,291 @@
/****************************************************************************
* 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 <config.h>
#endif
#include "./u_static_p.h"
#include "./aqhomehttp.h"
#include "aqhome/http/httpservice.h"
#include "aqhome/http/httpservice_http.h"
#include "aqhome/http/httpservice_conf.h"
#include <gwenhywfar/gwenhywfar.h>
#include <gwenhywfar/debug.h>
#include <gwenhywfar/i18n.h>
GWEN_INHERIT(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_STATIC);
/* ------------------------------------------------------------------------------------------------
* defines
* ------------------------------------------------------------------------------------------------
*/
/* ------------------------------------------------------------------------------------------------
* 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 void _readFileList(AQH_HTTP_URLHANDLER *uh);
static GWEN_BUFFER *_readFileIntoBuffer(AQH_HTTP_URLHANDLER *uh, const char *requestedFilename);
static const char *_getContentTypeFromFilename(const char *filename);
static GWEN_MSG *_createFileResponseMsg(AQH_HTTP_URLHANDLER *uh,
const char *protocol,
const char *contentType,
const uint8_t *ptr, uint32_t len);
/* ------------------------------------------------------------------------------------------------
* implementations
* ------------------------------------------------------------------------------------------------
*/
AQH_HTTP_URLHANDLER *AQH_StaticHttpUrlHandler_new(AQH_SERVICE *sv, const char *folder)
{
AQH_HTTP_URLHANDLER *uh;
AQH_URLHANDLER_STATIC *xuh;
uh=AQH_HttpUrlHandler_new(sv);
GWEN_NEW_OBJECT(AQH_URLHANDLER_STATIC, xuh);
GWEN_INHERIT_SETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_STATIC, uh, xuh, _freeData);
AQH_HttpUrlHandler_SetFolder(uh, folder);
AQH_HttpUrlHandler_SetHandleFn(uh, _handleUrl);
_readFileList(uh);
return uh;
}
void _freeData(void *bp, void *p)
{
AQH_URLHANDLER_STATIC *xuh;
xuh=(AQH_URLHANDLER_STATIC*)p;
GWEN_StringList_free(xuh->fileList);
GWEN_FREE_OBJECT(xuh);
}
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 {
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)
{
AQH_URLHANDLER_STATIC *xuh;
AQH_SERVICE *sv;
const char *protocol;
const GWEN_STRINGLIST *sl;
xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_STATIC, uh);
if (xuh==NULL) {
DBG_ERROR(NULL, "Not a AQH_URLHANDLER_STATIC object");
return NULL;
}
sv=AQH_HttpUrlHandler_GetHttpService(uh);
protocol=AQH_HttpRequest_GetProtocol(rq);
/* 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)) {
DBG_ERROR(NULL, "Invalid url (2nd member is [%s])", s);
return AQH_HttpService_CreateResponseMsg(sv, 404, "Not found", protocol, NULL);
}
else {
GWEN_BUFFER *fileBuf;
const char *contentType;
GWEN_MSG *msgOut;
contentType=_getContentTypeFromFilename(s);
DBG_INFO(NULL, "Reading file \"%s\" (%s)", s, contentType);
fileBuf=_readFileIntoBuffer(uh, s);
if (fileBuf==NULL) {
DBG_INFO(NULL, "here");
return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 404, "Not found", protocol, NULL);
}
msgOut=_createFileResponseMsg(uh, protocol, contentType,
(const uint8_t*) GWEN_Buffer_GetStart(fileBuf), GWEN_Buffer_GetUsedBytes(fileBuf));
GWEN_Buffer_free(fileBuf);
return msgOut;
}
}
else {
DBG_ERROR(NULL, "No list of url members");
return AQH_HttpService_CreateResponseMsg(AQH_HttpUrlHandler_GetHttpService(uh), 500, "Internal Error", protocol, NULL);
}
}
void _readFileList(AQH_HTTP_URLHANDLER *uh)
{
AQH_URLHANDLER_STATIC *xuh;
const char *folder;
xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_STATIC, uh);
GWEN_StringList_free(xuh->fileList);
xuh->fileList=NULL;
folder=AQH_HttpUrlHandler_GetFolder(uh);
if (folder && *folder) {
GWEN_STRINGLIST *fileList;
fileList=AQH_HttpService_GetFolderFileList(folder, NULL, 1);
if (fileList) {
GWEN_StringList_RemoveString(fileList, ".");
GWEN_StringList_RemoveString(fileList, "..");
GWEN_StringList_free(xuh->fileList);
xuh->fileList=fileList;
}
else {
DBG_INFO(NULL, "No file list (empty folder?)");
}
}
}
GWEN_BUFFER *_readFileIntoBuffer(AQH_HTTP_URLHANDLER *uh, const char *requestedFilename)
{
AQH_URLHANDLER_STATIC *xuh;
const char *folder;
xuh=GWEN_INHERIT_GETDATA(AQH_HTTP_URLHANDLER, AQH_URLHANDLER_STATIC, uh);
folder=AQH_HttpUrlHandler_GetFolder(uh);
if (!(xuh->fileList && GWEN_StringList_Count(xuh->fileList)>0)) {
DBG_INFO(NULL, "Reading file list for folder \"%s\"", folder);
_readFileList(uh);
}
if (!(xuh->fileList && GWEN_StringList_Count(xuh->fileList)>0)) {
DBG_INFO(NULL, "No file list (empty or missing/bad folder? Permissions?");
return NULL;
}
if (GWEN_StringList_HasString(xuh->fileList, requestedFilename)) {
GWEN_BUFFER *nameBuf;
GWEN_BUFFER *fileBuf;
int rv;
fileBuf=GWEN_Buffer_new(0, 1024, 0, 1);
nameBuf=GWEN_Buffer_new(0, 256, 0, 1);
GWEN_Buffer_AppendString(nameBuf, folder);
GWEN_Buffer_AppendString(nameBuf, GWEN_DIR_SEPARATOR_S);
GWEN_Buffer_AppendString(nameBuf, requestedFilename);
DBG_INFO(NULL, "Reading file \"%s\"", GWEN_Buffer_GetStart(nameBuf));
rv=GWEN_SyncIo_Helper_ReadFile(GWEN_Buffer_GetStart(nameBuf), fileBuf);
if (rv<0) {
DBG_ERROR(NULL, "Error reading file \"%s\" (%d)", GWEN_Buffer_GetStart(nameBuf), rv);
GWEN_Buffer_free(nameBuf);
GWEN_Buffer_free(fileBuf);
return NULL;
}
GWEN_Buffer_free(nameBuf);
return fileBuf;
}
else {
DBG_INFO(NULL, "File \"%s\" not found in folder \"%s\"", requestedFilename, folder);
return NULL;
}
}
GWEN_MSG *_createFileResponseMsg(AQH_HTTP_URLHANDLER *uh,
const char *protocol,
const char *contentType,
const uint8_t *ptr, uint32_t len)
{
GWEN_BUFFER *buf;
GWEN_MSG *msg;
GWEN_DB_NODE *db;
buf=GWEN_Buffer_new(0, len+256, 0, 1);
AQH_HttpService_AddStatusLine(AQH_HttpUrlHandler_GetHttpService(uh), 200, "OK", protocol, buf);
db=GWEN_DB_Group_new("header");
GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "Connection", "Keep-Alive");
GWEN_DB_SetCharValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "Content-Type", contentType);
GWEN_DB_SetIntValue(db, GWEN_DB_FLAGS_OVERWRITE_VARS, "Content-Length", len);
AQH_HttpService_AddHeader(AQH_HttpUrlHandler_GetHttpService(uh), db, buf);
GWEN_DB_Group_free(db);
GWEN_Buffer_AppendBytes(buf, (const char *) ptr, len);
msg=GWEN_Msg_fromBytes((const uint8_t*)GWEN_Buffer_GetStart(buf), GWEN_Buffer_GetUsedBytes(buf));
GWEN_Buffer_free(buf);
return msg;
}
const char *_getContentTypeFromFilename(const char *filename)
{
if (filename) {
const char *s;
s=strrchr(filename, '.');
if (s) {
if (strcasecmp(s, ".png")==0)
return "image/png";
else if (strcasecmp(s, ".jpg")==0)
return "image/jpg";
}
}
return "application/x-binary";
}

View File

@@ -0,0 +1,24 @@
/****************************************************************************
* 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_STATIC_H
#define AQHOME_STORAGE_U_STATIC_H
#include "aqhome/http/urlhandler.h"
#include <gwenhywfar/endpoint.h>
AQH_HTTP_URLHANDLER *AQH_StaticHttpUrlHandler_new(AQH_SERVICE *sv, const char *folder);
#endif

View File

@@ -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_STATIC_P_H
#define AQHOME_STORAGE_U_STATIC_P_H
#include "./u_static.h"
#include <gwenhywfar/stringlist.h>
typedef struct AQH_URLHANDLER_STATIC AQH_URLHANDLER_STATIC;
struct AQH_URLHANDLER_STATIC {
GWEN_STRINGLIST *fileList;
};
#endif

View File

@@ -63,7 +63,6 @@ static int _checkSession(const AQH_SESSION *session);
static int _checkModule(const AQH_MODULE *m, int ignoreMissingId);
static int _checkRoleList(const AQH_ROLE_LIST *roleList, int ignoreMissingId);
static int _writeDbFile(const char *fname, GWEN_DB_NODE *db);
static GWEN_STRINGLIST *_getConfFileList(const char *folder, const char *mask);
static AQH_SESSION_LIST *_readAllSessionsIntoList(const AQH_SERVICE *sv);
static AQH_SESSION *_readSessionFromFile(const char *filename);
@@ -761,6 +760,31 @@ int AQH_HttpService_DelSession(AQH_SERVICE *sv, AQH_SESSION *session)
GWEN_STRINGLIST *AQH_HttpService_GetFolderFileList(const char *folder, const char *mask, int senseCase)
{
GWEN_STRINGLIST *sl;
int rv;
sl=GWEN_StringList_new();
GWEN_StringList_SetSenseCase(sl, senseCase);
rv=GWEN_Directory_GetFileEntries(folder, sl, mask);
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
GWEN_StringList_free(sl);
return NULL;
}
if (GWEN_StringList_Count(sl)<1) {
DBG_INFO(AQH_LOGDOMAIN, "Empty string list");
GWEN_StringList_free(sl);
return NULL;
}
return sl;
}
AQH_MODULE *_ensureModule(AQH_SERVICE *sv, const char *modName)
{
AQH_MODULE *module;
@@ -1159,29 +1183,6 @@ GWEN_BUFFER *_getSessionFolder(const AQH_SERVICE *sv)
GWEN_STRINGLIST *_getConfFileList(const char *folder, const char *mask)
{
GWEN_STRINGLIST *sl;
int rv;
sl=GWEN_StringList_new();
rv=GWEN_Directory_GetFileEntries(folder, sl, mask);
if (rv<0) {
DBG_INFO(AQH_LOGDOMAIN, "here (%d)", rv);
GWEN_StringList_free(sl);
return NULL;
}
if (GWEN_StringList_Count(sl)<1) {
DBG_INFO(AQH_LOGDOMAIN, "Empty string list");
GWEN_StringList_free(sl);
return NULL;
}
return sl;
}
AQH_SESSION_LIST *_readAllSessionsIntoList(const AQH_SERVICE *sv)
{
GWEN_BUFFER *folderBuf;
@@ -1190,7 +1191,7 @@ AQH_SESSION_LIST *_readAllSessionsIntoList(const AQH_SERVICE *sv)
if (folderBuf) {
GWEN_STRINGLIST *fileList;
fileList=_getConfFileList(GWEN_Buffer_GetStart(folderBuf), "*.conf");
fileList=AQH_HttpService_GetFolderFileList(GWEN_Buffer_GetStart(folderBuf), "*.conf", 1);
if (fileList) {
AQH_SESSION_LIST *sessionList;
uint32_t pos;

View File

@@ -52,6 +52,8 @@ AQHOME_API int AQH_HttpService_DelSession(AQH_SERVICE *sv, AQH_SESSION *session)
AQHOME_API void AQH_HttpService_LoadAllSessions(AQH_SERVICE *sv);
AQHOME_API GWEN_STRINGLIST *AQH_HttpService_GetFolderFileList(const char *folder, const char *mask, int senseCase);
#endif

View File

@@ -53,6 +53,8 @@ void AQH_HttpUrlHandler_free(AQH_HTTP_URLHANDLER *uh)
if (uh) {
GWEN_LIST_FINI(AQH_HTTP_URLHANDLER, uh);
GWEN_INHERIT_FINI(AQH_HTTP_URLHANDLER, uh);
free(uh->folder);
GWEN_StringList_free(uh->urlPatternList);
GWEN_FREE_OBJECT(uh);
}
@@ -90,6 +92,23 @@ void AQH_HttpUrlHandler_AddUrlPattern(AQH_HTTP_URLHANDLER *uh, const char *s)
const char *AQH_HttpUrlHandler_GetFolder(const AQH_HTTP_URLHANDLER *uh)
{
return uh?uh->folder:NULL;
}
void AQH_HttpUrlHandler_SetFolder(AQH_HTTP_URLHANDLER *uh, const char *s)
{
if (uh) {
free(uh->folder);
uh->folder=s?strdup(s):NULL;
}
}
int AQH_HttpUrlHandler_UrlMatches(const AQH_HTTP_URLHANDLER *uh, const char *s)
{
if (uh && s && *s) {

View File

@@ -39,6 +39,9 @@ AQHOME_API int AQH_HttpUrlHandler_UrlMatches(const AQH_HTTP_URLHANDLER *uh, cons
AQHOME_API AQH_HTTP_CONTENT *AQH_HttpUrlHandler_GetContentProvider(const AQH_HTTP_URLHANDLER *uh);
AQHOME_API void AQH_HttpUrlHandler_SetContentProvider(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_CONTENT *cp);
AQHOME_API const char *AQH_HttpUrlHandler_GetFolder(const AQH_HTTP_URLHANDLER *uh);
AQHOME_API void AQH_HttpUrlHandler_SetFolder(AQH_HTTP_URLHANDLER *uh, const char *s);
AQHOME_API void AQH_HttpUrlHandler_SetHandleFn(AQH_HTTP_URLHANDLER *uh, AQH_HTTP_URLHANDLER_HANDLE_FN fn);
AQHOME_API int AQH_HttpUrlHandler_AddContentHeaders(AQH_HTTP_URLHANDLER *uh, int m, GWEN_BUFFER *dbuf);

View File

@@ -21,6 +21,8 @@ struct AQH_HTTP_URLHANDLER {
AQH_SERVICE *httpService;
GWEN_STRINGLIST *urlPatternList;
AQH_HTTP_CONTENT *httpContentProvider;
char *folder;
AQH_HTTP_URLHANDLER_HANDLE_FN handleFn;
};