upgrade obexd to 0.47
[profile/ivi/obexd.git] / plugins / opp.c
1 /*
2  *
3  *  OBEX Server
4  *
5  *  Copyright (C) 2007-2010  Nokia 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 #include <unistd.h>
32 #include <inttypes.h>
33
34 #include <glib.h>
35
36 #include "obexd.h"
37 #include "plugin.h"
38 #include "obex.h"
39 #include "service.h"
40 #include "log.h"
41 #include "manager.h"
42 #include "filesystem.h"
43
44 #define VCARD_TYPE "text/x-vcard"
45 #define VCARD_FILE CONFIGDIR "/vcard.vcf"
46
47 #define OPP_CHANNEL     9
48 #define OPP_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
49 <record>                                                        \
50   <attribute id=\"0x0001\">                                     \
51     <sequence>                                                  \
52       <uuid value=\"0x1105\"/>                                  \
53     </sequence>                                                 \
54   </attribute>                                                  \
55                                                                 \
56   <attribute id=\"0x0004\">                                     \
57     <sequence>                                                  \
58       <sequence>                                                \
59         <uuid value=\"0x0100\"/>                                \
60       </sequence>                                               \
61       <sequence>                                                \
62         <uuid value=\"0x0003\"/>                                \
63         <uint8 value=\"%u\" name=\"channel\"/>                  \
64       </sequence>                                               \
65       <sequence>                                                \
66         <uuid value=\"0x0008\"/>                                \
67       </sequence>                                               \
68     </sequence>                                                 \
69   </attribute>                                                  \
70                                                                 \
71   <attribute id=\"0x0009\">                                     \
72     <sequence>                                                  \
73       <sequence>                                                \
74         <uuid value=\"0x1105\"/>                                \
75         <uint16 value=\"0x0102\" name=\"version\"/>             \
76       </sequence>                                               \
77     </sequence>                                                 \
78   </attribute>                                                  \
79                                                                 \
80   <attribute id=\"0x0100\">                                     \
81     <text value=\"%s\" name=\"name\"/>                          \
82   </attribute>                                                  \
83                                                                 \
84   <attribute id=\"0x0303\">                                     \
85     <sequence>                                                  \
86       <uint8 value=\"0x01\"/>                                   \
87       <uint8 value=\"0x02\"/>                                   \
88       <uint8 value=\"0x03\"/>                                   \
89       <uint8 value=\"0x04\"/>                                   \
90       <uint8 value=\"0x05\"/>                                   \
91       <uint8 value=\"0x06\"/>                                   \
92       <uint8 value=\"0xff\"/>                                   \
93     </sequence>                                                 \
94   </attribute>                                                  \
95   <attribute id=\"0x0200\">                                     \
96     <uint16 value=\"%u\" name=\"psm\"/>                         \
97   </attribute>                                                  \
98 </record>"
99
100 static void *opp_connect(struct obex_session *os, int *err)
101 {
102         manager_register_transfer(os);
103
104         if (err)
105                 *err = 0;
106
107         return NULL;
108 }
109
110 static void opp_progress(struct obex_session *os, void *user_data)
111 {
112         manager_emit_transfer_progress(os);
113 }
114
115 static int opp_chkput(struct obex_session *os, void *user_data)
116 {
117         char *folder, *name, *path;
118         int32_t time;
119         const char *t;
120         int err;
121
122         if (obex_get_size(os) == OBJECT_SIZE_DELETE)
123                 return -ENOSYS;
124
125         t = obex_get_name(os);
126         if (t != NULL && !is_filename(t))
127                 return -EBADR;
128
129         if (obex_option_auto_accept()) {
130                 folder = g_strdup(obex_option_root_folder());
131                 name = g_strdup(obex_get_name(os));
132                 goto skip_auth;
133         }
134
135         time = 0;
136         err = manager_request_authorization(os, time, &folder, &name);
137         if (err < 0)
138                 return -EPERM;
139
140         if (folder == NULL)
141                 folder = g_strdup(obex_option_root_folder());
142
143         if (name == NULL)
144                 name = g_strdup(obex_get_name(os));
145
146 skip_auth:
147         if (name == NULL || strlen(name) == 0) {
148                 err = -EBADR;
149                 goto failed;
150         }
151
152         if (g_strcmp0(name, obex_get_name(os)) != 0)
153                 obex_set_name(os, name);
154
155         path = g_build_filename(folder, name, NULL);
156
157         err = obex_put_stream_start(os, path);
158
159         g_free(path);
160
161         if (err < 0)
162                 goto failed;
163
164         manager_emit_transfer_started(os);
165
166 failed:
167         g_free(folder);
168         g_free(name);
169
170         return err;
171 }
172
173 static int opp_put(struct obex_session *os, void *user_data)
174 {
175         const char *name = obex_get_name(os);
176         const char *folder = obex_option_root_folder();
177
178         if (folder == NULL)
179                 return -EPERM;
180
181         if (name == NULL)
182                 return -EBADR;
183
184         return 0;
185 }
186
187 static int opp_get(struct obex_session *os, void *user_data)
188 {
189         const char *type;
190
191         if (obex_get_name(os))
192                 return -EPERM;
193
194         type = obex_get_type(os);
195
196         if (type == NULL)
197                 return -EPERM;
198
199         if (g_ascii_strcasecmp(type, VCARD_TYPE) == 0) {
200                 if (obex_get_stream_start(os, VCARD_FILE) < 0)
201                         return -ENOENT;
202
203         } else
204                 return -EPERM;
205
206         return 0;
207 }
208
209 static void opp_disconnect(struct obex_session *os, void *user_data)
210 {
211         manager_unregister_transfer(os);
212 }
213
214 static void opp_reset(struct obex_session *os, void *user_data)
215 {
216         manager_emit_transfer_completed(os);
217 }
218
219 static struct obex_service_driver driver = {
220         .name = "Object Push server",
221         .service = OBEX_OPP,
222         .channel = OPP_CHANNEL,
223         .port = OBEX_PORT_RANDOM,
224         .record = OPP_RECORD,
225         .connect = opp_connect,
226         .progress = opp_progress,
227         .disconnect = opp_disconnect,
228         .get = opp_get,
229         .put = opp_put,
230         .chkput = opp_chkput,
231         .reset = opp_reset
232 };
233
234 static int opp_init(void)
235 {
236         return obex_service_driver_register(&driver);
237 }
238
239 static void opp_exit(void)
240 {
241         obex_service_driver_unregister(&driver);
242 }
243
244 OBEX_PLUGIN_DEFINE(opp, opp_init, opp_exit)