Implement publish handler in CGI frontend
[cascardo/atompub.git] / frontend / cgi / cgi.c
index 76380ba..ec011ce 100644 (file)
 
 #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);
+}
+
 static AtomRequest *
 cgi_get_request (AtomCtx *ctx)
 {
   AtomError *error;
   char *method = getenv ("REQUEST_METHOD");
   char *path = getenv ("PATH_INFO");
-  int type;
-  char *request;
+  AtomRequest *request;
   if (method == NULL)
     {
       error = atom_error_new ();
@@ -47,6 +125,17 @@ cgi_get_request (AtomCtx *ctx)
       /* 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");
@@ -102,6 +191,22 @@ cgi_handle_feed (AtomCtx *ctx, AtomFeed *feed)
   g_free (str);
 }
 
+static void
+cgi_handle_publish (AtomCtx *ctx, AtomEntry *entry)
+{
+  char * str;
+  size_t len;
+  char *req;
+  req = atom_id_to_backend (ctx, atom_entry_id (entry));
+  fprintf (stdout, "Status: 201 Created\n");
+  fprintf (stdout, "Location: %s%s\n", getbaseurl (), req);
+  cgi_write_header ();
+  atom_entry_string (entry, &str, &len);
+  atom_entry_delete (entry);
+  write (1, str, len);
+  g_free (str);
+}
+
 static int
 cgi_is_feed (AtomCtx *ctx, char *req)
 {
@@ -119,5 +224,6 @@ cgi_frontend (void)
   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);
+  atom_frontend_handle_publish_set (frontend, cgi_handle_publish);
   return frontend;
 }