~ubuntu-branches/ubuntu/maverick/obexd/maverick

« back to all changes in this revision

Viewing changes to plugins/pbap.c

  • Committer: Bazaar Package Importer
  • Author(s): Nobuhiro Iwamatsu
  • Date: 2010-04-27 04:17:15 UTC
  • mfrom: (0.1.3 sid) (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20100427041715-9dv1jqg73bs6xxr9
Tags: 0.23-1
* New upstream release (Closes: #558710).
* Update debian/control.
  - Remove Filippo Giunchedi <filippo@debian.org> from uploaders.
  - Add Nobuhiro Iwamatsu to Uploaders (Closes: #564570).
  - Bumped standards-version to 3.8.4.
  - Update description (Closes: #541880).
* Add debian/source/format.
  Set source format to "1.0". 

Show diffs side-by-side

added added

removed removed

Lines of Context:
29
29
#include <string.h>
30
30
#include <errno.h>
31
31
#include <glib.h>
32
 
#include <bluetooth/bluetooth.h>
 
32
#include <stdlib.h>
 
33
#include <unistd.h>
 
34
#include <sys/types.h>
 
35
#include <sys/stat.h>
 
36
#include <fcntl.h>
33
37
 
34
38
#include <openobex/obex.h>
35
39
#include <openobex/obex_const.h>
39
43
#include "obex.h"
40
44
#include "service.h"
41
45
#include "phonebook.h"
42
 
#include "telephony.h"
 
46
#include "mimetype.h"
 
47
#include "filesystem.h"
43
48
#include "dbus.h"
44
49
 
45
50
#define PHONEBOOK_TYPE          "x-bt/phonebook"
73
78
 
74
79
#define APPARAM_HDR_SIZE 2
75
80
 
76
 
#define get_be64(val)   GUINT64_FROM_BE(bt_get_unaligned((guint64 *) val))
77
 
#define get_be16(val)   GUINT16_FROM_BE(bt_get_unaligned((guint16 *) val))
78
 
 
79
 
#define put_be16(val, ptr) bt_put_unaligned(GUINT16_TO_BE(val), (guint16 *) ptr)
80
 
 
81
81
#define PBAP_CHANNEL    15
82
82
 
83
83
#define PBAP_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>        \
121
121
  </attribute>                                                                  \
122
122
</record>"
123
123
 
124
 
struct apparam_hdr {
 
124
struct aparam_header {
125
125
        uint8_t         tag;
126
126
        uint8_t         len;
127
127
        uint8_t         val[0];
128
128
} __attribute__ ((packed));
129
129
 
 
130
struct pbap_session {
 
131
        struct obex_session *os;
 
132
        struct apparam_field *params;
 
133
        gchar *folder;
 
134
        GString *buffer;
 
135
};
 
136
 
130
137
static const guint8 PBAP_TARGET[TARGET_SIZE] = {
131
138
                        0x79, 0x61, 0x35, 0xF0,  0xF0, 0xC5, 0x11, 0xD8,
132
139
                        0x09, 0x66, 0x08, 0x00,  0x20, 0x0C, 0x9A, 0x66  };
133
140
 
134
 
static int pbap_parse_apparam_header(obex_t *obex, obex_object_t *obj,
135
 
                                                struct apparam_field *apparam)
136
 
{
137
 
        obex_headerdata_t hd;
138
 
        guint8 hi;
139
 
        guint32 hlen;
140
 
 
141
 
        while (OBEX_ObjectGetNextHeader(obex, obj, &hi, &hd, &hlen)) {
142
 
                void *ptr = (void *) hd.bs;
143
 
                uint32_t len = hlen;
144
 
 
145
 
                if (hi != OBEX_HDR_APPARAM)
146
 
                        continue;
147
 
 
148
 
                if (hlen < APPARAM_HDR_SIZE) {
149
 
                        g_free(apparam->searchval);
150
 
                        error("PBAP pullphonebook app parameters header"
151
 
                                                " is too short: %d", hlen);
152
 
                        return -1;
153
 
                }
154
 
 
155
 
                while (len > APPARAM_HDR_SIZE) {
156
 
                        struct apparam_hdr *hdr = ptr;
157
 
 
158
 
                        if (hdr->len > len - APPARAM_HDR_SIZE) {
159
 
                                g_free(apparam->searchval);
160
 
                                error("Unexpected PBAP pullphonebook app"
161
 
                                                " length, tag %d, len %d",
162
 
                                                        hdr->tag, hdr->len);
163
 
                                return -1;
164
 
                        }
165
 
 
166
 
                        switch (hdr->tag) {
167
 
                        case ORDER_TAG:
168
 
                                if (hdr->len == ORDER_LEN)
169
 
                                        apparam->order = hdr->val[0];
170
 
                                break;
171
 
                        case SEARCHATTRIB_TAG:
172
 
                                if (hdr->len == SEARCHATTRIB_LEN)
173
 
                                        apparam->searchattrib = hdr->val[0];
174
 
                                break;
175
 
                        case SEARCHVALUE_TAG:
176
 
                                apparam->searchval = g_try_malloc(hdr->len + 1);
177
 
                                if (apparam->searchval != NULL) {
178
 
                                        memcpy(apparam->searchval, hdr->val,
179
 
                                                                hdr->len);
180
 
                                        apparam->searchval[hdr->len] = '\0';
181
 
                                }
182
 
                                break;
183
 
                        case FILTER_TAG:
184
 
                                if (hdr->len == FILTER_LEN) {
185
 
                                        guint64 val;
186
 
                                        memcpy(&val, hdr->val, sizeof(val));
187
 
                                        apparam->filter = get_be64(&val);
188
 
                                }
189
 
                                break;
190
 
                        case FORMAT_TAG:
191
 
                                if (hdr->len == FORMAT_LEN)
192
 
                                        apparam->format = hdr->val[0];
193
 
                                break;
194
 
                        case MAXLISTCOUNT_TAG:
195
 
                                if (hdr->len == MAXLISTCOUNT_LEN) {
196
 
                                        guint16 val;
197
 
                                        memcpy(&val, hdr->val, sizeof(val));
198
 
                                        apparam->maxlistcount = get_be16(&val);
199
 
                                }
200
 
                                break;
201
 
                        case LISTSTARTOFFSET_TAG:
202
 
                                if (hdr->len == LISTSTARTOFFSET_LEN) {
203
 
                                        guint16 val;
204
 
                                        memcpy(&val, hdr->val, sizeof(val));
205
 
                                        apparam->liststartoffset = get_be16(&val);
206
 
                                }
207
 
                                break;
208
 
                        default:
209
 
                                g_free(apparam->searchval);
210
 
                                error("Unexpected PBAP pullphonebook app"
211
 
                                                " parameter, tag %d, len %d",
212
 
                                                        hdr->tag, hdr->len);
213
 
                                return -1;
214
 
                        }
215
 
 
216
 
                        ptr += APPARAM_HDR_SIZE + hdr->len;
217
 
                        len -= APPARAM_HDR_SIZE + hdr->len;
218
 
                }
219
 
 
220
 
                /* Ignore multiple app param headers */
221
 
                break;
222
 
        }
223
 
 
224
 
        return 0;
225
 
}
226
 
 
227
 
/* Add app parameter header, that is sent back to PBAP client */
228
 
static int pbap_add_result_apparam_header(obex_t *obex, obex_object_t *obj,
229
 
                                guint16 maxlistcount, gchar *path_name,
230
 
                                guint16 phonebooksize,
231
 
                                guint8 newmissedcalls, gboolean *addbody)
232
 
{
233
 
        guint8 rspsize = 0;
234
 
        gboolean addmissedcalls = FALSE;
235
 
        obex_headerdata_t hd;
236
 
 
237
 
        if (maxlistcount == 0) {
238
 
                rspsize += APPARAM_HDR_SIZE + PHONEBOOKSIZE_LEN;
239
 
                *addbody = FALSE;
240
 
        }
241
 
 
242
 
        if (g_str_equal(path_name, SIM1_MCH) == TRUE ||
243
 
                                g_str_equal(path_name, MCH) == TRUE) {
244
 
                rspsize += APPARAM_HDR_SIZE + NEWMISSEDCALLS_LEN;
245
 
                addmissedcalls = TRUE;
246
 
        }
247
 
 
248
 
        if (rspsize > 0) {
249
 
                void *buf, *ptr;
250
 
 
251
 
                buf = g_try_malloc0(rspsize);
252
 
                if (buf == NULL)
253
 
                        return -ENOMEM;
254
 
 
255
 
                ptr = buf;
256
 
 
257
 
                if (maxlistcount == 0) {
258
 
                        struct apparam_hdr *hdr = ptr;
259
 
                        guint16 val = GUINT16_TO_BE(phonebooksize);
260
 
 
261
 
                        hdr->tag = PHONEBOOKSIZE_TAG;
262
 
                        hdr->len = PHONEBOOKSIZE_LEN;
263
 
                        memcpy(hdr->val, &val, sizeof(val));
264
 
 
265
 
                        ptr += APPARAM_HDR_SIZE + PHONEBOOKSIZE_LEN;
266
 
                }
267
 
 
268
 
                if (addmissedcalls == TRUE) {
269
 
                        struct apparam_hdr *hdr = ptr;
270
 
 
271
 
                        hdr->tag = NEWMISSEDCALLS_TAG;
272
 
                        hdr->len = NEWMISSEDCALLS_LEN;
273
 
                        hdr->val[0] = newmissedcalls;
274
 
 
275
 
                        ptr += APPARAM_HDR_SIZE + NEWMISSEDCALLS_LEN;
276
 
                }
277
 
 
278
 
                hd.bs = buf;
279
 
                OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_APPARAM,
280
 
                                                        hd, rspsize, 0);
281
 
                g_free(buf);
282
 
        }
283
 
 
284
 
        return 0;
285
 
}
286
 
 
287
 
static int pbap_pullphonebook(obex_t *obex, obex_object_t *obj,
288
 
                                                        gboolean *addbody)
289
 
{
290
 
        struct obex_session *session = OBEX_GetUserData(obex);
291
 
        struct apparam_field params;
292
 
        guint8 newmissedcalls = 0;
293
 
        guint16 phonebooksize = 0;
294
 
        int err;
295
 
 
296
 
        memset(&params, 0, sizeof(struct apparam_field));
297
 
 
298
 
        err = pbap_parse_apparam_header(obex, obj, &params);
299
 
        if (err < 0)
300
 
                return err;
301
 
 
302
 
        if (params.maxlistcount == 0) {
303
 
                phonebooksize = DEFAULT_COUNT;
304
 
                goto done;
305
 
        }
306
 
 
307
 
        err = phonebook_pullphonebook(obex, obj, params);
308
 
        if (err < 0)
309
 
                return err;
310
 
 
311
 
done:
312
 
        return pbap_add_result_apparam_header(obex, obj, params.maxlistcount,
313
 
                                                session->name, phonebooksize,
314
 
                                                newmissedcalls, addbody);
315
 
}
316
 
 
317
 
static int pbap_pullvcardlisting(obex_t *obex, obex_object_t *obj,
318
 
                                                        gboolean *addbody)
319
 
{
320
 
        struct obex_session *session = OBEX_GetUserData(obex);
321
 
        gchar *fullname;
322
 
        struct apparam_field params;
323
 
        guint8 newmissedcalls = 0;
324
 
        guint16 phonebooksize = 0;
325
 
        int err;
326
 
 
327
 
        memset(&params, 0, sizeof(struct apparam_field));
328
 
 
329
 
        err = pbap_parse_apparam_header(obex, obj, &params);
330
 
        if (err < 0)
331
 
                return err;
332
 
 
333
 
        if (params.maxlistcount == 0) {
334
 
                phonebooksize = DEFAULT_COUNT;
335
 
                goto proceed;
336
 
        }
337
 
 
338
 
        /* libebook does not support sound attribute */
339
 
        if (params.searchattrib >= 2) {
340
 
                DBG("libebook does not support sound attribute");
341
 
                goto done;
342
 
        }
343
 
 
344
 
        err = phonebook_pullvcardlisting(obex, obj, params);
345
 
        if (err < 0)
346
 
                goto done;
347
 
 
348
 
proceed:
349
 
 
350
 
        fullname = g_build_filename(session->current_folder, session->name,
351
 
                                                                NULL);
352
 
        if (fullname != NULL)
353
 
                fullname = g_strconcat(fullname, ".vcf", NULL);
354
 
 
355
 
        err = pbap_add_result_apparam_header(obex, obj, params.maxlistcount,
356
 
                                                fullname, phonebooksize,
357
 
                                                newmissedcalls, addbody);
358
 
        g_free(fullname);
359
 
 
360
 
done:
361
 
        g_free(params.searchval);
362
 
        return err;
363
 
}
364
 
 
365
 
static int pbap_pullvcardentry(obex_t *obex, obex_object_t *obj)
366
 
{
367
 
        struct apparam_field params;
368
 
        int err;
369
 
 
370
 
        memset(&params, 0, sizeof(struct apparam_field));
371
 
        err = pbap_parse_apparam_header(obex, obj, &params);
372
 
        if (err < 0)
373
 
                return err;
374
 
 
375
 
        err = phonebook_pullvcardentry(obex, obj, params);
376
 
 
377
 
        g_free(params.searchval);
378
 
        return err;
379
 
}
380
 
 
381
 
static void pbap_connect(obex_t *obex, obex_object_t *obj)
382
 
{
383
 
        struct obex_session *os = OBEX_GetUserData(obex);
384
 
        obex_headerdata_t hd;
385
 
 
386
 
        register_session(os->cid, os);
387
 
        emit_session_created(os->cid);
388
 
 
389
 
        /* Append received UUID in WHO header */
390
 
        hd.bs = PBAP_TARGET;
391
 
        OBEX_ObjectAddHeader(obex, obj,
392
 
                        OBEX_HDR_WHO, hd, sizeof(PBAP_TARGET),
393
 
                        OBEX_FL_FIT_ONE_PACKET);
394
 
        hd.bq4 = os->cid;
395
 
        OBEX_ObjectAddHeader(obex, obj,
396
 
                        OBEX_HDR_CONNECTION, hd, 4,
397
 
                        OBEX_FL_FIT_ONE_PACKET);
398
 
 
399
 
        OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
400
 
}
401
 
 
402
 
static void pbap_get(obex_t *obex, obex_object_t *obj)
403
 
{
404
 
        struct obex_session *session = OBEX_GetUserData(obex);
405
 
        obex_headerdata_t hd;
406
 
        gboolean addbody = TRUE;
407
 
        int err;
408
 
 
409
 
        if (session == NULL)
410
 
                return;
411
 
 
412
 
        if (session->type == NULL)
413
 
                goto fail;
414
 
 
415
 
        if (g_str_equal(session->type, VCARDLISTING_TYPE) == FALSE
416
 
                                                && session->name == NULL)
417
 
                goto fail;
418
 
 
419
 
        OBEX_ObjectReParseHeaders(obex, obj);
420
 
 
421
 
        if (g_str_equal(session->type, PHONEBOOK_TYPE) == TRUE)
422
 
                err = pbap_pullphonebook(obex, obj, &addbody);
423
 
        else if (g_str_equal(session->type, VCARDLISTING_TYPE) == TRUE)
424
 
                err = pbap_pullvcardlisting(obex, obj, &addbody);
425
 
        else if (g_str_equal(session->type, VCARDENTRY_TYPE) == TRUE)
426
 
                err = pbap_pullvcardentry(obex, obj);
 
141
static void set_folder(struct pbap_session *pbap, const char *new_folder)
 
142
{
 
143
        g_free(pbap->folder);
 
144
 
 
145
        pbap->folder = new_folder ? g_strdup(new_folder) : NULL;
 
146
}
 
147
 
 
148
static struct apparam_field *parse_aparam(const guint8 *buffer, guint32 hlen)
 
149
{
 
150
        struct apparam_field *param;
 
151
        struct aparam_header *hdr;
 
152
        guint32 len = 0;
 
153
        guint16 val16;
 
154
        guint64 val64;
 
155
 
 
156
        param = g_new0(struct apparam_field, 1);
 
157
 
 
158
        while (len < hlen) {
 
159
                hdr = (void *) buffer + len;
 
160
 
 
161
                switch (hdr->tag) {
 
162
                case ORDER_TAG:
 
163
                        if (hdr->len != ORDER_LEN)
 
164
                                goto failed;
 
165
 
 
166
                        param->order = hdr->val[0];
 
167
                        break;
 
168
 
 
169
                case SEARCHATTRIB_TAG:
 
170
                        if (hdr->len != SEARCHATTRIB_LEN)
 
171
                                goto failed;
 
172
 
 
173
                        param->searchattrib = hdr->val[0];
 
174
                        break;
 
175
                case SEARCHVALUE_TAG:
 
176
                        param->searchval = g_try_malloc0(hdr->len + 1);
 
177
                        if (param->searchval)
 
178
                                memcpy(param->searchval, hdr->val, hdr->len);
 
179
                        break;
 
180
                case FILTER_TAG:
 
181
                        if (hdr->len != FILTER_LEN)
 
182
                                goto failed;
 
183
 
 
184
                        memcpy(&val64, hdr->val, sizeof(val64));
 
185
                        param->filter = GUINT64_FROM_BE(val64);
 
186
 
 
187
                        break;
 
188
                case FORMAT_TAG:
 
189
                        if (hdr->len != FORMAT_LEN)
 
190
                                goto failed;
 
191
 
 
192
                        param->format = hdr->val[0];
 
193
                        break;
 
194
                case MAXLISTCOUNT_TAG:
 
195
                        if (hdr->len != MAXLISTCOUNT_LEN)
 
196
                                goto failed;
 
197
 
 
198
                        memcpy(&val16, hdr->val, sizeof(val16));
 
199
                        param->maxlistcount = GUINT16_FROM_BE(val16);
 
200
                        break;
 
201
                case LISTSTARTOFFSET_TAG:
 
202
                        if (hdr->len != LISTSTARTOFFSET_LEN)
 
203
                                goto failed;
 
204
 
 
205
                        memcpy(&val16, hdr->val, sizeof(val16));
 
206
                        param->liststartoffset = GUINT16_FROM_BE(val16);
 
207
                        break;
 
208
                default:
 
209
                        goto failed;
 
210
                }
 
211
 
 
212
                len += hdr->len + sizeof(struct aparam_header);
 
213
        }
 
214
 
 
215
        return param;
 
216
 
 
217
failed:
 
218
        g_free(param);
 
219
 
 
220
        return NULL;
 
221
}
 
222
 
 
223
static gpointer pbap_connect(struct obex_session *os, int *err)
 
224
{
 
225
        struct pbap_session *pbap;
 
226
 
 
227
        manager_register_session(os);
 
228
 
 
229
        pbap = g_new0(struct pbap_session, 1);
 
230
        pbap->folder = g_strdup("/");
 
231
        pbap->os = os;
 
232
 
 
233
        if (err)
 
234
                *err = 0;
 
235
 
 
236
        return pbap;
 
237
}
 
238
 
 
239
static int pbap_get(struct obex_session *os, obex_object_t *obj,
 
240
                gpointer user_data)
 
241
{
 
242
        struct pbap_session *pbap = user_data;
 
243
        const gchar *type = obex_get_type(os);
 
244
        const gchar *name = obex_get_name(os);
 
245
        struct apparam_field *params;
 
246
        const guint8 *buffer;
 
247
        gchar *path;
 
248
        ssize_t rsize;
 
249
        gint ret;
 
250
 
 
251
        if (type == NULL)
 
252
                return -EBADR;
 
253
 
 
254
        if (strcmp(type, PHONEBOOK_TYPE) == 0)
 
255
                /* Always contains the absolute path */
 
256
                path = g_strdup(name);
 
257
        else if (strcmp(type, VCARDLISTING_TYPE) == 0)
 
258
                /* Always relative */
 
259
                if (!name || strlen(name) == 0)
 
260
                        /* Current folder */
 
261
                        path = g_strdup(pbap->folder);
 
262
                else
 
263
                        /* Current folder + relative path */
 
264
                        path = g_build_filename(pbap->folder, name, NULL);
 
265
 
 
266
        else if (strcmp(type, VCARDENTRY_TYPE) == 0)
 
267
                /* Always relative */
 
268
                path = g_build_filename(pbap->folder, name, NULL);
427
269
        else
428
 
                goto fail;
429
 
 
430
 
        if (err < 0)
431
 
                goto fail;
432
 
 
433
 
        if (addbody == TRUE) {
434
 
                OBEX_SuspendRequest(obex, obj);
435
 
                session->size = 0;
436
 
 
437
 
                /* Add body header */
438
 
                hd.bs = NULL;
439
 
                OBEX_ObjectAddHeader(obex, obj, OBEX_HDR_BODY,
440
 
                                                hd, 0, OBEX_FL_STREAM_START);
441
 
        }
442
 
 
443
 
        OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS);
444
 
 
445
 
        return;
446
 
 
447
 
fail:
448
 
        OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
449
 
}
450
 
 
451
 
static gboolean pbap_is_valid_folder(struct obex_session *session)
452
 
{
453
 
        if (session->current_folder == NULL) {
454
 
                if (g_str_equal(session->name, "telecom") == TRUE ||
455
 
                        g_str_equal(session->name, "SIM1") == TRUE)
456
 
                        return TRUE;
457
 
        } else if (g_str_equal(session->current_folder, "SIM1") == TRUE) {
458
 
                if (g_str_equal(session->name, "telecom") == TRUE)
459
 
                        return TRUE;
460
 
        } else if (g_str_equal(session->current_folder, "telecom") == TRUE ||
461
 
                g_str_equal(session->current_folder, "SIM1/telecom") == TRUE) {
462
 
                if (g_str_equal(session->name, "pb") == TRUE ||
463
 
                                g_str_equal(session->name, "ich") == TRUE ||
464
 
                                g_str_equal(session->name, "och") == TRUE ||
465
 
                                g_str_equal(session->name, "mch") == TRUE ||
466
 
                                g_str_equal(session->name, "cch") == TRUE)
467
 
                        return TRUE;
468
 
        }
469
 
 
470
 
        return FALSE;
471
 
}
472
 
 
473
 
static void pbap_setpath(obex_t *obex, obex_object_t *obj)
474
 
{
475
 
        struct obex_session *session = OBEX_GetUserData(obex);
 
270
                return -EBADR;
 
271
 
 
272
        rsize = obex_aparam_read(os, obj, &buffer);
 
273
        if (rsize < 0) {
 
274
                ret = -EBADR;
 
275
                goto failed;
 
276
        }
 
277
 
 
278
        params = parse_aparam(buffer, rsize);
 
279
        if (params == NULL) {
 
280
                ret = -EBADR;
 
281
                goto failed;
 
282
        }
 
283
 
 
284
        if (pbap->params) {
 
285
                g_free(pbap->params->searchval);
 
286
                g_free(pbap->params);
 
287
        }
 
288
 
 
289
        pbap->params = params;
 
290
        ret = obex_stream_start(os, path, pbap);
 
291
 
 
292
failed:
 
293
        g_free(path);
 
294
 
 
295
        return ret;
 
296
}
 
297
 
 
298
 
 
299
static int pbap_setpath(struct obex_session *os, obex_object_t *obj,
 
300
                gpointer user_data)
 
301
{
 
302
        struct pbap_session *pbap = user_data;
 
303
        const gchar *name;
476
304
        guint8 *nonhdr;
477
305
        gchar *fullname;
 
306
        int ret;
478
307
 
479
308
        if (OBEX_ObjectGetNonHdrData(obj, &nonhdr) != 2) {
480
 
                OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE,
481
 
                                OBEX_RSP_PRECONDITION_FAILED);
482
309
                error("Set path failed: flag and constants not found!");
483
 
                return;
484
 
        }
485
 
 
486
 
        /* Check "Backup" flag */
487
 
        if ((nonhdr[0] & 0x01) == 0x01) {
488
 
                debug("Set to parent path");
489
 
 
490
 
                if (session->current_folder == NULL) {
491
 
                        /* we are already in top level folder */
492
 
                        OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN,
493
 
                                        OBEX_RSP_FORBIDDEN);
494
 
                        return;
495
 
                }
496
 
 
497
 
                fullname = g_path_get_dirname(session->current_folder);
498
 
                g_free(session->current_folder);
499
 
 
500
 
                if (strlen(fullname) == 1 && *fullname == '.')
501
 
                        session->current_folder = NULL;
502
 
                else
503
 
                        session->current_folder = g_strdup(fullname);
504
 
 
505
 
                g_free(fullname);
506
 
 
507
 
                debug("Set to parent path: %s", session->current_folder);
508
 
 
509
 
                OBEX_ObjectSetRsp(obj, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS);
510
 
                return;
511
 
        }
512
 
 
513
 
        if (!session->name) {
514
 
                OBEX_ObjectSetRsp(obj, OBEX_RSP_CONTINUE, OBEX_RSP_BAD_REQUEST);
515
 
                error("Set path failed: name missing!");
516
 
                return;
517
 
        }
518
 
 
519
 
        if (strlen(session->name) == 0) {
520
 
                debug("Set to root");
521
 
 
522
 
                g_free(session->current_folder);
523
 
                session->current_folder = NULL;
524
 
 
525
 
                OBEX_ObjectSetRsp(obj, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS);
526
 
                return;
527
 
        }
528
 
 
529
 
        /* Check and set to name path */
530
 
        if (strstr(session->name, "/")) {
531
 
                OBEX_ObjectSetRsp(obj, OBEX_RSP_FORBIDDEN, OBEX_RSP_FORBIDDEN);
532
 
                error("Set path failed: name incorrect!");
533
 
                return;
534
 
        }
535
 
 
536
 
        if (pbap_is_valid_folder(session) == FALSE) {
537
 
                OBEX_ObjectSetRsp(obj, OBEX_RSP_NOT_FOUND, OBEX_RSP_NOT_FOUND);
538
 
                return;
539
 
        }
540
 
 
541
 
        if (session->current_folder == NULL)
542
 
                fullname = g_build_filename("", session->name, NULL);
 
310
                return -EBADMSG;
 
311
        }
 
312
 
 
313
        name = obex_get_name(os);
 
314
 
 
315
        ret = phonebook_set_folder(pbap->folder, name, nonhdr[0]);
 
316
        if (ret < 0)
 
317
                return ret;
 
318
 
 
319
        if (!pbap->folder)
 
320
                fullname = g_strdup(name);
543
321
        else
544
 
                fullname = g_build_filename(session->current_folder, session->name, NULL);
545
 
 
546
 
        debug("Fullname: %s", fullname);
547
 
 
548
 
        g_free(session->current_folder);
549
 
        session->current_folder = fullname;
550
 
        OBEX_ObjectSetRsp(obj, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS);
 
322
                fullname = g_build_filename(pbap->folder, name, NULL);
 
323
 
 
324
        set_folder(pbap, fullname);
 
325
 
 
326
        g_free(fullname);
 
327
 
 
328
        return 0;
551
329
}
552
330
 
553
 
static void pbap_disconnect(obex_t *obex)
 
331
static void pbap_disconnect(struct obex_session *os,
 
332
                gpointer user_data)
554
333
{
555
 
        struct obex_session *os = OBEX_GetUserData(obex);
556
 
 
557
 
        emit_session_removed(os->cid);
558
 
        unregister_session(os->cid);
 
334
        struct pbap_session *pbap = user_data;
 
335
 
 
336
        manager_unregister_session(os);
 
337
 
 
338
        if (pbap->params) {
 
339
                g_free(pbap->params->searchval);
 
340
                g_free(pbap->params);
 
341
        }
 
342
 
 
343
        g_free(pbap->folder);
 
344
        g_free(pbap);
559
345
}
560
346
 
561
 
static gint pbap_chkput(obex_t *obex, obex_object_t *obj)
 
347
static gint pbap_chkput(struct obex_session *os,
 
348
                gpointer user_data)
562
349
{
563
350
        /* Rejects all PUTs */
564
351
        return -EINVAL;
578
365
        .chkput = pbap_chkput
579
366
};
580
367
 
 
368
static void query_result(const gchar *buffer, size_t bufsize,
 
369
                gint vcards, gint missed, gpointer user_data)
 
370
{
 
371
        struct pbap_session *pbap = user_data;
 
372
 
 
373
        if (!pbap->buffer)
 
374
                pbap->buffer = g_string_new_len(buffer, bufsize);
 
375
        else
 
376
                pbap->buffer = g_string_append_len(pbap->buffer, buffer, bufsize);
 
377
 
 
378
        obex_object_set_io_flags(pbap, G_IO_IN, 0);
 
379
}
 
380
 
 
381
static gpointer vobject_open(const char *name, int oflag, mode_t mode,
 
382
                gpointer context, size_t *size, int *err)
 
383
{
 
384
        struct pbap_session *pbap = context;
 
385
        int ret;
 
386
 
 
387
        if (oflag != O_RDONLY) {
 
388
                ret = -EPERM;
 
389
                goto fail;
 
390
        }
 
391
 
 
392
        ret = phonebook_pull(name, pbap->params, query_result, pbap);
 
393
        if (ret < 0)
 
394
                goto fail;
 
395
 
 
396
        if (size)
 
397
                *size = OBJECT_SIZE_UNKNOWN;
 
398
 
 
399
        return pbap;
 
400
 
 
401
fail:
 
402
        if (err)
 
403
                *err = ret;
 
404
 
 
405
        return NULL;
 
406
}
 
407
 
 
408
static ssize_t vobject_read(gpointer object, void *buf, size_t count)
 
409
{
 
410
        struct pbap_session *pbap = object;
 
411
 
 
412
        if (pbap->buffer)
 
413
                return string_read(pbap->buffer, buf, count);
 
414
 
 
415
        return -EAGAIN;
 
416
}
 
417
 
 
418
static int vobject_close(gpointer object)
 
419
{
 
420
        struct pbap_session *pbap = object;
 
421
 
 
422
        if (pbap->buffer) {
 
423
                string_free(pbap->buffer);
 
424
                pbap->buffer = NULL;
 
425
        }
 
426
 
 
427
        return 0;
 
428
}
 
429
 
 
430
struct obex_mime_type_driver mime_pull = {
 
431
        .target         = PBAP_TARGET,
 
432
        .mimetype       = "x-bt/phonebook",
 
433
        .open           = vobject_open,
 
434
        .close          = vobject_close,
 
435
        .read           = vobject_read,
 
436
};
 
437
 
 
438
struct obex_mime_type_driver mime_list = {
 
439
        .target         = PBAP_TARGET,
 
440
        .mimetype       = "x-bt/vcard-listing",
 
441
        .open           = vobject_open,
 
442
        .close          = vobject_close,
 
443
        .read           = vobject_read,
 
444
};
 
445
 
 
446
struct obex_mime_type_driver mime_vcard = {
 
447
        .target         = PBAP_TARGET,
 
448
        .mimetype       = "x-bt/vcard",
 
449
        .open           = vobject_open,
 
450
        .close          = vobject_close,
 
451
        .read           = vobject_read,
 
452
};
 
453
 
581
454
static int pbap_init(void)
582
455
{
 
456
        int err;
 
457
 
 
458
        err = phonebook_init();
 
459
        if (err < 0)
 
460
                return err;
 
461
 
 
462
        err = obex_mime_type_driver_register(&mime_pull);
 
463
        if (err < 0)
 
464
                return err;
 
465
 
 
466
        err = obex_mime_type_driver_register(&mime_list);
 
467
        if (err < 0)
 
468
                return err;
 
469
 
 
470
        err = obex_mime_type_driver_register(&mime_vcard);
 
471
        if (err < 0)
 
472
                return err;
 
473
 
583
474
        return obex_service_driver_register(&pbap);
584
475
}
585
476
 
586
477
static void pbap_exit(void)
587
478
{
588
479
        obex_service_driver_unregister(&pbap);
 
480
        obex_mime_type_driver_unregister(&mime_pull);
 
481
        obex_mime_type_driver_unregister(&mime_list);
 
482
        obex_mime_type_driver_unregister(&mime_vcard);
 
483
        phonebook_exit();
589
484
}
590
485
 
591
486
OBEX_PLUGIN_DEFINE(pbap, pbap_init, pbap_exit)