blob: 3ee18a619daff77737e75dd3a3c36cc6583ff7c1 [file] [log] [blame]
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -03001/*
2 *
3 * OBEX Server
4 *
Johan Hedberg00deeee2010-01-07 12:32:49 +02005 * Copyright (C) 2007-2010 Nokia Corporation
Marcel Holtmann4174e902010-01-01 17:09:14 -08006 * Copyright (C) 2007-2010 Marcel Holtmann <marcel@holtmann.org>
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -03007 *
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
Johan Hedbergb8779d22012-12-07 12:46:04 +020025#ifdef HAVE_CONFIG_H
26#include <config.h>
27#endif
28
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -030029#include <fcntl.h>
30#include <stdio.h>
31#include <errno.h>
32#include <stdlib.h>
33#include <string.h>
34#include <dirent.h>
35#include <sys/stat.h>
36#include <sys/types.h>
37#include <sys/wait.h>
38#include <unistd.h>
Luiz Augusto von Dentz30d62742011-11-15 15:27:57 +020039#include <inttypes.h>
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -030040
41#include <glib.h>
42
Marcel Holtmann7a72ebe2015-03-01 01:38:12 -080043#include "obexd/src/obexd.h"
44#include "obexd/src/plugin.h"
45#include "obexd/src/log.h"
46#include "obexd/src/obex.h"
47#include "obexd/src/manager.h"
48#include "obexd/src/mimetype.h"
49#include "obexd/src/service.h"
Luiz Augusto von Dentz41323662011-02-26 16:49:41 -030050#include "ftp.h"
Slawomir Bochenski6b5d9542011-08-01 15:44:57 +020051#include "filesystem.h"
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -030052
53#define LST_TYPE "x-obex/folder-listing"
54#define CAP_TYPE "x-obex/capability"
55
Vinicius Costa Gomesdf9dd742010-05-13 19:26:42 -030056static const uint8_t FTP_TARGET[TARGET_SIZE] = {
57 0xF9, 0xEC, 0x7B, 0xC4, 0x95, 0x3C, 0x11, 0xD2,
58 0x98, 0x4E, 0x52, 0x54, 0x00, 0xDC, 0x9E, 0x09 };
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -030059
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -030060struct ftp_session {
61 struct obex_session *os;
Bharat Panda1e5a31d2014-10-30 20:29:24 +053062 struct obex_transfer *transfer;
Vinicius Costa Gomesdf9dd742010-05-13 19:26:42 -030063 char *folder;
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -030064};
65
66static void set_folder(struct ftp_session *ftp, const char *new_folder)
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -030067{
Luiz Augusto von Dentz8e773042011-02-23 11:54:37 +020068 DBG("%p folder %s", ftp, new_folder);
69
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -030070 g_free(ftp->folder);
71
72 ftp->folder = new_folder ? g_strdup(new_folder) : NULL;
73}
74
Vinicius Costa Gomesdf9dd742010-05-13 19:26:42 -030075static int get_by_type(struct ftp_session *ftp, const char *type)
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -030076{
77 struct obex_session *os = ftp->os;
Luiz Augusto von Dentzc1781672011-11-02 15:09:50 +020078 const char *capability = obex_option_capability();
Vinicius Costa Gomes70bc46a2010-05-24 14:59:13 -030079 const char *name = obex_get_name(os);
80 char *path;
81 int err;
Vinicius Costa Gomes171d3ae2010-02-26 16:32:13 -030082
Luiz Augusto von Dentz8e773042011-02-23 11:54:37 +020083 DBG("%p name %s type %s", ftp, name, type);
84
Vinicius Costa Gomes70bc46a2010-05-24 14:59:13 -030085 if (type == NULL && name == NULL)
86 return -EBADR;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -030087
Slawomir Bochenski1729ca82011-07-27 18:25:48 +020088 if (type != NULL && g_ascii_strcasecmp(type, CAP_TYPE) == 0)
Vinicius Costa Gomes7c028642010-04-01 20:09:34 -030089 return obex_get_stream_start(os, capability);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -030090
Slawomir Bochenski6b5d9542011-08-01 15:44:57 +020091 if (name != NULL && !is_filename(name))
92 return -EBADR;
93
Vinicius Costa Gomes70bc46a2010-05-24 14:59:13 -030094 path = g_build_filename(ftp->folder, name, NULL);
95 err = obex_get_stream_start(os, path);
96
97 g_free(path);
98
99 return err;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300100}
101
Luiz Augusto von Dentz41323662011-02-26 16:49:41 -0300102void *ftp_connect(struct obex_session *os, int *err)
Luiz Augusto von Dentz5bb6f1c2009-11-09 16:00:41 -0300103{
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300104 struct ftp_session *ftp;
105 const char *root_folder;
106
Luiz Augusto von Dentz8e773042011-02-23 11:54:37 +0200107 DBG("");
108
Luiz Augusto von Dentzc1781672011-11-02 15:09:50 +0200109 root_folder = obex_option_root_folder();
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300110
Claudio Takahasiac94e9b2010-02-25 17:24:59 -0300111 manager_register_session(os);
Luiz Augusto von Dentz5bb6f1c2009-11-09 16:00:41 -0300112
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300113 ftp = g_new0(struct ftp_session, 1);
114 set_folder(ftp, root_folder);
115 ftp->os = os;
116
Vinicius Costa Gomes556447e2010-03-05 20:18:36 -0300117 if (err)
118 *err = 0;
119
Bharat Panda1e5a31d2014-10-30 20:29:24 +0530120 ftp->transfer = manager_register_transfer(os);
121
Luiz Augusto von Dentz8e773042011-02-23 11:54:37 +0200122 DBG("session %p created", ftp);
123
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300124 return ftp;
Luiz Augusto von Dentz5bb6f1c2009-11-09 16:00:41 -0300125}
126
Luiz Augusto von Dentz7c358982011-11-15 15:27:55 +0200127int ftp_get(struct obex_session *os, void *user_data)
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300128{
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300129 struct ftp_session *ftp = user_data;
Vinicius Costa Gomes171d3ae2010-02-26 16:32:13 -0300130 const char *type = obex_get_type(os);
Vinicius Costa Gomes6c4b6ba2010-03-23 19:36:09 -0300131 int ret;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300132
Luiz Augusto von Dentz8e773042011-02-23 11:54:37 +0200133 DBG("%p", ftp);
134
Vinicius Costa Gomes6c4b6ba2010-03-23 19:36:09 -0300135 if (ftp->folder == NULL)
136 return -ENOENT;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300137
Vinicius Costa Gomes6c4b6ba2010-03-23 19:36:09 -0300138 ret = get_by_type(ftp, type);
139 if (ret < 0)
140 return ret;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300141
Bharat Panda1e5a31d2014-10-30 20:29:24 +0530142 /* Only track progress of file transfer */
143 if (type == NULL)
144 manager_emit_transfer_started(ftp->transfer);
145
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300146 return 0;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300147}
148
Vinicius Costa Gomesdf9dd742010-05-13 19:26:42 -0300149static int ftp_delete(struct ftp_session *ftp, const char *name)
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300150{
Vinicius Costa Gomesdf9dd742010-05-13 19:26:42 -0300151 char *path;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300152 int ret = 0;
153
Luiz Augusto von Dentz8e773042011-02-23 11:54:37 +0200154 DBG("%p name %s", ftp, name);
155
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300156 if (!(ftp->folder && name))
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300157 return -EINVAL;
158
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300159 path = g_build_filename(ftp->folder, name, NULL);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300160
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300161 if (obex_remove(ftp->os, path) < 0)
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300162 ret = -errno;
163
164 g_free(path);
165
166 return ret;
167}
168
Luiz Augusto von Dentz41323662011-02-26 16:49:41 -0300169int ftp_chkput(struct obex_session *os, void *user_data)
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300170{
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300171 struct ftp_session *ftp = user_data;
Vinicius Costa Gomesdf9dd742010-05-13 19:26:42 -0300172 const char *name = obex_get_name(os);
173 char *path;
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300174 int ret;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300175
Luiz Augusto von Dentz8e773042011-02-23 11:54:37 +0200176 DBG("%p name %s", ftp, name);
177
Luiz Augusto von Dentz38c2f102010-05-14 11:00:19 +0300178 if (name == NULL)
179 return -EBADR;
180
Slawomir Bochenskied7441b2011-08-04 14:49:56 +0200181 if (!is_filename(name))
182 return -EBADR;
183
Claudio Takahasi0c2498c2010-02-26 15:51:54 -0300184 if (obex_get_size(os) == OBJECT_SIZE_DELETE)
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300185 return 0;
186
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300187 path = g_build_filename(ftp->folder, name, NULL);
188
Vinicius Costa Gomes7c028642010-04-01 20:09:34 -0300189 ret = obex_put_stream_start(os, path);
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300190
Bharat Panda1e5a31d2014-10-30 20:29:24 +0530191 if (ret == 0)
192 manager_emit_transfer_started(ftp->transfer);
193
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300194 g_free(path);
195
196 return ret;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300197}
198
Luiz Augusto von Dentz7c358982011-11-15 15:27:55 +0200199int ftp_put(struct obex_session *os, void *user_data)
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300200{
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300201 struct ftp_session *ftp = user_data;
Claudio Takahasi5ec32752010-02-26 14:36:27 -0300202 const char *name = obex_get_name(os);
203 ssize_t size = obex_get_size(os);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300204
Luiz Augusto von Dentz8e773042011-02-23 11:54:37 +0200205 DBG("%p name %s size %zd", ftp, name, size);
206
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300207 if (ftp->folder == NULL)
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300208 return -EPERM;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300209
Vinicius Costa Gomesd485fe82010-02-26 14:22:07 -0300210 if (name == NULL)
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300211 return -EBADR;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300212
Slawomir Bochenski6b5d9542011-08-01 15:44:57 +0200213 if (!is_filename(name))
214 return -EBADR;
215
Vinicius Costa Gomesd485fe82010-02-26 14:22:07 -0300216 if (size == OBJECT_SIZE_DELETE)
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300217 return ftp_delete(ftp, name);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300218
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300219 return 0;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300220}
221
Luiz Augusto von Dentz7c358982011-11-15 15:27:55 +0200222int ftp_setpath(struct obex_session *os, void *user_data)
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300223{
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300224 struct ftp_session *ftp = user_data;
Vinicius Costa Gomesdf9dd742010-05-13 19:26:42 -0300225 const char *root_folder, *name;
Luiz Augusto von Dentzdcab04f2011-11-15 15:27:54 +0200226 const uint8_t *nonhdr;
Vinicius Costa Gomesdf9dd742010-05-13 19:26:42 -0300227 char *fullname;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300228 struct stat dstat;
229 gboolean root;
230 int err;
231
Luiz Augusto von Dentzdcab04f2011-11-15 15:27:54 +0200232 if (obex_get_non_header_data(os, &nonhdr) != 2) {
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300233 error("Set path failed: flag and constants not found!");
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300234 return -EBADMSG;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300235 }
236
Claudio Takahasi5ec32752010-02-26 14:36:27 -0300237 name = obex_get_name(os);
Luiz Augusto von Dentzc1781672011-11-02 15:09:50 +0200238 root_folder = obex_option_root_folder();
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300239 root = g_str_equal(root_folder, ftp->folder);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300240
Luiz Augusto von Dentz8e773042011-02-23 11:54:37 +0200241 DBG("%p name %s", ftp, name);
242
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300243 /* Check flag "Backup" */
244 if ((nonhdr[0] & 0x01) == 0x01) {
Luiz Augusto Von Dentzfc180e22010-06-17 12:06:08 +0300245 DBG("Set to parent path");
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300246
Claudio Takahasieaa09662010-02-26 12:21:04 -0300247 if (root)
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300248 return -EPERM;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300249
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300250 fullname = g_path_get_dirname(ftp->folder);
251 set_folder(ftp, fullname);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300252 g_free(fullname);
253
Luiz Augusto Von Dentzfc180e22010-06-17 12:06:08 +0300254 DBG("Set to parent path: %s", ftp->folder);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300255
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300256 return 0;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300257 }
258
Claudio Takahasieaa09662010-02-26 12:21:04 -0300259 if (!name) {
Luiz Augusto Von Dentzfc180e22010-06-17 12:06:08 +0300260 DBG("Set path failed: name missing!");
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300261 return -EINVAL;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300262 }
263
Claudio Takahasieaa09662010-02-26 12:21:04 -0300264 if (strlen(name) == 0) {
Luiz Augusto Von Dentzfc180e22010-06-17 12:06:08 +0300265 DBG("Set to root");
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300266 set_folder(ftp, root_folder);
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300267 return 0;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300268 }
269
270 /* Check and set to name path */
Slawomir Bochenski6b5d9542011-08-01 15:44:57 +0200271 if (!is_filename(name)) {
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300272 error("Set path failed: name incorrect!");
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300273 return -EPERM;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300274 }
275
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300276 fullname = g_build_filename(ftp->folder, name, NULL);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300277
Luiz Augusto Von Dentzfc180e22010-06-17 12:06:08 +0300278 DBG("Fullname: %s", fullname);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300279
Slawomir Bochenskida050e82011-08-04 15:45:03 +0200280 err = verify_path(fullname);
Marek Kasik16102002016-06-30 17:01:27 -0400281 if (err == -ENOENT)
282 goto not_found;
Slawomir Bochenskida050e82011-08-04 15:45:03 +0200283
284 if (err < 0)
285 goto done;
286
287 err = stat(fullname, &dstat);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300288
289 if (err < 0) {
Luiz Augusto Von Dentze265df72010-04-27 16:25:39 +0300290 err = -errno;
291
292 if (err == -ENOENT)
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300293 goto not_found;
294
Slawomir Bochenskida050e82011-08-04 15:45:03 +0200295 DBG("stat: %s(%d)", strerror(-err), -err);
Luiz Augusto Von Dentze265df72010-04-27 16:25:39 +0300296
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300297 goto done;
298 }
299
300 if (S_ISDIR(dstat.st_mode) && (dstat.st_mode & S_IRUSR) &&
301 (dstat.st_mode & S_IXUSR)) {
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300302 set_folder(ftp, fullname);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300303 goto done;
304 }
305
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300306 err = -EPERM;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300307 goto done;
308
309not_found:
310 if (nonhdr[0] != 0) {
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300311 err = -ENOENT;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300312 goto done;
313 }
314
315 if (mkdir(fullname, 0755) < 0) {
Luiz Augusto Von Dentze265df72010-04-27 16:25:39 +0300316 err = -errno;
Luiz Augusto Von Dentzfc180e22010-06-17 12:06:08 +0300317 DBG("mkdir: %s(%d)", strerror(-err), -err);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300318 goto done;
319 }
320
Luiz Augusto Von Dentze265df72010-04-27 16:25:39 +0300321 err = 0;
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300322 set_folder(ftp, fullname);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300323
324done:
325 g_free(fullname);
Vinicius Costa Gomes84786d52010-03-02 21:03:54 -0300326 return err;
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300327}
328
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200329static gboolean is_valid_path(const char *path)
330{
Marcel Holtmannc59ae992013-01-04 12:27:55 -0800331 char **elements, **cur;
Luiz Augusto von Dentz1f3e8d22011-11-02 15:09:55 +0200332 int depth = 0;
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200333
Luiz Augusto von Dentz1f3e8d22011-11-02 15:09:55 +0200334 elements = g_strsplit(path, "/", 0);
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200335
Luiz Augusto von Dentz1f3e8d22011-11-02 15:09:55 +0200336 for (cur = elements; *cur != NULL; cur++) {
337 if (**cur == '\0' || strcmp(*cur, ".") == 0)
338 continue;
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200339
Luiz Augusto von Dentz1f3e8d22011-11-02 15:09:55 +0200340 if (strcmp(*cur, "..") == 0) {
341 depth--;
342 if (depth < 0)
343 break;
344 continue;
345 }
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200346
Luiz Augusto von Dentz1f3e8d22011-11-02 15:09:55 +0200347 depth++;
348 }
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200349
Luiz Augusto von Dentz1f3e8d22011-11-02 15:09:55 +0200350 g_strfreev(elements);
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200351
352 if (depth < 0)
353 return FALSE;
354
355 return TRUE;
356}
357
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300358static char *ftp_build_filename(struct ftp_session *ftp, const char *destname)
359{
360 char *filename;
361
362 /* DestName can either be relative or absolute (FTP style) */
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200363 if (destname[0] == '/')
Luiz Augusto von Dentzc1781672011-11-02 15:09:50 +0200364 filename = g_build_filename(obex_option_root_folder(),
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200365 destname, NULL);
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300366 else
367 filename = g_build_filename(ftp->folder, destname, NULL);
368
Luiz Augusto von Dentzc1781672011-11-02 15:09:50 +0200369 if (is_valid_path(filename + strlen(obex_option_root_folder())))
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300370 return filename;
371
372 g_free(filename);
373
374 return NULL;
375}
376
377static int ftp_copy(struct ftp_session *ftp, const char *name,
378 const char *destname)
379{
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200380 char *source, *destination, *destdir;
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300381 int ret;
382
383 DBG("%p name %s destination %s", ftp, name, destname);
384
385 if (ftp->folder == NULL) {
386 error("No folder set");
387 return -ENOENT;
388 }
389
390 if (name == NULL || destname == NULL)
391 return -EINVAL;
392
393 destination = ftp_build_filename(ftp, destname);
394
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200395 if (destination == NULL)
396 return -EBADR;
397
398 destdir = g_path_get_dirname(destination);
399 ret = verify_path(destdir);
400 g_free(destdir);
401
402 if (ret < 0)
403 return ret;
404
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300405 source = g_build_filename(ftp->folder, name, NULL);
406
407 ret = obex_copy(ftp->os, source, destination);
408
409 g_free(source);
410 g_free(destination);
411
412 return ret;
413}
414
415static int ftp_move(struct ftp_session *ftp, const char *name,
416 const char *destname)
417{
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200418 char *source, *destination, *destdir;
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300419 int ret;
420
421 DBG("%p name %s destname %s", ftp, name, destname);
422
423 if (ftp->folder == NULL) {
424 error("No folder set");
425 return -ENOENT;
426 }
427
428 if (name == NULL || destname == NULL)
429 return -EINVAL;
430
431 destination = ftp_build_filename(ftp, destname);
432
Slawomir Bochenskic38a2232011-08-05 08:40:31 +0200433 if (destination == NULL)
434 return -EBADR;
435
436 destdir = g_path_get_dirname(destination);
437 ret = verify_path(destdir);
438 g_free(destdir);
439
440 if (ret < 0)
441 return ret;
442
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300443 source = g_build_filename(ftp->folder, name, NULL);
444
445 ret = obex_move(ftp->os, source, destination);
446
447 g_free(source);
448 g_free(destination);
449
450 return ret;
451}
452
Luiz Augusto von Dentz7c358982011-11-15 15:27:55 +0200453int ftp_action(struct obex_session *os, void *user_data)
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300454{
455 struct ftp_session *ftp = user_data;
456 const char *name, *destname;
457 uint8_t action_id;
458
459 name = obex_get_name(os);
Slawomir Bochenskic32fc4f2011-08-09 10:44:39 +0200460 if (name == NULL || !is_filename(name))
461 return -EBADR;
462
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300463 destname = obex_get_destname(os);
464 action_id = obex_get_action_id(os);
465
466 DBG("%p action 0x%x", ftp, action_id);
467
468 switch (action_id) {
469 case 0x00: /* Copy Object */
470 return ftp_copy(ftp, name, destname);
471 case 0x01: /* Move/Rename Object */
472 return ftp_move(ftp, name, destname);
473 default:
Luiz Augusto von Dentz93c9b5a2012-02-18 17:19:01 +0200474 return -ENOSYS;
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300475 }
476}
477
Luiz Augusto von Dentz41323662011-02-26 16:49:41 -0300478void ftp_disconnect(struct obex_session *os, void *user_data)
Luiz Augusto von Dentz5bb6f1c2009-11-09 16:00:41 -0300479{
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300480 struct ftp_session *ftp = user_data;
481
Luiz Augusto von Dentz8e773042011-02-23 11:54:37 +0200482 DBG("%p", ftp);
483
Claudio Takahasi815bfac2010-02-25 17:57:49 -0300484 manager_unregister_session(os);
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300485
Bharat Panda1e5a31d2014-10-30 20:29:24 +0530486 manager_unregister_transfer(ftp->transfer);
487
Vinicius Costa Gomes4ce2d8b2010-03-15 14:41:47 -0300488 g_free(ftp->folder);
489 g_free(ftp);
Luiz Augusto von Dentz5bb6f1c2009-11-09 16:00:41 -0300490}
491
Bharat Panda1e5a31d2014-10-30 20:29:24 +0530492static void ftp_progress(struct obex_session *os, void *user_data)
493{
494 struct ftp_session *ftp = user_data;
495
496 manager_emit_transfer_progress(ftp->transfer);
497}
498
Bharat Panda11703a42014-10-31 21:16:47 +0530499static void ftp_reset(struct obex_session *os, void *user_data)
500{
501 struct ftp_session *ftp = user_data;
502
503 manager_emit_transfer_completed(ftp->transfer);
504}
505
Vinicius Costa Gomes539120c2010-03-31 18:09:51 -0300506static struct obex_service_driver ftp = {
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300507 .name = "File Transfer server",
508 .service = OBEX_FTP,
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300509 .target = FTP_TARGET,
Forrest Zhao19e380e2009-11-16 15:17:47 +0800510 .target_size = TARGET_SIZE,
Luiz Augusto von Dentz5bb6f1c2009-11-09 16:00:41 -0300511 .connect = ftp_connect,
Bharat Panda1e5a31d2014-10-30 20:29:24 +0530512 .progress = ftp_progress,
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300513 .get = ftp_get,
514 .put = ftp_put,
515 .chkput = ftp_chkput,
Luiz Augusto von Dentz5bb6f1c2009-11-09 16:00:41 -0300516 .setpath = ftp_setpath,
Luiz Augusto von Dentzfeeb8b32011-06-17 09:26:45 +0300517 .action = ftp_action,
Bharat Panda11703a42014-10-31 21:16:47 +0530518 .disconnect = ftp_disconnect,
519 .reset = ftp_reset
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300520};
521
522static int ftp_init(void)
523{
Luiz Augusto von Dentz41323662011-02-26 16:49:41 -0300524 return obex_service_driver_register(&ftp);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300525}
526
527static void ftp_exit(void)
528{
529 obex_service_driver_unregister(&ftp);
Luiz Augusto von Dentz67e2aa62009-11-03 11:05:00 -0300530}
531
Luiz Augusto von Dentz7aa82b32009-11-03 11:11:19 -0300532OBEX_PLUGIN_DEFINE(ftp, ftp_init, ftp_exit)