#include <atompub/atom.h>
+#include <glib.h>
+
+#define _GNU_SOURCE /* for asprintf */
+#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
+
+static int
+uri_is_absolute (char *uri)
+{
+ return (*uri != '/');
+}
+
+static char *
+getbaseurl (void)
+{
+ char *uri = NULL;
+ char *request_uri = getenv ("REQUEST_URI");
+ char *path = getenv ("PATH_INFO");
+ char *host = getenv ("HTTP_HOST");
+ char *server = getenv ("SERVER_NAME");
+ char *sport = getenv ("SERVER_PORT");
+ int port;
+ if (sport)
+ {
+ port = strtol (sport, NULL, 0);
+ }
+ else
+ {
+ port = 0;
+ }
+ if (request_uri == NULL)
+ return NULL;
+ if (uri_is_absolute (request_uri))
+ {
+ uri = strdup (request_uri);
+ }
+ else if (host)
+ {
+ asprintf (&uri, "http://%s%s", host, request_uri);
+ }
+ else if (server && port != 0 && port != 80)
+ {
+ asprintf (&uri, "http://%s:%d%s", server, port, request_uri);
+ }
+ else if (server)
+ {
+ asprintf (&uri, "http://%s%s", server, request_uri);
+ }
+ if (path && uri)
+ {
+ size_t pathl = strlen (path);
+ size_t uril = strlen (uri);
+ if (!strncmp (uri + uril - pathl, path, pathl))
+ {
+ *(uri + uril - pathl) = 0;
+ }
+ }
+ return uri;
+}
+
+static void
+cgi_request_content_set (AtomCtx *ctx, AtomRequest *request)
+{
+ GIOChannel *channel;
+ GError *error = NULL;
+ gchar *data;
+ gsize len;
+ channel = g_io_channel_unix_new (0);
+ if (g_io_channel_read_to_end (channel, &data, &len, &error) !=
+ G_IO_STATUS_NORMAL)
+ {
+ AtomError *aerr = atom_error_new_from_gerror (error);
+ g_io_channel_unref (channel);
+ atom_error_set (ctx, aerr);
+ g_error_free (error);
+ return;
+ }
+ atom_request_content_set (request, data, len);
+ g_io_channel_unref (channel);
+ g_free (data);
+}
-void
-cgi_serve_request (AtomCtx *ctx)
+static AtomRequest *
+cgi_get_request (AtomCtx *ctx)
{
+ AtomError *error;
char *method = getenv ("REQUEST_METHOD");
char *path = getenv ("PATH_INFO");
+ AtomRequest *request;
if (method == NULL)
- return;
- if (path == NULL)
{
- path = atom_config_get_str (ctx, "cgi", "index");
+ error = atom_error_new ();
+ atom_error_code_set (error, 400);
+ atom_error_message_set (error, "Bad Request");
+ atom_error_set (ctx, error);
+ return NULL;
}
+ if (path == NULL || *path == '\0')
+ path = "/";
if (!strcmp (method, "GET"))
{
- IRI *iri = iri_new ();
- Atom *atom;
- iri_set_path (iri, path);
- atom = atom_retrieve_resource (ctx, iri);
- iri_delete (iri);
- if (atom)
- {
- char *header = "Content-type: application/atom+xml\n\n";
- write (1, header, strlen (header));
- write (1, atom_string (atom), atom_len (atom));
- atom_delete (atom);
- }
+ /* Remove the leading slash before mapping */
+ return atom_request_new (ATOM_REQUEST_GET, path + 1);
+ }
+ else if (!strcmp (method, "POST"))
+ {
+ request = atom_request_new (ATOM_REQUEST_POST, path + 1);
+ cgi_request_content_set (ctx, request);
+ if (atom_error_get (ctx) != NULL)
+ {
+ atom_request_delete (request);
+ return NULL;
+ }
+ return request;
+ }
+ error = atom_error_new ();
+ atom_error_code_set (error, 501);
+ atom_error_message_set (error, "Not Implemented");
+ atom_error_set (ctx, error);
+ return NULL;
+}
+
+static void
+cgi_handle_error (AtomCtx *ctx)
+{
+ AtomError *error;
+ if ((error = atom_error_get (ctx)) != NULL)
+ {
+ int code = atom_error_code (error);
+ char *message = atom_error_message (error);
+ fprintf (stdout, "Status: %d %s\n\n%s\n", code, message, message);
}
else
{
- fprintf (stdout, "Status: 501 Not Implemented\n\n");
+ fprintf (stdout, "Status: 500 Server error\n\nServer error\n");
}
}
+
+static void
+cgi_write_header (void)
+{
+ char *header;
+ header = "Content-type: application/atom+xml\n\n";
+ write (1, header, strlen (header));
+}
+
+static void
+cgi_handle_entry (AtomCtx *ctx, AtomEntry *entry)
+{
+ char * str;
+ size_t len;
+ cgi_write_header ();
+ atom_entry_string (entry, &str, &len);
+ atom_entry_delete (entry);
+ write (1, str, len);
+ g_free (str);
+}
+
+static void
+cgi_handle_feed (AtomCtx *ctx, AtomFeed *feed)
+{
+ char * str;
+ size_t len;
+ cgi_write_header ();
+ atom_feed_string (feed, &str, &len);
+ atom_feed_delete (feed);
+ write (1, str, len);
+ g_free (str);
+}
+
+static int
+cgi_is_feed (AtomCtx *ctx, char *req)
+{
+ return (req == NULL || *req == '\0');
+}
+
+AtomFrontend *
+cgi_frontend (void)
+{
+ AtomFrontend *frontend;
+ frontend = atom_frontend_new ();
+ atom_frontend_map_entries_set (frontend, atom_map_frontend_requests);
+ atom_frontend_is_feed_set (frontend, cgi_is_feed);
+ atom_frontend_get_request_set (frontend, cgi_get_request);
+ atom_frontend_handle_error_set (frontend, cgi_handle_error);
+ atom_frontend_handle_entry_set (frontend, cgi_handle_entry);
+ atom_frontend_handle_feed_set (frontend, cgi_handle_feed);
+ return frontend;
+}