diff --git a/assets/js/init.js b/assets/js/init.js
index 41bfe47..b072d9f 100644
--- a/assets/js/init.js
+++ b/assets/js/init.js
@@ -46,21 +46,27 @@ $(document).ready(function() {
);
$.getJSON("/sessinfo/", $.proxy(sess.loadJSON, sess));
- $.getJSON("/user/get/", $.proxy(sess.loadUserJSON, sess));
+ $.getJSON("/currentuser/", $.proxy(sess.loadUserJSON, sess));
$(window).focus(function() {
$.getJSON("/sessinfo/", $.proxy(sess.loadJSON, sess));
});
$("div#menu ul li.logout").click(function() {
- $.getJSON("/logout/", $.proxy(sess.loadUserJSON, sess));
+ $.ajax({
+ dataType: "json",
+ url: "/authenticate/",
+ type: 'DELETE',
+ success: $.proxy(sess.loadUserJSON, sess)
+ });
+ //$.getJSON("/authenticate/", $.proxy(sess.loadUserJSON, sess));
$.getJSON("/sessinfo/", $.proxy(sess.loadJSON, sess));
});
$("#login").load("/_login.html", function (){
$("#login form").submit(function(event) {
event.preventDefault();
- $.post("/login/",
+ $.post("/authenticate/",
$("#login form").serialize(),
$.proxy(sess.loadUserJSON, sess));
$("#login").addClass("hide");
@@ -71,7 +77,7 @@ $(document).ready(function() {
$("#signup").load("/_signup.html", function (){
$("#signup form").submit(function(event) {
event.preventDefault();
- $.post("/signup/",
+ $.post("/user/",
$("#signup form").serialize(),
$.proxy(sess.loadUserJSON, sess));
$("#signup").addClass("hide");
diff --git a/configure.ac b/configure.ac
index d3687b9..0cee415 100644
--- a/configure.ac
+++ b/configure.ac
@@ -97,6 +97,7 @@ AC_CONFIG_FILES([Makefile
src/storage/Makefile
src/user/Makefile
src/config/Makefile
+ src/router/Makefile
docs/Makefile
config/Makefile
tests/Makefile])
diff --git a/include/application/adapter/http.h b/include/application/adapter/http.h
index 2708080..956a06e 100644
--- a/include/application/adapter/http.h
+++ b/include/application/adapter/http.h
@@ -24,11 +24,13 @@
#define __APPLICATION_ADAPTER_HTTP_H__
#include "class.h"
+#include "router.h"
#include "application/application.h"
CLASS(ApplicationAdapterHttp) {
Application application;
+ Router router;
};
#endif // __APPLICATION_ADAPTER_HTTP_H__
diff --git a/include/http/request.h b/include/http/request.h
index 45eac76..8455495 100644
--- a/include/http/request.h
+++ b/include/http/request.h
@@ -30,7 +30,18 @@
#define N_HTTP_METHOD 8
-char * http_method[N_HTTP_METHOD];
+extern char * http_method[N_HTTP_METHOD];
+
+typedef enum e_HttpMethod {
+ HTTP_OPTIONS = 0,
+ HTTP_GET,
+ HTTP_HEAD,
+ HTTP_POST,
+ HTTP_PUT,
+ HTTP_DELETE,
+ HTTP_TRACE,
+ HTTP_CONNECT
+} HttpMethod;
CLASS(HttpRequest) {
EXTENDS(HttpMessage);
@@ -39,12 +50,14 @@ CLASS(HttpRequest) {
char * uri;
char * path;
+ HttpMethod method_id;
+
Hash get;
Hash post;
Hash cookies;
};
-int httpRequestHasValidMethod(HttpRequest);
+HttpMethod httpRequestGetMethodId(HttpRequest);
#endif // __HTTP_REQUEST_H__
diff --git a/include/router.h b/include/router.h
new file mode 100644
index 0000000..644af94
--- /dev/null
+++ b/include/router.h
@@ -0,0 +1,59 @@
+/**
+ * \file
+ * A generic REST router that is able to map a URL to a specific
+ * function. It uses dlsym to get the address of the function to
+ * be called.
+ * The functions need to have a common interface for sure....This will
+ * work out while I am working on this.
+ * After a function is found it's address will be stored in a hash
+ * so that further lookups might be faster.
+ * By it's nature I think this is part of the HttpApplicationAdapter.
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2013 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#ifndef __ROUTER_H__
+#define __ROUTER_H__
+
+#include
+
+#include "class.h"
+#include "hash.h"
+#include "session.h"
+#include "http/request.h"
+#include "http/response.h"
+#include "application/application.h"
+
+typedef char * (* fptr_routable)(Application, Session, Hash);
+
+CLASS(Router) {
+ Hash functions;
+ Application application;
+
+ void * handle;
+ char * prefix;
+ size_t nprefix;
+
+};
+
+HttpResponse routerRoute(Router, HttpRequest, Session);
+
+#endif // __ROUTER_H__
+
+// vim: set ts=4 sw=4:
diff --git a/src/Makefile.am b/src/Makefile.am
index bc1f50e..1159b5e 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -27,13 +27,14 @@ TRHTTPSERVER = http/libhttp.la \
TR = ./application/.libs/libapplication.a \
./user/.libs/libuser.a \
- ./storage/.libs/libstorage.a \
./auth/.libs/libauth.a \
+ ./storage/.libs/libstorage.a \
./session/.libs/libsession.a \
- ./config/.libs/libconfig.a
+ ./config/.libs/libconfig.a \
+ ./router/.libs/librouter.a
TRLIBS = -ltrutils -ltrhttpserver -ltrbase
-USEDLIBS = -lrt -lssl -lldap -lgdbm -luuid
+USEDLIBS = -lrt -lssl -lldap -lgdbm -luuid -ldl
AM_CFLAGS += -I../include/
@@ -55,7 +56,9 @@ libtrhttpserver_la_LIBADD = $(TRHTTPSERVER)
taskrambler_SOURCES = taskrambler.c $(IFACE) $(UTILS)
taskrambler_CFLAGS = $(AM_CFLAGS)
taskrambler_LDADD = $(TRLIBS) $(TR) $(USEDLIBS)
+taskrambler_LDFLAGS = -Wl,--export-dynamic \
+ -Wl,--whole-archive,./application/.libs/libapplication.a,--no-whole-archive
SUBDIRS = asset auth cbuf class hash queue http \
logger server session socket stream tree application \
- storage user config
+ storage user config router
diff --git a/src/application/Makefile.am b/src/application/Makefile.am
index af6f02c..09cb56f 100644
--- a/src/application/Makefile.am
+++ b/src/application/Makefile.am
@@ -11,10 +11,17 @@ APPLICATION = application.c \
session_cleanup.c
ADAPTERHTTP = adapter/http/http.c \
adapter/http/update.c
+CONTROLLER = controller/authenticate/create.c \
+ controller/authenticate/delete.c \
+ controller/currentuser/read.c \
+ controller/randval/read.c \
+ controller/sessinfo/read.c \
+ controller/user/create.c \
+ controller/version/read.c
AM_CFLAGS += -I../../include/
noinst_LTLIBRARIES = libapplication.la
-libapplication_la_SOURCES = $(APPLICATION) $(ADAPTERHTTP)
+libapplication_la_SOURCES = $(APPLICATION) $(ADAPTERHTTP) $(CONTROLLER)
libapplication_la_CFLAGS = $(AM_CFLAGS)
diff --git a/src/application/adapter/http/http.c b/src/application/adapter/http/http.c
index 3dfdda3..ef6ddf4 100644
--- a/src/application/adapter/http/http.c
+++ b/src/application/adapter/http/http.c
@@ -25,6 +25,7 @@
#include
#include "class.h"
+#include "router.h"
#include "application/application.h"
#include "application/adapter/http.h"
@@ -38,6 +39,7 @@ applicationAdapterHttpCtor(void * _this, va_list * params)
ApplicationAdapterHttp this = _this;
this->application = va_arg(*params, Application);
+ this->router = va_arg(*params, Router);
return 0;
}
diff --git a/src/application/adapter/http/update.c b/src/application/adapter/http/update.c
index bb23915..4d2bc0d 100644
--- a/src/application/adapter/http/update.c
+++ b/src/application/adapter/http/update.c
@@ -22,32 +22,19 @@
#define _GNU_SOURCE
-#include
#include
-#include
#include
-#include "class.h"
#include "application/application.h"
#include "application/adapter/http.h"
#include "hash.h"
#include "http/worker.h"
#include "http/header.h"
-#include "http/response.h"
-#include "auth/credential.h"
-#include "user.h"
-
-#include "utils/memory.h"
-
+#include "http/message.h"
+#include "router.h"
#define NO_SESSION_SID NULL
-#define RANDVAL_JSON "{\"ctime\":%ld,\"vnext\":%ld,\"value\":\"%02d\"}"
-#define SESSION_JSON "{\"id\":\"%s\",\"timeout\":%d,\"timeleft\":%ld}"
-#define USER_JSON \
- "{\"email\":\"%s\",\"firstname\":\"%s\",\"surname\":\"%s\"}"
-#define VERSION_JSON "{\"version\":\"%s\"}"
-
static
inline
char *
@@ -62,170 +49,6 @@ getSessionId(Hash cookies)
return NO_SESSION_SID;
}
-HttpMessage
-responseVersion(const char * version)
-{
- char buffer[200];
- size_t nbuf;
-
- nbuf = sprintf(buffer, VERSION_JSON, version? version : "");
- return (HttpMessage)httpResponseJson(buffer, nbuf);
-}
-
-HttpMessage
-responseRandval(struct randval * val)
-{
- char buffer[200];
- size_t nbuf;
- time_t remaining;
-
- remaining = 10 - (time(NULL) - val->timestamp);
-
- nbuf = sprintf(
- buffer,
- RANDVAL_JSON,
- val->timestamp,
- remaining,
- val->value);
-
- return (HttpMessage)httpResponseJson(buffer, nbuf);
-}
-
-HttpMessage
-responseSession(Session session)
-{
- char buffer[200];
- size_t nbuf;
-
- nbuf = sprintf(buffer, SESSION_JSON,
- (NULL != session)? session->id : "",
- (NULL != session)? SESSION_LIVETIME : 0,
- (NULL != session)? session->livetime - time(NULL) : 0);
-
- return (HttpMessage)httpResponseJson(buffer, nbuf);
-}
-
-HttpMessage
-responseUser(User user)
-{
- char buffer[200];
- size_t nbuf;
-
- nbuf = sprintf(buffer, USER_JSON,
- (NULL != user)? user->email : "",
- (NULL != user)? user->firstname : "",
- (NULL != user)? user->surname : "");
-
- return (HttpMessage)httpResponseJson(buffer, nbuf);
-}
-
-static
-void
-loginAdapter(Application application, HttpWorker worker, Session session)
-{
- HashValue username;
- HashValue password;
- Credential credential;
-
- username = hashGet(
- worker->current_request->post,
- CSTRA("username"));
- password = hashGet(
- worker->current_request->post,
- CSTRA("password"));
-
- if (NULL == username) {
- username = hashGet(
- worker->current_request->post,
- CSTRA("email"));
- }
-
- if (NULL == username || NULL == password) {
- worker->current_response = (HttpMessage)httpResponse403();
- return;
- }
-
- credential = new(Credential,
- CRED_PASSWORD,
- (char *)(username->value), username->nvalue,
- (char *)(password->value), password->nvalue);
-
- if (! applicationLogin(application, credential, session)) {
- worker->current_response = (HttpMessage)httpResponse403();
- } else {
- worker->current_response = responseUser(session->user);
- }
-
- delete(credential);
-}
-
-static
-void
-signupAdapter(Application application, HttpWorker worker, Session session)
-{
- HashValue email;
- HashValue password;
- HashValue pwrepeat;
- HashValue firstname;
- HashValue surname;
-
- Credential credential;
- User user;
-
- email = hashGet(
- worker->current_request->post,
- CSTRA("email"));
- password = hashGet(
- worker->current_request->post,
- CSTRA("password"));
- pwrepeat = hashGet(
- worker->current_request->post,
- CSTRA("pwrepeat"));
- firstname = hashGet(
- worker->current_request->post,
- CSTRA("firstname"));
- surname = hashGet(
- worker->current_request->post,
- CSTRA("surname"));
-
- if (
- NULL == email ||
- NULL == password ||
- NULL == pwrepeat ||
- NULL == firstname ||
- NULL == surname) {
- // maybe this is not a 500...have to check repsonse codes.
- worker->current_response = (HttpMessage)httpResponse500();
- return;
- }
-
- if (password->nvalue != pwrepeat->nvalue ||
- 0 != memcmp(password->value, pwrepeat->value, password->nvalue)) {
- // maybe this is not a 500...have to check repsonse codes.
- worker->current_response = (HttpMessage)httpResponse500();
- return;
- }
-
- credential = new(Credential,
- CRED_PASSWORD,
- (char *)(email->value), email->nvalue,
- (char *)(password->value), password->nvalue);
-
- user = new(User,
- (char *)(email->value), email->nvalue,
- (char *)(firstname->value), firstname->nvalue,
- (char *)(surname->value), surname->nvalue);
-
- if (! applicationSignup(application, credential, user, session)) {
- worker->current_response = (HttpMessage)httpResponse500();
- } else {
- loginAdapter(application, worker, session);
- }
-
- delete(credential);
- delete(user);
-}
-
void
applicationAdapterHttpUpdate(void * _this, void * subject)
{
@@ -253,66 +76,10 @@ applicationAdapterHttpUpdate(void * _this, void * subject)
worker->additional_headers,
new(HttpHeader, CSTRA("Set-Cookie"), buf, nbuf));
- if (0 == strcmp("POST", worker->current_request->method)) {
- if (0 == strcmp("/login/", worker->current_request->path)) {
- loginAdapter(this->application, worker, session);
- return;
- }
-
- if (0 == strcmp("/signup/", worker->current_request->path)) {
- signupAdapter(this->application, worker, session);
- return;
- }
- }
-
- if (0 == strcmp("GET", worker->current_request->method)) {
- if (0 == strcmp("/version/", worker->current_request->path)) {
- worker->current_response =
- responseVersion(this->application->version);
- return;
- }
-
- if (0 == strcmp("/user/get/", worker->current_request->path)) {
- worker->current_response = responseUser(session->user);
- return;
- }
-
- if (0 == strcmp("/logout/", worker->current_request->path)) {
- applicationLogout(this->application, session);
-
- worker->current_response = responseUser(session->user);
- return;
- }
-
- if (0 == strcmp("/sessinfo/", worker->current_request->path)) {
- worker->current_response = responseSession(session);
- return;
- }
-
- if (0 == strcmp("/randval/", worker->current_request->path)) {
- if (NULL != session->user) {
- worker->current_response =
- responseRandval(this->application->val);
- return;
- } else {
- worker->current_response = (HttpMessage)httpResponse403();
- }
- }
- }
-
- // if (0 < session->livetime - now) {
- // nbuf = sprintf(buf, SESSION_JSON,
- // session->id,
- // SESSION_LIVETIME,
- // session->livetime - now);
-
- // queuePut(
- // worker->additional_headers,
- // new(HttpHeader, CSTRA("X-TaskramblerSession"), buf, nbuf));
-
- // } else {
- // nbuf = sprintf(buf, "sid=%s;Path=/;Max-Age=-3600", session->id);
- // }
+ worker->current_response = (HttpMessage)routerRoute(
+ this->router,
+ worker->current_request,
+ session);
}
// vim: set ts=4 sw=4:
diff --git a/src/application/controller/authenticate/create.c b/src/application/controller/authenticate/create.c
new file mode 100644
index 0000000..3f09f70
--- /dev/null
+++ b/src/application/controller/authenticate/create.c
@@ -0,0 +1,75 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2013 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+ */
+
+#define _GNU_SOURCE
+
+#include "class.h"
+#include "application/application.h"
+#include "session.h"
+#include "hash.h"
+#include "auth/credential.h"
+#include "user.h"
+
+#include "utils/memory.h"
+
+char * controllerCurrentuserRead(Application, Session, Hash);
+
+char *
+controllerAuthenticateCreate(
+ Application application,
+ Session session,
+ Hash args)
+{
+ HashValue username;
+ HashValue password;
+ Credential credential;
+
+ char * response_data;
+
+ username = hashGet(args, CSTRA("username"));
+ password = hashGet(args, CSTRA("password"));
+
+ if (NULL == username) {
+ username = hashGet(args, CSTRA("email"));
+ }
+
+ if (NULL == username || NULL == password) {
+ return NULL;
+ }
+
+ credential = new(Credential,
+ CRED_PASSWORD,
+ (char *)(username->value), username->nvalue,
+ (char *)(password->value), password->nvalue);
+
+ if (! applicationLogin(application, credential, session)) {
+ response_data = NULL;
+ } else {
+ response_data = controllerCurrentuserRead(application, session, NULL);
+ }
+
+ delete(credential);
+
+ return response_data;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/application/controller/authenticate/delete.c b/src/application/controller/authenticate/delete.c
new file mode 100644
index 0000000..85e15ed
--- /dev/null
+++ b/src/application/controller/authenticate/delete.c
@@ -0,0 +1,44 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2013 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+* along with this program. If not, see .
+ */
+
+#define _GNU_SOURCE
+
+#include "class.h"
+#include "application/application.h"
+#include "session.h"
+#include "hash.h"
+
+#include "utils/memory.h"
+
+char * controllerCurrentuserRead(Application, Session, Hash);
+
+char *
+controllerAuthenticateDelete(
+ Application application,
+ Session session,
+ Hash args)
+{
+ applicationLogout(application, session);
+ return controllerCurrentuserRead(application, session, NULL);
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/application/controller/currentuser/read.c b/src/application/controller/currentuser/read.c
new file mode 100644
index 0000000..90e676f
--- /dev/null
+++ b/src/application/controller/currentuser/read.c
@@ -0,0 +1,58 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2013 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#define _GNU_SOURCE
+
+#include
+#include
+
+#include "class.h"
+#include "application/application.h"
+#include "session.h"
+#include "hash.h"
+
+#include "utils/memory.h"
+
+
+#define USER_JSON \
+ "{\"email\":\"%s\",\"firstname\":\"%s\",\"surname\":\"%s\"}"
+
+char *
+controllerCurrentuserRead(Application app, Session sess, Hash args)
+{
+ char * buffer;
+ size_t nbuffer;
+
+ nbuffer = snprintf(NULL, 0, USER_JSON,
+ (NULL != sess->user)? sess->user->email : "",
+ (NULL != sess->user)? sess->user->firstname : "",
+ (NULL != sess->user)? sess->user->surname : "");
+ buffer = memMalloc(nbuffer);
+ nbuffer = sprintf(buffer, USER_JSON,
+ (NULL != sess->user)? sess->user->email : "",
+ (NULL != sess->user)? sess->user->firstname : "",
+ (NULL != sess->user)? sess->user->surname : "");
+
+ return buffer;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/application/controller/randval/read.c b/src/application/controller/randval/read.c
new file mode 100644
index 0000000..3c6dab7
--- /dev/null
+++ b/src/application/controller/randval/read.c
@@ -0,0 +1,63 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2013 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#define _GNU_SOURCE
+
+#include
+#include
+
+#include "application/application.h"
+#include "session.h"
+#include "hash.h"
+
+#include "utils/memory.h"
+
+#define RANDVAL_JSON "{\"ctime\":%ld,\"vnext\":%ld,\"value\":\"%02d\"}"
+
+char *
+controllerRandvalRead(Application app, Session sess, Hash args)
+{
+ char * buffer;
+ size_t nbuffer;
+ time_t remaining;
+
+ remaining = 10 - (time(NULL) - app->val->timestamp);
+
+ nbuffer = snprintf(
+ NULL,
+ 0,
+ RANDVAL_JSON,
+ app->val->timestamp,
+ remaining,
+ app->val->value);
+ buffer = memMalloc(nbuffer);
+ sprintf(
+ buffer,
+ RANDVAL_JSON,
+ app->val->timestamp,
+ remaining,
+ app->val->value);
+
+ return buffer;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/application/controller/sessinfo/read.c b/src/application/controller/sessinfo/read.c
new file mode 100644
index 0000000..02b9df0
--- /dev/null
+++ b/src/application/controller/sessinfo/read.c
@@ -0,0 +1,59 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2013 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#define _GNU_SOURCE
+
+#include
+#include
+
+#include "application/application.h"
+#include "session.h"
+#include "hash.h"
+
+#include "utils/memory.h"
+
+#define SESSION_JSON "{\"id\":\"%s\",\"timeout\":%d,\"timeleft\":%ld}"
+
+
+char *
+controllerSessinfoRead(
+ Application application,
+ Session session,
+ Hash args)
+{
+ char * buffer;
+ size_t nbuffer;
+
+ nbuffer = snprintf(NULL, 0, SESSION_JSON,
+ (NULL != session)? session->id : "",
+ (NULL != session)? SESSION_LIVETIME : 0,
+ (NULL != session)? session->livetime - time(NULL) : 0);
+ buffer = memMalloc(nbuffer);
+ sprintf(buffer, SESSION_JSON,
+ (NULL != session)? session->id : "",
+ (NULL != session)? SESSION_LIVETIME : 0,
+ (NULL != session)? session->livetime - time(NULL) : 0);
+
+ return buffer;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/application/controller/user/create.c b/src/application/controller/user/create.c
new file mode 100644
index 0000000..81bcf41
--- /dev/null
+++ b/src/application/controller/user/create.c
@@ -0,0 +1,98 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2013 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#define _GNU_SOURCE
+
+#include "application/application.h"
+#include "session.h"
+#include "hash.h"
+#include "auth/credential.h"
+#include "user.h"
+
+#include "utils/memory.h"
+
+char * controllerCurrentuserRead(Application, Session, Hash);
+
+char *
+controllerUserCreate(
+ Application application,
+ Session session,
+ Hash args)
+{
+ HashValue email;
+ HashValue password;
+ HashValue pwrepeat;
+ HashValue firstname;
+ HashValue surname;
+
+ Credential credential;
+ User user;
+
+ char * response_data;
+
+ email = hashGet(args, CSTRA("email"));
+ password = hashGet(args, CSTRA("password"));
+ pwrepeat = hashGet(args, CSTRA("pwrepeat"));
+ firstname = hashGet(args, CSTRA("firstname"));
+ surname = hashGet(args, CSTRA("surname"));
+
+ if (
+ NULL == email ||
+ NULL == password ||
+ NULL == pwrepeat ||
+ NULL == firstname ||
+ NULL == surname)
+ {
+ return NULL;
+ }
+
+ if (
+ password->nvalue != pwrepeat->nvalue ||
+ 0 != memcmp(password->value, pwrepeat->value, password->nvalue))
+ {
+ return NULL;
+ }
+
+ credential = new(Credential,
+ CRED_PASSWORD,
+ (char *)(email->value), email->nvalue,
+ (char *)(password->value), password->nvalue);
+
+ user = new(User,
+ (char *)(email->value), email->nvalue,
+ (char *)(firstname->value), firstname->nvalue,
+ (char *)(surname->value), surname->nvalue);
+
+ if (! applicationSignup(application, credential, user, session)) {
+ response_data = NULL;
+ } else {
+ applicationLogin(application, credential, session);
+ response_data = controllerCurrentuserRead(application, session, NULL);
+ }
+
+ delete(credential);
+ delete(user);
+
+ return response_data;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/application/controller/version/read.c b/src/application/controller/version/read.c
new file mode 100644
index 0000000..ed2d6c9
--- /dev/null
+++ b/src/application/controller/version/read.c
@@ -0,0 +1,49 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2013 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#define _GNU_SOURCE
+
+#include
+#include
+
+#include "application/application.h"
+#include "hash.h"
+#include "session.h"
+
+#include "utils/memory.h"
+
+#define VERSION_JSON "{\"version\":\"%s\"}"
+
+char *
+controllerVersionRead(Application app, Session sess, Hash args)
+{
+ char * buffer;
+ size_t nbuffer;
+
+ nbuffer = snprintf(NULL, 0, VERSION_JSON, app->version? app->version : "");
+ buffer = memMalloc(nbuffer);
+ sprintf(buffer, VERSION_JSON, app->version? app->version : "");
+
+ return buffer;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/http/Makefile.am b/src/http/Makefile.am
index 8cc182d..b682010 100644
--- a/src/http/Makefile.am
+++ b/src/http/Makefile.am
@@ -8,7 +8,7 @@ MSG = message.c \
message/get_version.c \
message/has_valid_version.c
REQ = request.c \
- request/has_valid_method.c
+ request/get_method_id.c
RESP = response.c \
response/304.c \
response/404.c \
diff --git a/src/http/request.c b/src/http/request.c
index 3054632..b97f999 100644
--- a/src/http/request.c
+++ b/src/http/request.c
@@ -56,6 +56,18 @@ httpRequestCtor(void * _this, va_list * params)
this->uri[ulen] = 0;
memcpy(this->uri, uri, ulen);
+ this->method_id = httpRequestGetMethodId(this);
+
+ if (-1 == this->method_id) {
+ MEM_FREE(this->uri);
+ MEM_FREE(this->method);
+ MEM_FREE(this->path); /** \todo looks like path is not used at all */
+
+ PARENTCALL(_this, Class, dtor);
+
+ return -1;
+ }
+
this->get = new(Hash);
this->post = new(Hash);
this->cookies = new(Hash);
diff --git a/src/http/request/has_valid_method.c b/src/http/request/get_method_id.c
similarity index 88%
rename from src/http/request/has_valid_method.c
rename to src/http/request/get_method_id.c
index c44dcc3..1e15d92 100644
--- a/src/http/request/has_valid_method.c
+++ b/src/http/request/get_method_id.c
@@ -32,22 +32,27 @@ char * http_method[N_HTTP_METHOD] = {
"PUT",
"DELETE",
"TRACE",
- "CONNECT"};
+ "CONNECT"
+};
-int
-httpRequestHasValidMethod(HttpRequest this)
+HttpMethod
+httpRequestGetMethodId(HttpRequest this)
{
int i;
if (NULL == this->method)
- return 0;
+ return -1;
for (i=0; imethod))
break;
}
- return (i != N_HTTP_METHOD);
+ if (i >= N_HTTP_METHOD) {
+ return -1;
+ }
+
+ return (i);
}
// vim: set ts=4 sw=4:
diff --git a/src/router/Makefile.am b/src/router/Makefile.am
new file mode 100644
index 0000000..4854fbd
--- /dev/null
+++ b/src/router/Makefile.am
@@ -0,0 +1,11 @@
+ACLOCAL_AMFLAGS = -I m4
+AUTOMAKE_OPTIONS = subdir-objects
+
+ROUTER = router.c route.c
+
+AM_CFLAGS += -I../../include/
+
+noinst_LTLIBRARIES = librouter.la
+
+librouter_la_SOURCES = $(ROUTER)
+librouter_la_CFLAGS = $(AM_CFLAGS)
diff --git a/src/router/route.c b/src/router/route.c
new file mode 100644
index 0000000..5a6e2c0
--- /dev/null
+++ b/src/router/route.c
@@ -0,0 +1,181 @@
+/**
+ * \file
+ * This is the generic application router....
+ * Here RBAC can take place as every resource is always requested
+ * via an HTTP request.
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2013 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+// for strchr and others.
+#include
+
+// for size_t
+#include
+
+// for dlopen, dlsym
+#include
+
+// for toupper
+#include
+
+#include "router.h"
+#include "hash.h"
+#include "session.h"
+#include "http/request.h"
+#include "http/response.h"
+#include "application/application.h"
+
+#include "utils/memory.h"
+#include "commons.h"
+
+
+#define COMMAND_LEN 128
+
+
+HttpResponse
+routerRoute(
+ Router this,
+ HttpRequest request,
+ Session sess)
+{
+ char functionName[COMMAND_LEN + this->nprefix * 10];
+ Hash args = NULL;
+ fptr_routable function;
+
+ char * tmp;
+ char * command;
+ size_t ncommand;
+ char * response_data;
+ HttpResponse response;
+
+ if ('/' != request->uri[0]) {
+ /*
+ * we only support absolute paths within our
+ * application
+ */
+ return NULL;
+ }
+
+ command = &(request->uri[1]);
+ command[0] = toupper(command[0]);
+
+ /*
+ * find end of command
+ */
+ tmp = strchr(command, '/');
+ if (NULL == tmp) {
+ ncommand = strlen(command);
+ } else {
+ ncommand = tmp - command;
+ }
+
+ memcpy(functionName, this->prefix, this->nprefix);
+ memcpy(&(functionName[this->nprefix]),
+ command, MIN(COMMAND_LEN, ncommand));
+
+ /**
+ * \todo
+ * now get all arguments if we have some
+ */
+
+ /*
+ * following the crud pattern we map the first part
+ * of the uri and the request method to according
+ * function names.
+ */
+ switch (request->method_id) {
+ case HTTP_GET:
+ args = new(Hash);
+ strcpy(&(functionName[this->nprefix + ncommand]), "Read");
+ break;
+
+ case HTTP_POST:
+ args = request->post;
+ strcpy(&(functionName[this->nprefix + ncommand]), "Create");
+ break;
+
+ case HTTP_PUT:
+ strcpy(&(functionName[this->nprefix + ncommand]), "Update");
+ break;
+
+ case HTTP_DELETE:
+ strcpy(&(functionName[this->nprefix + ncommand]), "Delete");
+ break;
+
+ default:
+ /* other methods are not subject of REST */
+ return NULL;
+ }
+
+ /*
+ * \todo for the moment I don't cache the found symbol...
+ * I don't even check if there was an error...the only thing
+ * I do is checking a NULL symbol and in that case don't
+ * handle the request here.
+ */
+ dlerror();
+ function = dlsym(this->handle, functionName);
+
+ /**
+ * \todo somewhere here or above access control have to take place
+ */
+
+ if (NULL == function) {
+ /**
+ * nothing there to handle the request ... so leave it to the
+ * caller...
+ */
+ char * error;
+
+ if (NULL != (error = dlerror())) {
+ /**
+ * \todo add logging...maybe.
+ */
+ }
+
+ return NULL;
+ }
+
+ /*
+ * function has to allocate the memory for reponse_date by using
+ * memMalloc.
+ */
+ response_data = function(this->application, sess, args);
+
+ switch (request->method_id) {
+ case HTTP_GET:
+ delete(args);
+ break;
+
+ case HTTP_POST:
+ case HTTP_PUT:
+ case HTTP_DELETE:
+ default:
+ /* other methods are not subject of REST */
+ break;
+ }
+
+ response = httpResponseJson(response_data, strlen(response_data));
+ MEM_FREE(response_data);
+
+ return response;
+}
+
+// vim: set ts=4 sw=4:
diff --git a/src/router/router.c b/src/router/router.c
new file mode 100644
index 0000000..8305c87
--- /dev/null
+++ b/src/router/router.c
@@ -0,0 +1,66 @@
+/**
+ * \file
+ *
+ * \author Georg Hopp
+ *
+ * \copyright
+ * Copyright © 2013 Georg Hopp
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+// for dlopen, dlsym
+#include
+
+#include "class.h"
+#include "router.h"
+#include "hash.h"
+#include "application/application.h"
+
+#define PREFIX "controller"
+
+static
+int
+routerCtor(void * _this, va_list * params)
+{
+ Router this = _this;
+
+ this->application = va_arg(*params, Application);
+ this->functions = new(Hash);
+ this->handle = dlopen(NULL, RTLD_LAZY);
+ this->prefix = PREFIX;
+ this->nprefix = sizeof(PREFIX) - 1;
+
+ if (NULL == this->handle) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static
+void
+routerDtor(void * _this) {
+ Router this = _this;
+
+ delete(this->functions);
+ dlclose(this->handle);
+}
+
+INIT_IFACE(Class, routerCtor, routerDtor, NULL);
+CREATE_CLASS(Router, NULL, IFACE(Class));
+
+// vim: set ts=4 sw=4:
diff --git a/src/taskrambler.c b/src/taskrambler.c
index 7f588d9..1565916 100644
--- a/src/taskrambler.c
+++ b/src/taskrambler.c
@@ -165,6 +165,7 @@ main()
AuthLdap authLdap;
AuthStorage authStorage;
Application application;
+ Router router;
ApplicationAdapterHttp adapterHttp;
HttpWorker worker;
Server server;
@@ -210,7 +211,8 @@ main()
authLdap,
authStorage);
- adapterHttp = new(ApplicationAdapterHttp, application);
+ router = new(Router, application);
+ adapterHttp = new(ApplicationAdapterHttp, application, router);
worker = new(HttpWorker, "taskrambler");
subjectAttach(worker, adapterHttp);
@@ -267,6 +269,7 @@ main()
delete(server);
delete(worker);
delete(adapterHttp);
+ delete(router);
delete(application);
delete(authStorage);
delete(passwords);