upgrade obexd to 0.47
[profile/ivi/obexd.git] / client / sync.c
1 /*
2  *
3  *  OBEX Client
4  *
5  *  Copyright (C) 2007-2010  Intel Corporation
6  *  Copyright (C) 2007-2010  Marcel Holtmann <marcel@holtmann.org>
7  *
8  *
9  *  This program is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This program is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this program; if not, write to the Free Software
21  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
22  *
23  */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <errno.h>
30 #include <string.h>
31
32 #include <glib.h>
33 #include <gdbus.h>
34
35 #include "log.h"
36
37 #include "transfer.h"
38 #include "session.h"
39 #include "driver.h"
40 #include "sync.h"
41
42 #define OBEX_SYNC_UUID "IRMC-SYNC"
43 #define OBEX_SYNC_UUID_LEN 9
44
45 #define SYNC_INTERFACE "org.bluez.obex.Synchronization"
46 #define ERROR_INF SYNC_INTERFACE ".Error"
47 #define SYNC_UUID "00001104-0000-1000-8000-00805f9b34fb"
48
49 struct sync_data {
50         struct obc_session *session;
51         char *phonebook_path;
52         DBusMessage *msg;
53 };
54
55 static DBusConnection *conn = NULL;
56
57 static DBusMessage *sync_setlocation(DBusConnection *connection,
58                         DBusMessage *message, void *user_data)
59 {
60         struct sync_data *sync = user_data;
61         const char *location;
62         char *path = NULL, *tmp;
63
64         if (dbus_message_get_args(message, NULL,
65                         DBUS_TYPE_STRING, &location,
66                         DBUS_TYPE_INVALID) == FALSE)
67                 return g_dbus_create_error(message,
68                         ERROR_INF ".InvalidArguments", NULL);
69
70         if (!g_ascii_strcasecmp(location, "INT") ||
71                         !g_ascii_strcasecmp(location, "INTERNAL"))
72                 path = g_strdup("telecom/pb.vcf");
73         else if (!g_ascii_strncasecmp(location, "SIM", 3)) {
74                 tmp = g_ascii_strup(location, 4);
75                 path = g_build_filename(tmp, "telecom/pb.vcf", NULL);
76                 g_free(tmp);
77         } else
78                 return g_dbus_create_error(message,
79                         ERROR_INF ".InvalidArguments", "InvalidPhonebook");
80
81         g_free(sync->phonebook_path);
82         sync->phonebook_path = path;
83
84         return dbus_message_new_method_return(message);
85 }
86
87 static DBusMessage *sync_getphonebook(DBusConnection *connection,
88                         DBusMessage *message, void *user_data)
89 {
90         struct sync_data *sync = user_data;
91         struct obc_transfer *transfer;
92         const char *target_file;
93         GError *err = NULL;
94         DBusMessage *reply;
95
96         if (dbus_message_get_args(message, NULL,
97                                         DBUS_TYPE_STRING, &target_file,
98                                         DBUS_TYPE_INVALID) == FALSE)
99                 return g_dbus_create_error(message,
100                                 ERROR_INF ".InvalidArguments",
101                                 "Invalid arguments in method call");
102
103         if (sync->msg)
104                 return g_dbus_create_error(message,
105                         ERROR_INF ".InProgress", "Transfer in progress");
106
107         /* set default phonebook_path to memory internal phonebook */
108         if (!sync->phonebook_path)
109                 sync->phonebook_path = g_strdup("telecom/pb.vcf");
110
111         transfer = obc_transfer_get("phonebook", sync->phonebook_path,
112                                                         target_file, &err);
113         if (transfer == NULL)
114                 goto fail;
115
116         if (!obc_session_queue(sync->session, transfer, NULL, NULL, &err))
117                 goto fail;
118
119         return obc_transfer_create_dbus_reply(transfer, message);
120
121 fail:
122         reply = g_dbus_create_error(message, ERROR_INF ".Failed", "%s",
123                                                                 err->message);
124         g_error_free(err);
125         return reply;
126 }
127
128 static DBusMessage *sync_putphonebook(DBusConnection *connection,
129                         DBusMessage *message, void *user_data)
130 {
131         struct sync_data *sync = user_data;
132         struct obc_transfer *transfer;
133         const char *source_file;
134         GError *err = NULL;
135         DBusMessage *reply;
136
137         if (dbus_message_get_args(message, NULL,
138                                         DBUS_TYPE_STRING, &source_file,
139                                         DBUS_TYPE_INVALID) == FALSE)
140                 return g_dbus_create_error(message,
141                                 ERROR_INF ".InvalidArguments",
142                                 "Invalid arguments in method call");
143
144         /* set default phonebook_path to memory internal phonebook */
145         if (!sync->phonebook_path)
146                 sync->phonebook_path = g_strdup("telecom/pb.vcf");
147
148         transfer = obc_transfer_put(NULL, sync->phonebook_path, source_file,
149                                                         NULL, 0, &err);
150         if (transfer == NULL)
151                 goto fail;
152
153         if (!obc_session_queue(sync->session, transfer, NULL, NULL, &err))
154                 goto fail;
155
156         return obc_transfer_create_dbus_reply(transfer, message);
157
158 fail:
159         reply = g_dbus_create_error(message, ERROR_INF ".Failed", "%s",
160                                                                 err->message);
161         g_error_free(err);
162         return reply;
163 }
164
165 static const GDBusMethodTable sync_methods[] = {
166         { GDBUS_METHOD("SetLocation",
167                         GDBUS_ARGS({ "location", "s" }), NULL,
168                         sync_setlocation) },
169         { GDBUS_METHOD("GetPhonebook",
170                         GDBUS_ARGS({ "targetfile", "s" }),
171                         GDBUS_ARGS({ "transfer", "o" },
172                                         { "properties", "a{sv}" }),
173                         sync_getphonebook) },
174         { GDBUS_METHOD("PutPhonebook",
175                         GDBUS_ARGS({ "sourcefile", "s" }),
176                         GDBUS_ARGS({ "transfer", "o" },
177                                         { "properties", "a{sv}" }),
178                         sync_putphonebook) },
179         { }
180 };
181
182 static void sync_free(void *data)
183 {
184         struct sync_data *sync = data;
185
186         obc_session_unref(sync->session);
187         g_free(sync->phonebook_path);
188         g_free(sync);
189 }
190
191 static int sync_probe(struct obc_session *session)
192 {
193         struct sync_data *sync;
194         const char *path;
195
196         path = obc_session_get_path(session);
197
198         DBG("%s", path);
199
200         sync = g_try_new0(struct sync_data, 1);
201         if (!sync)
202                 return -ENOMEM;
203
204         sync->session = obc_session_ref(session);
205
206         if (!g_dbus_register_interface(conn, path, SYNC_INTERFACE, sync_methods,
207                                                 NULL, NULL, sync, sync_free)) {
208                 sync_free(sync);
209                 return -ENOMEM;
210         }
211
212         return 0;
213 }
214
215 static void sync_remove(struct obc_session *session)
216 {
217         const char *path = obc_session_get_path(session);
218
219         DBG("%s", path);
220
221         g_dbus_unregister_interface(conn, path, SYNC_INTERFACE);
222 }
223
224 static struct obc_driver sync = {
225         .service = "SYNC",
226         .uuid = SYNC_UUID,
227         .target = OBEX_SYNC_UUID,
228         .target_len = OBEX_SYNC_UUID_LEN,
229         .probe = sync_probe,
230         .remove = sync_remove
231 };
232
233 int sync_init(void)
234 {
235         int err;
236
237         DBG("");
238
239         conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
240         if (!conn)
241                 return -EIO;
242
243         err = obc_driver_register(&sync);
244         if (err < 0) {
245                 dbus_connection_unref(conn);
246                 conn = NULL;
247                 return err;
248         }
249
250         return 0;
251 }
252
253 void sync_exit(void)
254 {
255         DBG("");
256
257         dbus_connection_unref(conn);
258         conn = NULL;
259
260         obc_driver_unregister(&sync);
261 }