obexd-test package is needed for testing
[profile/ivi/obexd.git] / src / mimetype.c
1 /*
2  *
3  *  OBEX Server
4  *
5  *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@holtmann.org>
6  *
7  *
8  *  This program is free software; you can redistribute it and/or modify
9  *  it under the terms of the GNU General Public License as published by
10  *  the Free Software Foundation; either version 2 of the License, or
11  *  (at your option) any later version.
12  *
13  *  This program is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  *  GNU General Public License for more details.
17  *
18  *  You should have received a copy of the GNU General Public License
19  *  along with this program; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21  *
22  */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <stdio.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <stdint.h>
32 #include <stdlib.h>
33 #include <sys/stat.h>
34
35 #include <glib.h>
36
37 #include "log.h"
38 #include "obex.h"
39 #include "mimetype.h"
40
41 static GSList *drivers = NULL;
42
43 static GSList *watches = NULL;
44
45 struct io_watch {
46         void *object;
47         obex_object_io_func func;
48         void *user_data;
49 };
50
51 void obex_object_set_io_flags(void *object, int flags, int err)
52 {
53         GSList *l;
54
55         for (l = watches; l;) {
56                 struct io_watch *watch = l->data;
57
58                 l = l->next;
59
60                 if (watch->object != object)
61                         continue;
62
63                 if (watch->func(object, flags, err, watch->user_data) == TRUE)
64                         continue;
65
66                 if (g_slist_find(watches, watch) == NULL)
67                         continue;
68
69                 watches = g_slist_remove(watches, watch);
70                 g_free(watch);
71         }
72 }
73
74 static struct io_watch *find_io_watch(void *object)
75 {
76         GSList *l;
77
78         for (l = watches; l; l = l->next) {
79                 struct io_watch *watch = l->data;
80
81                 if (watch->object == object)
82                         return watch;
83         }
84
85         return NULL;
86 }
87
88 static void reset_io_watch(void *object)
89 {
90         struct io_watch *watch;
91
92         watch = find_io_watch(object);
93         if (watch == NULL)
94                 return;
95
96         watches = g_slist_remove(watches, watch);
97         g_free(watch);
98 }
99
100 static int set_io_watch(void *object, obex_object_io_func func,
101                                 void *user_data)
102 {
103         struct io_watch *watch;
104
105         if (func == NULL) {
106                 reset_io_watch(object);
107                 return 0;
108         }
109
110         watch = find_io_watch(object);
111         if (watch)
112                 return -EPERM;
113
114         watch = g_new0(struct io_watch, 1);
115         watch->object = object;
116         watch->func = func;
117         watch->user_data = user_data;
118
119         watches = g_slist_append(watches, watch);
120
121         return 0;
122 }
123
124 static struct obex_mime_type_driver *find_driver(const uint8_t *target,
125                                 unsigned int target_size,
126                                 const char *mimetype, const uint8_t *who,
127                                 unsigned int who_size)
128 {
129         GSList *l;
130
131         for (l = drivers; l; l = l->next) {
132                 struct obex_mime_type_driver *driver = l->data;
133
134                 if (memncmp0(target, target_size, driver->target, driver->target_size))
135                         continue;
136
137                 if (memncmp0(who, who_size, driver->who, driver->who_size))
138                         continue;
139
140                 if (mimetype == NULL || driver->mimetype == NULL) {
141                         if (mimetype == driver->mimetype)
142                                 return driver;
143                         else
144                                 continue;
145                 }
146
147                 if (g_ascii_strcasecmp(mimetype, driver->mimetype) == 0)
148                         return driver;
149         }
150
151         return NULL;
152 }
153
154 struct obex_mime_type_driver *obex_mime_type_driver_find(const uint8_t *target,
155                                 unsigned int target_size,
156                                 const char *mimetype, const uint8_t *who,
157                                 unsigned int who_size)
158 {
159         struct obex_mime_type_driver *driver;
160
161         driver = find_driver(target, target_size, mimetype, who, who_size);
162         if (driver == NULL) {
163                 if (who != NULL) {
164                         /* Fallback to non-who specific */
165                         driver = find_driver(target, target_size, mimetype, NULL, 0);
166                         if (driver != NULL)
167                                 return driver;
168                 }
169
170                 if (mimetype != NULL)
171                         /* Fallback to target default */
172                         driver = find_driver(target, target_size, NULL, NULL, 0);
173
174                 if (driver == NULL)
175                         /* Fallback to general default */
176                         driver = find_driver(NULL, 0, NULL, NULL, 0);
177         }
178
179         return driver;
180 }
181
182 int obex_mime_type_driver_register(struct obex_mime_type_driver *driver)
183 {
184         if (!driver) {
185                 error("Invalid driver");
186                 return -EINVAL;
187         }
188
189         if (find_driver(driver->target, driver->target_size, driver->mimetype,
190                                         driver->who, driver->who_size)) {
191                 error("Permission denied: %s could not be registered",
192                                 driver->mimetype);
193                 return -EPERM;
194         }
195
196         if (driver->set_io_watch == NULL)
197                 driver->set_io_watch = set_io_watch;
198
199         DBG("driver %p mimetype %s registered", driver, driver->mimetype);
200
201         drivers = g_slist_append(drivers, driver);
202
203         return 0;
204 }
205
206 void obex_mime_type_driver_unregister(struct obex_mime_type_driver *driver)
207 {
208         if (!g_slist_find(drivers, driver)) {
209                 error("Unable to unregister: No such driver %p", driver);
210                 return;
211         }
212
213         DBG("driver %p mimetype %s unregistered", driver, driver->mimetype);
214
215         drivers = g_slist_remove(drivers, driver);
216 }