d4732c3d1cbbae67c6ce3801da47405fc3c6c411
[cascardo/atompub.git] / atom / entry.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
20 #include <atompub/atom.h>
21
22 #include <glib.h>
23 #include <libxml/tree.h>
24 #include <libxml/parser.h>
25
26 struct _atom_entry
27 {
28   xmlDocPtr doc;
29   AtomID *id;
30   char *title;
31   GPtrArray *authors;
32   GPtrArray *categories;
33   char *summary;
34 };
35
36 void atom_entry_author_add (AtomEntry *, AtomPerson *);
37 static void atom_entry_authors_delete (AtomEntry *);
38
39 void atom_entry_category_add (AtomEntry *, AtomCategory *);
40 static void atom_entry_categories_delete (AtomEntry *);
41
42 AtomEntry *
43 atom_entry_new (char *title, AtomPerson *author)
44 {
45   AtomEntry *entry;
46   entry = g_slice_new (AtomEntry);
47   entry->doc = NULL;
48   entry->id = NULL;
49   entry->title = g_strdup (title);
50   entry->authors = NULL;
51   entry->categories = NULL;
52   atom_entry_author_add (entry, author);
53   entry->summary = NULL;
54   return entry;
55 }
56
57 AtomEntry *
58 atom_entry_new_data_len (char *data, size_t len)
59 {
60   AtomEntry *entry;
61   xmlNodePtr root;
62   xmlNodePtr child;
63   entry = g_slice_new0 (AtomEntry);
64   entry->doc = xmlReadMemory (data, len, NULL, NULL,
65                               XML_PARSE_RECOVER | XML_PARSE_NOERROR);
66   if (entry->doc == NULL ||
67       (root = xmlDocGetRootElement (entry->doc)) == NULL)
68     {
69       g_slice_free (AtomEntry, entry);
70       return NULL;
71     }
72   if (xmlStrcmp (root->name, "entry"))
73     {
74       xmlFreeDoc (entry->doc);
75       g_slice_free (AtomEntry, entry);
76       return NULL;
77     }
78   for (child = root->xmlChildrenNode; child != NULL; child = child->next)
79     {
80       char * content;
81       content = xmlNodeGetContent (child->xmlChildrenNode);
82       if (!xmlStrcmp (child->name, "id"))
83         entry->id = atom_id_new (content);
84       else if (!xmlStrcmp (child->name, "title"))
85         entry->title = g_strdup (content);
86       else if (!xmlStrcmp (child->name, "summary"))
87         entry->summary = g_strdup (content);
88       else if (!xmlStrcmp (child->name, "author"))
89         atom_entry_author_add (entry, atom_person_new_from_xmlnode (child));
90       else if (!xmlStrcmp (child->name, "category"))
91         atom_entry_category_add (entry, atom_category_new_from_xmlnode (child));
92       else
93         xmlFree (content);
94     }
95   return entry;
96 }
97
98 void
99 atom_entry_delete (AtomEntry *entry)
100 {
101   if (entry->doc)
102     xmlFreeDoc (entry->doc);
103   if (entry->id)
104     atom_id_delete (entry->id);
105   if (entry->title)
106     g_free (entry->title);
107   if (entry->authors)
108     atom_entry_authors_delete (entry);
109   if (entry->categories)
110     atom_entry_categories_delete (entry);
111   if (entry->summary)
112     g_free (entry->summary);
113   g_slice_free (AtomEntry, entry);
114 }
115
116 AtomID *
117 atom_entry_id (AtomEntry *entry)
118 {
119   return entry->id;
120 }
121
122 void
123 atom_entry_id_set (AtomEntry *entry, AtomID *id)
124 {
125   if (entry->id)
126     atom_id_delete (entry->id);
127   entry->id = id;
128 }
129
130 char *
131 atom_entry_title (AtomEntry *entry)
132 {
133   return entry->title;
134 }
135
136 void
137 atom_entry_title_set (AtomEntry *entry, char *title)
138 {
139   if (entry->title)
140     g_free (title);
141   entry->title = g_strdup (title);
142 }
143
144 void
145 atom_entry_authors (AtomEntry *entry, AtomPerson *** authors, size_t *len)
146 {
147   if (len)
148     *len = entry->authors->len;
149   if (authors)
150     *authors = entry->authors->pdata;
151 }
152
153 void
154 atom_entry_author_add (AtomEntry *entry, AtomPerson *author)
155 {
156   if (entry->authors == NULL)
157     {
158       entry->authors = g_ptr_array_new ();
159     }
160   g_ptr_array_add (entry->authors, author);
161 }
162
163 static void
164 atom_entry_authors_delete (AtomEntry *entry)
165 {
166   size_t len = entry->authors->len;
167   int i;
168   for (i = 0; i < len; i++)
169     atom_person_delete (g_ptr_array_index (entry->authors, i));
170   g_ptr_array_free (entry->authors, TRUE);
171 }
172
173 void
174 atom_entry_categories (AtomEntry *entry, AtomCategory *** categories,
175                        size_t *len)
176 {
177   if (len)
178     *len = entry->categories->len;
179   if (categories)
180     *categories = entry->categories->pdata;
181 }
182
183 void
184 atom_entry_category_add (AtomEntry *entry, AtomCategory *category)
185 {
186   g_ptr_array_add (entry->categories, category);
187   if (entry->categories == NULL)
188     {
189       entry->categories = g_ptr_array_new ();
190     }
191   g_ptr_array_add (entry->categories, category);
192 }
193
194 static void
195 atom_entry_categories_delete (AtomEntry *entry)
196 {
197   size_t len = entry->categories->len;
198   int i;
199   for (i = 0; i < len; i++)
200     atom_category_delete (g_ptr_array_index (entry->categories, i));
201   g_ptr_array_free (entry->categories, TRUE);
202 }
203
204 char *
205 atom_entry_summary (AtomEntry *entry)
206 {
207   return entry->summary;
208 }
209
210 void
211 atom_entry_summary_set (AtomEntry *entry, char *summary)
212 {
213   if (entry->summary)
214     g_free (entry->summary);
215   entry->summary = g_strdup (summary);
216 }
217
218 static void
219 atom_entry_update_xmlnode (AtomEntry *entry)
220 {
221   xmlNodePtr root;
222   xmlNodePtr id;
223   xmlNodePtr title;
224   xmlNodePtr summary;
225   xmlNodePtr author;
226   xmlNodePtr cat;
227   int i;
228   if (entry->doc == NULL)
229     {
230       entry->doc = xmlNewDoc ("1.0");
231       root = xmlNewNode (NULL, "entry");
232       xmlNewNs (root, ATOM_NAMESPACE, NULL);
233       xmlDocSetRootElement (entry->doc, root);
234     }
235   else
236     {
237       xmlNodePtr child;
238       xmlNodePtr next;
239       root = xmlDocGetRootElement (entry->doc);
240       child = root->xmlChildrenNode;
241       while (child != NULL)
242         {
243           next = child->next;
244           if (!xmlStrcmp (child->name, "id") ||
245               !xmlStrcmp (child->name, "title") ||
246               !xmlStrcmp (child->name, "summary") ||
247               !xmlStrcmp (child->name, "author") ||
248               !xmlStrcmp (child->name, "category"))
249             {
250               xmlUnlinkNode (child);
251               xmlFreeNode (child);
252             }
253           child = next;
254         }
255     }
256   id = xmlNewTextChild (root, NULL, "id", atom_id_string (entry->id));
257   title = xmlNewTextChild (root, NULL, "title", entry->title);
258   if (entry->summary)
259     summary = xmlNewTextChild (root, NULL, "summary", entry->summary);
260   for (i = 0; i < entry->authors->len; i++)
261     {
262       AtomPerson *person;
263       person = g_ptr_array_index (entry->authors, i);
264       author = atom_person_to_xmlnode (person, "author");
265       xmlAddChild (root, author);
266     }
267   for (i = 0; entry->categories && i < entry->categories->len; i++)
268     {
269       AtomCategory *category;
270       category = g_ptr_array_index (entry->categories, i);
271       cat = atom_category_to_xmlnode (category, "category");
272       xmlAddChild (root, category);
273     }
274 }
275
276 void
277 atom_entry_string (AtomEntry *entry, char **buffer, size_t *len)
278 {
279   atom_entry_update_xmlnode (entry);
280   xmlDocDumpMemory (entry->doc, buffer, len);
281 }
282
283 xmlNodePtr
284 atom_entry_to_xmlnode (AtomEntry *entry)
285 {
286   atom_entry_update_xmlnode (entry);
287   return xmlCopyNodeList (xmlDocGetRootElement (entry->doc));
288 }