X-Git-Url: http://git.cascardo.eti.br/?a=blobdiff_plain;f=frontend%2Fcgi%2Fcgi.c;h=ec011ce76b0b129439e24d9d2bf21d4b45b753aa;hb=0585e4c354924c71a990fb75536a6c6c8313c510;hp=238ac39c1dd938189c396fb197d02e0ec72f1bd0;hpb=e868641b28f8fa86b2b274d6ecb289bbaab2eb35;p=cascardo%2Fatompub.git diff --git a/frontend/cgi/cgi.c b/frontend/cgi/cgi.c index 238ac39..ec011ce 100644 --- a/frontend/cgi/cgi.c +++ b/frontend/cgi/cgi.c @@ -19,53 +19,211 @@ #include +#include + +#define _GNU_SOURCE /* for asprintf */ #include #include #include #include -void -cgi_serve_request (AtomCtx *ctx) +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"); + 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; - GError *error; - 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); - } - else if ((error = atom_error_get (ctx)) != NULL) - { - if (error->domain == G_FILE_ERROR && - (error->code == G_FILE_ERROR_EXIST || - error->code == G_FILE_ERROR_ACCES || - error->code == G_FILE_ERROR_PERM)) - fprintf (stdout, "Status: 403 %s\n\n", error->message); - else if (error->domain == G_FILE_ERROR && - error->code == G_FILE_ERROR_NOENT) - fprintf (stdout, "Status: 404 %s\n\n", error->message); - else - fprintf (stdout, "Status: 500 %s\n\n", error->message); - } + /* 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 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) +{ + 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); + atom_frontend_handle_publish_set (frontend, cgi_handle_publish); + return frontend; +}