Add initial support for libsoup backend
[cascardo/atompub.git] / backend / soup / soup.c
1 /*
2  *  Copyright (C) 2008  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 #include <glib.h>
20 #include <libsoup/soup.h>
21 #include <atompub/atom.h>
22 #include <atompub/atom-glib.h>
23 #include <string.h>
24
25 SoupSession *session;
26
27 static SoupMessage *
28 soup_req_to_message (AtomCtx *ctx, char *req, char *method)
29 {
30   gchar *root = atom_config_get_str (ctx, "soup", "root");
31   gchar *uri = g_build_filename (root, req, NULL);
32   SoupMessage *message = soup_message_new (method, uri);
33   g_free (root);
34   g_free (uri);
35   return message;
36 }
37
38 static AtomEntry *
39 soup_message_to_atom (AtomCtx *ctx, SoupMessage *message)
40 {
41   AtomEntry *atom;
42   if (message->status_code != 200)
43     {
44       AtomError *aerr = atom_error_new ();
45       atom_error_set_code (aerr, message->status_code);
46       atom_error_set_message (aerr, message->reason_phrase);
47       atom_error_set (ctx, aerr);
48       return NULL;
49     }
50   atom = atom_entry_new_data_len (message->response_body->data,
51                                   message->response_body->length);
52   return atom;
53 }
54
55 static void
56 soup_atom_to_message (AtomCtx *ctx, AtomEntry *entry, SoupMessage *message)
57 {
58   gchar *data = NULL;
59   gsize len = 0;
60   atom_entry_string (entry, &data, &len);
61   soup_message_set_request (message, "application/atom+xml",
62                             SOUP_MEMORY_COPY, data, len);
63   g_free (data);
64 }
65
66 static AtomEntry *
67 soup_atom_retrieve_entry (AtomCtx *ctx, char *req)
68 {
69   SoupMessage *message;
70   AtomEntry *atom;
71   message = soup_req_to_message (ctx, req, "GET");
72   soup_session_send_message (session, message);
73   atom = soup_message_to_atom (ctx, message);
74   g_object_unref (message);
75   return atom;
76 }
77
78 static void
79 soup_atom_publish_entry (AtomCtx *ctx, char *req, AtomEntry *entry)
80 {
81   SoupMessage *message;
82   /* TODO: Create a function to map from an Entry ID to a new filename */
83   if (req == NULL)
84     req = atom_entry_id (entry);
85   message = soup_req_to_message (ctx, req, "POST");
86   soup_atom_to_message (ctx, entry, message);
87   soup_message_headers_append (message->request_headers, "Slug", req);
88   soup_session_send_message (session, message);
89   if (message->status_code != 201)
90     {
91       AtomError *aerr = atom_error_new ();
92       atom_error_set_code (aerr, message->status_code);
93       atom_error_set_message (aerr, message->reason_phrase);
94       atom_error_set (ctx, aerr);
95     }
96   g_object_unref (message);
97 }
98
99 AtomBackend *
100 soup_backend (void)
101 {
102   AtomBackend *backend;
103   session = soup_session_sync_new ();
104   backend = atom_backend_new ();
105   atom_backend_retrieve_entry_set (backend, soup_atom_retrieve_entry);
106   atom_backend_publish_entry_set (backend, soup_atom_publish_entry);
107   return backend;
108 }