// SPDX-License-Identifier: GPL-2.0-or-later /* * * OBEX Server * * Copyright (C) 2007-2010 Marcel Holtmann * * */ #ifdef HAVE_CONFIG_H #include #endif #define _GNU_SOURCE #include #include #include #include #include #include #include #include "log.h" #include "obex.h" #include "mimetype.h" static GSList *drivers = NULL; static GSList *watches = NULL; struct io_watch { void *object; obex_object_io_func func; void *user_data; }; void obex_object_set_io_flags(void *object, int flags, int err) { GSList *l; for (l = watches; l;) { struct io_watch *watch = l->data; l = l->next; if (watch->object != object) continue; if (watch->func(object, flags, err, watch->user_data) == TRUE) continue; if (g_slist_find(watches, watch) == NULL) continue; watches = g_slist_remove(watches, watch); g_free(watch); } } static struct io_watch *find_io_watch(void *object) { GSList *l; for (l = watches; l; l = l->next) { struct io_watch *watch = l->data; if (watch->object == object) return watch; } return NULL; } static void reset_io_watch(void *object) { struct io_watch *watch; watch = find_io_watch(object); if (watch == NULL) return; watches = g_slist_remove(watches, watch); g_free(watch); } static int set_io_watch(void *object, obex_object_io_func func, void *user_data) { struct io_watch *watch; if (func == NULL) { reset_io_watch(object); return 0; } watch = find_io_watch(object); if (watch) return -EPERM; watch = g_new0(struct io_watch, 1); watch->object = object; watch->func = func; watch->user_data = user_data; watches = g_slist_append(watches, watch); return 0; } static struct obex_mime_type_driver *find_driver(const uint8_t *target, unsigned int target_size, const char *mimetype, const uint8_t *who, unsigned int who_size) { GSList *l; for (l = drivers; l; l = l->next) { struct obex_mime_type_driver *driver = l->data; if (memncmp0(target, target_size, driver->target, driver->target_size)) continue; if (memncmp0(who, who_size, driver->who, driver->who_size)) continue; if (mimetype == NULL || driver->mimetype == NULL) { if (mimetype == driver->mimetype) return driver; else continue; } if (g_ascii_strcasecmp(mimetype, driver->mimetype) == 0) return driver; } return NULL; } struct obex_mime_type_driver *obex_mime_type_driver_find(const uint8_t *target, unsigned int target_size, const char *mimetype, const uint8_t *who, unsigned int who_size) { struct obex_mime_type_driver *driver; driver = find_driver(target, target_size, mimetype, who, who_size); if (driver == NULL) { if (who != NULL) { /* Fallback to non-who specific */ driver = find_driver(target, target_size, mimetype, NULL, 0); if (driver != NULL) return driver; } if (mimetype != NULL) /* Fallback to target default */ driver = find_driver(target, target_size, NULL, NULL, 0); if (driver == NULL) /* Fallback to general default */ driver = find_driver(NULL, 0, NULL, NULL, 0); } return driver; } int obex_mime_type_driver_register(struct obex_mime_type_driver *driver) { if (!driver) { error("Invalid driver"); return -EINVAL; } if (find_driver(driver->target, driver->target_size, driver->mimetype, driver->who, driver->who_size)) { error("Permission denied: %s could not be registered", driver->mimetype); return -EPERM; } if (driver->set_io_watch == NULL) driver->set_io_watch = set_io_watch; DBG("driver %p mimetype %s registered", driver, driver->mimetype); drivers = g_slist_append(drivers, driver); return 0; } void obex_mime_type_driver_unregister(struct obex_mime_type_driver *driver) { if (!g_slist_find(drivers, driver)) { error("Unable to unregister: No such driver %p", driver); return; } DBG("driver %p mimetype %s unregistered", driver, driver->mimetype); drivers = g_slist_remove(drivers, driver); }