upload tizen1.0 source
[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
31 #include <glib.h>
32 #include <gdbus.h>
33
34 #include "log.h"
35
36 #include "transfer.h"
37 #include "session.h"
38 #include "driver.h"
39 #include "sync.h"
40
41 #define OBEX_SYNC_UUID "IRMC-SYNC"
42 #define OBEX_SYNC_UUID_LEN 9
43
44 #define SYNC_INTERFACE  "org.openobex.Synchronization"
45 #define ERROR_INF SYNC_INTERFACE ".Error"
46 #define SYNC_UUID "00001104-0000-1000-8000-00805f9b34fb"
47
48 struct sync_data {
49         struct obc_session *session;
50         char *phonebook_path;
51         DBusMessage *msg;
52 };
53
54 static DBusConnection *conn = NULL;
55
56 static DBusMessage *sync_setlocation(DBusConnection *connection,
57                         DBusMessage *message, void *user_data)
58 {
59         struct sync_data *sync = user_data;
60         const char *location;
61         char *path = NULL, *tmp;
62
63         if (dbus_message_get_args(message, NULL,
64                         DBUS_TYPE_STRING, &location,
65                         DBUS_TYPE_INVALID) == FALSE)
66                 return g_dbus_create_error(message,
67                         ERROR_INF ".InvalidArguments", NULL);
68
69         if (!g_ascii_strcasecmp(location, "INT") ||
70                         !g_ascii_strcasecmp(location, "INTERNAL"))
71                 path = g_strdup("telecom/pb.vcf");
72         else if (!g_ascii_strncasecmp(location, "SIM", 3)) {
73                 tmp = g_ascii_strup(location, 4);
74                 path = g_build_filename(tmp, "telecom/pb.vcf", NULL);
75                 g_free(tmp);
76         } else
77                 return g_dbus_create_error(message,
78                         ERROR_INF ".InvalidArguments", "InvalidPhonebook");
79
80         g_free(sync->phonebook_path);
81         sync->phonebook_path = path;
82
83         return dbus_message_new_method_return(message);
84 }
85
86 static void sync_getphonebook_callback(struct obc_session *session,
87                                         GError *err, void *user_data)
88 {
89         struct obc_transfer *transfer = obc_session_get_transfer(session);
90         struct sync_data *sync = user_data;
91         DBusMessage *reply;
92         const char *buf;
93         int size;
94
95         reply = dbus_message_new_method_return(sync->msg);
96
97         buf = obc_transfer_get_buffer(transfer, &size);
98         if (size == 0)
99                 buf = "";
100
101         dbus_message_append_args(reply,
102                 DBUS_TYPE_STRING, &buf,
103                 DBUS_TYPE_INVALID);
104
105         g_dbus_send_message(conn, reply);
106         dbus_message_unref(sync->msg);
107         sync->msg = NULL;
108 }
109
110 static DBusMessage *sync_getphonebook(DBusConnection *connection,
111                         DBusMessage *message, void *user_data)
112 {
113         struct sync_data *sync = user_data;
114
115         if (sync->msg)
116                 return g_dbus_create_error(message,
117                         ERROR_INF ".InProgress", "Transfer in progress");
118
119         /* set default phonebook_path to memory internal phonebook */
120         if (!sync->phonebook_path)
121                 sync->phonebook_path = g_strdup("telecom/pb.vcf");
122
123         if (obc_session_get(sync->session, "phonebook", sync->phonebook_path, NULL,
124                                 NULL, 0, sync_getphonebook_callback, sync) < 0)
125                 return g_dbus_create_error(message,
126                         ERROR_INF ".Failed", "Failed");
127
128         sync->msg = dbus_message_ref(message);
129
130         return NULL;
131 }
132
133 static DBusMessage *sync_putphonebook(DBusConnection *connection,
134                         DBusMessage *message, void *user_data)
135 {
136         struct sync_data *sync = user_data;
137         const char *buf;
138         char *buffer;
139
140         if (dbus_message_get_args(message, NULL,
141                         DBUS_TYPE_STRING, &buf,
142                         DBUS_TYPE_INVALID) == FALSE)
143                 return g_dbus_create_error(message,
144                         ERROR_INF ".InvalidArguments", NULL);
145
146         /* set default phonebook_path to memory internal phonebook */
147         if (!sync->phonebook_path)
148                 sync->phonebook_path = g_strdup("telecom/pb.vcf");
149
150         buffer = g_strdup(buf);
151
152         if (obc_session_put(sync->session, buffer, sync->phonebook_path) < 0)
153                 return g_dbus_create_error(message,
154                                 ERROR_INF ".Failed", "Failed");
155
156         return dbus_message_new_method_return(message);
157 }
158
159 static GDBusMethodTable sync_methods[] = {
160         { "SetLocation", "s", "", sync_setlocation },
161         { "GetPhonebook", "", "s", sync_getphonebook,
162                         G_DBUS_METHOD_FLAG_ASYNC },
163         { "PutPhonebook", "s", "", sync_putphonebook,
164                         G_DBUS_METHOD_FLAG_ASYNC },
165         {}
166 };
167
168 static void sync_free(void *data)
169 {
170         struct sync_data *sync = data;
171
172         obc_session_unref(sync->session);
173         g_free(sync->phonebook_path);
174         g_free(sync);
175 }
176
177 static int sync_probe(struct obc_session *session)
178 {
179         struct sync_data *sync;
180         const char *path;
181
182         path = obc_session_get_path(session);
183
184         DBG("%s", path);
185
186         sync = g_try_new0(struct sync_data, 1);
187         if (!sync)
188                 return -ENOMEM;
189
190         sync->session = obc_session_ref(session);
191
192         if (!g_dbus_register_interface(conn, path, SYNC_INTERFACE, sync_methods,
193                                                 NULL, NULL, sync, sync_free)) {
194                 sync_free(sync);
195                 return -ENOMEM;
196         }
197
198         return 0;
199 }
200
201 static void sync_remove(struct obc_session *session)
202 {
203         const char *path = obc_session_get_path(session);
204
205         DBG("%s", path);
206
207         g_dbus_unregister_interface(conn, path, SYNC_INTERFACE);
208 }
209
210 static struct obc_driver sync = {
211         .service = "SYNC",
212         .uuid = SYNC_UUID,
213         .target = OBEX_SYNC_UUID,
214         .target_len = OBEX_SYNC_UUID_LEN,
215         .probe = sync_probe,
216         .remove = sync_remove
217 };
218
219 int sync_init(void)
220 {
221         int err;
222
223         DBG("");
224
225         conn = dbus_bus_get(DBUS_BUS_SESSION, NULL);
226         if (!conn)
227                 return -EIO;
228
229         err = obc_driver_register(&sync);
230         if (err < 0) {
231                 dbus_connection_unref(conn);
232                 conn = NULL;
233                 return err;
234         }
235
236         return 0;
237 }
238
239 void sync_exit(void)
240 {
241         DBG("");
242
243         dbus_connection_unref(conn);
244         conn = NULL;
245
246         obc_driver_unregister(&sync);
247 }