9338f4d8d17e78015eaafbeec2bb3b097a8f6208
[cascardo/atompub.git] / frontend / cgi / cgi.c
1 /*
2  *  Copyright (C) 2007  Thadeu Lima de Souza Cascardo <cascardo@holoscopio.com>
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License along
15  *  with this program; if not, write to the Free Software Foundation, Inc.,
16  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18
19
20 #include <atompub/atom.h>
21
22 #include <glib.h>
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28
29 static void
30 cgi_request_content_set (AtomCtx *ctx, AtomRequest *request)
31 {
32   GIOChannel *channel;
33   GError *error = NULL;
34   gchar *data;
35   gsize len;
36   channel = g_io_channel_unix_new (0);
37   if (g_io_channel_read_to_end (channel, &data, &len, &error) !=
38       G_IO_STATUS_NORMAL)
39     {
40       AtomError *aerr = atom_error_new_from_gerror (error);
41       g_io_channel_unref (channel);
42       atom_error_set (ctx, aerr);
43       g_error_free (error);
44       return;
45     }
46   atom_request_content_set (request, data, len);
47   g_io_channel_unref (channel);
48   g_free (data);
49 }
50
51 static AtomRequest *
52 cgi_get_request (AtomCtx *ctx)
53 {
54   AtomError *error;
55   char *method = getenv ("REQUEST_METHOD");
56   char *path = getenv ("PATH_INFO");
57   AtomRequest *request;
58   if (method == NULL)
59     {
60       error = atom_error_new ();
61       atom_error_code_set (error, 400);
62       atom_error_message_set (error, "Bad Request");
63       atom_error_set (ctx, error);
64       return NULL;
65     }
66   if (path == NULL || *path == '\0')
67     path = "/";
68   if (!strcmp (method, "GET"))
69     {
70       /* Remove the leading slash before mapping */
71       return atom_request_new (ATOM_REQUEST_GET, path + 1);
72     }
73   else if (!strcmp (method, "POST"))
74     {
75       request = atom_request_new (ATOM_REQUEST_POST, path + 1);
76       cgi_request_content_set (ctx, request);
77       if (atom_error_get (ctx) != NULL)
78         {
79           atom_request_delete (request);
80           return NULL;
81         }
82       return request;
83     }
84   error = atom_error_new ();
85   atom_error_code_set (error, 501);
86   atom_error_message_set (error, "Not Implemented");
87   atom_error_set (ctx, error);
88   return NULL;
89 }
90
91 static void
92 cgi_handle_error (AtomCtx *ctx)
93 {
94   AtomError *error;
95   if ((error = atom_error_get (ctx)) != NULL)
96     {
97       int code = atom_error_code (error);
98       char *message = atom_error_message (error);
99       fprintf (stdout, "Status: %d %s\n\n%s\n", code, message, message);
100     }
101   else
102     {
103       fprintf (stdout, "Status: 500 Server error\n\nServer error\n");
104     }
105 }
106
107 static void
108 cgi_write_header (void)
109 {
110   char *header;
111   header = "Content-type: application/atom+xml\n\n";
112   write (1, header, strlen (header));
113 }
114
115 static void
116 cgi_handle_entry (AtomCtx *ctx, AtomEntry *entry)
117 {
118   char * str;
119   size_t len;
120   cgi_write_header ();
121   atom_entry_string (entry, &str, &len);
122   atom_entry_delete (entry);
123   write (1, str, len);
124   g_free (str);
125 }
126
127 static void
128 cgi_handle_feed (AtomCtx *ctx, AtomFeed *feed)
129 {
130   char * str;
131   size_t len;
132   cgi_write_header ();
133   atom_feed_string (feed, &str, &len);
134   atom_feed_delete (feed);
135   write (1, str, len);
136   g_free (str);
137 }
138
139 static int
140 cgi_is_feed (AtomCtx *ctx, char *req)
141 {
142   return (req == NULL || *req == '\0');
143 }
144
145 AtomFrontend *
146 cgi_frontend (void)
147 {
148   AtomFrontend *frontend;
149   frontend = atom_frontend_new ();
150   atom_frontend_map_entries_set (frontend, atom_map_frontend_requests);
151   atom_frontend_is_feed_set (frontend, cgi_is_feed);
152   atom_frontend_get_request_set (frontend, cgi_get_request);
153   atom_frontend_handle_error_set (frontend, cgi_handle_error);
154   atom_frontend_handle_entry_set (frontend, cgi_handle_entry);
155   atom_frontend_handle_feed_set (frontend, cgi_handle_feed);
156   return frontend;
157 }