Merge lp:~bluetooth/ubuntu/maverick/obexd/main into lp:ubuntu/maverick/obexd

Proposed by Baptiste Mille-Mathias
Status: Merged
Merge reported by: Daniel Holbach
Merged at revision: not available
Proposed branch: lp:~bluetooth/ubuntu/maverick/obexd/main
Merge into: lp:ubuntu/maverick/obexd
Diff against target: 10631 lines (+6085/-2141)
53 files modified
ChangeLog (+45/-0)
Makefile.am (+25/-7)
Makefile.in (+75/-35)
aclocal.m4 (+35/-0)
client/main.c (+28/-3)
client/session.c (+1/-1)
client/transfer.c (+6/-3)
compile (+143/-0)
config.h.in (+3/-0)
configure (+296/-24)
configure.ac (+23/-1)
debian/changelog (+40/-0)
debian/control (+2/-1)
debian/rules (+4/-0)
gdbus/object.c (+6/-2)
plugins/bluetooth.c (+609/-0)
plugins/filesystem.c (+126/-49)
plugins/filesystem.h (+2/-2)
plugins/ftp.c (+145/-169)
plugins/nokia-backup.c (+295/-0)
plugins/opp.c (+71/-61)
plugins/pbap.c (+633/-192)
plugins/phonebook-dummy.c (+491/-39)
plugins/phonebook-ebook.c (+332/-56)
plugins/phonebook-tracker.c (+825/-0)
plugins/phonebook.h (+74/-14)
plugins/syncevolution.c (+80/-72)
plugins/usb.c (+245/-0)
plugins/vcard.c (+327/-0)
plugins/vcard.h (+65/-0)
src/bluetooth.c (+0/-202)
src/bluetooth.h (+0/-34)
src/btio.c (+12/-12)
src/btio.h (+7/-7)
src/dbus.h (+2/-2)
src/logging.c (+32/-19)
src/main.c (+32/-186)
src/manager.c (+39/-412)
src/mimetype.c (+45/-12)
src/mimetype.h (+16/-14)
src/obex-priv.h (+23/-41)
src/obex.c (+422/-413)
src/obex.h (+16/-13)
src/plugin.c (+2/-2)
src/server.c (+146/-0)
src/server.h (+47/-0)
src/service.c (+8/-15)
src/service.h (+20/-18)
src/transport.c (+91/-0)
src/transport.h (+33/-0)
test/ftp-client (+9/-0)
test/pbap-client (+3/-0)
test/pull-business-card (+28/-8)
To merge this branch: bzr merge lp:~bluetooth/ubuntu/maverick/obexd/main
Reviewer Review Type Date Requested Status
Ubuntu branches Pending
Review via email: mp+27440@code.launchpad.net
To post a comment you must log in.
8. By Baptiste Mille-Mathias

* New upstream release.
  - version 0.28:
    + Fix broken assumption about contacts.
    + Fix issue with exporting empty contacts.
    + Fix issue with not always including the TEL header.
    + Fix wrong response code for PBAP PUT operation.
    + Fix handling of Tracker optional parameters.
    + Fix queries for incoming and outgoing folders.
    + Fix ordering during folder listing.
    + Fix complex logic discovering the type of call.
    + Add support for the X-IRMC-CALL-DATETIME field.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'ChangeLog'
2--- ChangeLog 2010-04-27 04:17:15 +0000
3+++ ChangeLog 2010-06-15 19:18:33 +0000
4@@ -1,3 +1,48 @@
5+ver 0.28:
6+ Fix broken assumption about contacts.
7+ Fix issue with exporting empty contacts.
8+ Fix issue with not always including the TEL header.
9+ Fix wrong response code for PBAP PUT operation.
10+ Fix handling of Tracker optional parameters.
11+ Fix queries for incoming and outgoing folders.
12+ Fix ordering during folder listing.
13+ Fix complex logic discovering the type of call.
14+ Add support for the X-IRMC-CALL-DATETIME field.
15+
16+ver 0.27:
17+ Fix GET name handling with FTP service.
18+ Fix service driver matching when who is not specified.
19+ Fix object name not being updated when agent changes it.
20+ Fix inconsistency when using vCard version 2.1.
21+ Fix wrong response code to PUT requests for PBAP.
22+ Fix crash on PBAP SetPhoneBook function.
23+ Add support for transport drivers.
24+ Add support for Nokia backup plugin.
25+
26+ver 0.26:
27+ Fix the order of the calls handles.
28+ Fix crash when receiving small objects.
29+ Fix invalid memory access when removing a file.
30+ Fix inverting the list with wrong search attribute.
31+ Fix wrong response code for dummy PullvCardListing.
32+ Fix sending the Not Found response asynchronously.
33+ Fix not resetting buffered data count when resetting the session.
34+ Add support for multiple telephone numbers.
35+ Add support for the ADR filter.
36+
37+ver 0.25:
38+ Fix issue with missing phonebook-tracker.c file.
39+
40+ver 0.24:
41+ Fix bug when creating directories.
42+ Fix error code when removing non-empty directory.
43+ Fix PullBusinessCard not return transfer errors.
44+ Fix MaxListCount handling for PBAP PullPhoneBook function.
45+ Fix mimetype driver selection and default fallback.
46+ Add support to the WHO header in mimetype drivers.
47+ Add support for PBAP operations to the back-ends.
48+ Add support for PBAP Tracker backend.
49+
50 ver 0.23:
51 Fix unneeded reset of session after a CONNECT.
52 Fix folder and object names with enabled auto accept.
53
54=== modified file 'Makefile.am'
55--- Makefile.am 2010-04-27 04:17:15 +0000
56+++ Makefile.am 2010-06-15 19:18:33 +0000
57@@ -29,9 +29,22 @@
58 builtin_sources =
59 builtin_nodist =
60
61+builtin_modules += bluetooth
62+builtin_sources += plugins/bluetooth.c
63+
64+if USB
65+builtin_modules += usb
66+builtin_sources += plugins/usb.c
67+endif
68+
69 builtin_modules += filesystem
70 builtin_sources += plugins/filesystem.c plugins/filesystem.h
71
72+if NOKIA_BACKUP
73+builtin_modules += backup
74+builtin_sources += plugins/nokia-backup.c
75+endif
76+
77 builtin_modules += opp
78 builtin_sources += plugins/opp.c
79
80@@ -39,7 +52,8 @@
81 builtin_sources += plugins/ftp.c
82
83 builtin_modules += pbap
84-builtin_sources += plugins/pbap.c plugins/phonebook.h
85+builtin_sources += plugins/pbap.c plugins/phonebook.h \
86+ plugins/vcard.h plugins/vcard.c
87
88 builtin_modules += syncevolution
89 builtin_sources += plugins/syncevolution.c
90@@ -52,13 +66,15 @@
91 src/main.c src/obexd.h src/plugin.h src/plugin.c \
92 src/logging.h src/logging.c src/btio.h src/btio.c \
93 src/dbus.h src/manager.c src/obex.h src/obex.c \
94- src/obex-priv.h src/bluetooth.h src/bluetooth.c \
95+ src/obex-priv.h \
96 src/mimetype.h src/mimetype.c \
97- src/service.h src/service.c
98+ src/service.h src/service.c \
99+ src/transport.h src/transport.c \
100+ src/server.h src/server.c
101
102 src_obexd_LDADD = @DBUS_LIBS@ @GLIB_LIBS@ @GTHREAD_LIBS@ \
103 @EBOOK_LIBS@ @OPENOBEX_LIBS@ \
104- @BLUEZ_LIBS@ -ldl
105+ @BLUEZ_LIBS@ @LIBICAL_LIBS@ -ldl
106
107 src_obexd_LDFLAGS = -Wl,--export-dynamic
108
109@@ -102,6 +118,7 @@
110
111 AM_CFLAGS = @OPENOBEX_CFLAGS@ @BLUEZ_CFLAGS@ @EBOOK_CFLAGS@ \
112 @GTHREAD_CFLAGS@ @GLIB_CFLAGS@ @DBUS_CFLAGS@ \
113+ @LIBICAL_CFLAGS@ \
114 -DOBEX_PLUGIN_BUILTIN -DPLUGINDIR=\""$(plugindir)"\"
115
116 INCLUDES = -I$(builddir)/src -I$(srcdir)/src -I$(srcdir)/plugins \
117@@ -111,16 +128,17 @@
118
119 EXTRA_DIST = src/genbuiltin $(doc_files) $(test_files) src/obex.conf \
120 src/obexd.service.in client/obex-client.service.in \
121- plugins/phonebook-dummy.c plugins/phonebook-ebook.c
122+ plugins/phonebook-dummy.c plugins/phonebook-ebook.c \
123+ plugins/phonebook-tracker.c
124
125 DISTCHECK_CONFIGURE_FLAGS = --enable-client --enable-server
126
127 MAINTAINERCLEANFILES = Makefile.in \
128 aclocal.m4 configure config.h.in config.sub config.guess \
129- ltmain.sh depcomp missing install-sh mkinstalldirs
130+ ltmain.sh depcomp compile missing install-sh mkinstalldirs
131
132 %.service: %.service.in config.log
133 $(AM_V_GEN)$(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
134
135 plugins/phonebook.c: plugins/@PHONEBOOK_DRIVER@
136- $(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
137+ $(AM_V_GEN)$(LN_S) @abs_top_srcdir@/$< $@
138
139=== modified file 'Makefile.in'
140--- Makefile.in 2010-04-27 04:17:15 +0000
141+++ Makefile.in 2010-06-15 19:18:33 +0000
142@@ -38,15 +38,20 @@
143 host_triplet = @host@
144 libexec_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2)
145 @SERVER_TRUE@am__append_1 = src/obexd.service.in
146-@SERVER_TRUE@am__append_2 = src/obexd
147+@SERVER_TRUE@@USB_TRUE@am__append_2 = usb
148+@SERVER_TRUE@@USB_TRUE@am__append_3 = plugins/usb.c
149+@NOKIA_BACKUP_TRUE@@SERVER_TRUE@am__append_4 = backup
150+@NOKIA_BACKUP_TRUE@@SERVER_TRUE@am__append_5 = plugins/nokia-backup.c
151+@SERVER_TRUE@am__append_6 = src/obexd
152 @SERVER_TRUE@noinst_PROGRAMS = test/obex-test$(EXEEXT)
153-@CLIENT_TRUE@am__append_3 = client/obex-client.service.in
154-@CLIENT_TRUE@am__append_4 = client/obex-client
155+@CLIENT_TRUE@am__append_7 = client/obex-client.service.in
156+@CLIENT_TRUE@am__append_8 = client/obex-client
157 subdir = .
158 DIST_COMMON = README $(am__configure_deps) $(srcdir)/Makefile.am \
159 $(srcdir)/Makefile.in $(srcdir)/config.h.in \
160 $(top_srcdir)/configure AUTHORS COPYING ChangeLog INSTALL NEWS \
161- config.guess config.sub depcomp install-sh ltmain.sh missing
162+ compile config.guess config.sub depcomp install-sh ltmain.sh \
163+ missing
164 ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
165 am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
166 $(top_srcdir)/configure.ac
167@@ -108,27 +113,33 @@
168 am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY))
169 am__v_lt_0 = --silent
170 am__src_obexd_SOURCES_DIST = gdbus/gdbus.h gdbus/mainloop.c \
171- gdbus/object.c gdbus/watch.c plugins/filesystem.c \
172- plugins/filesystem.h plugins/opp.c plugins/ftp.c \
173- plugins/pbap.c plugins/phonebook.h plugins/syncevolution.c \
174- src/main.c src/obexd.h src/plugin.h src/plugin.c src/logging.h \
175- src/logging.c src/btio.h src/btio.c src/dbus.h src/manager.c \
176- src/obex.h src/obex.c src/obex-priv.h src/bluetooth.h \
177- src/bluetooth.c src/mimetype.h src/mimetype.c src/service.h \
178- src/service.c
179-@SERVER_TRUE@am__objects_3 = plugins/filesystem.$(OBJEXT) \
180-@SERVER_TRUE@ plugins/opp.$(OBJEXT) plugins/ftp.$(OBJEXT) \
181-@SERVER_TRUE@ plugins/pbap.$(OBJEXT) \
182+ gdbus/object.c gdbus/watch.c plugins/bluetooth.c plugins/usb.c \
183+ plugins/filesystem.c plugins/filesystem.h \
184+ plugins/nokia-backup.c plugins/opp.c plugins/ftp.c \
185+ plugins/pbap.c plugins/phonebook.h plugins/vcard.h \
186+ plugins/vcard.c plugins/syncevolution.c src/main.c src/obexd.h \
187+ src/plugin.h src/plugin.c src/logging.h src/logging.c \
188+ src/btio.h src/btio.c src/dbus.h src/manager.c src/obex.h \
189+ src/obex.c src/obex-priv.h src/mimetype.h src/mimetype.c \
190+ src/service.h src/service.c src/transport.h src/transport.c \
191+ src/server.h src/server.c
192+@SERVER_TRUE@@USB_TRUE@am__objects_3 = plugins/usb.$(OBJEXT)
193+@NOKIA_BACKUP_TRUE@@SERVER_TRUE@am__objects_4 = plugins/nokia-backup.$(OBJEXT)
194+@SERVER_TRUE@am__objects_5 = plugins/bluetooth.$(OBJEXT) \
195+@SERVER_TRUE@ $(am__objects_3) plugins/filesystem.$(OBJEXT) \
196+@SERVER_TRUE@ $(am__objects_4) plugins/opp.$(OBJEXT) \
197+@SERVER_TRUE@ plugins/ftp.$(OBJEXT) plugins/pbap.$(OBJEXT) \
198+@SERVER_TRUE@ plugins/vcard.$(OBJEXT) \
199 @SERVER_TRUE@ plugins/syncevolution.$(OBJEXT)
200-@SERVER_TRUE@am_src_obexd_OBJECTS = $(am__objects_1) $(am__objects_3) \
201+@SERVER_TRUE@am_src_obexd_OBJECTS = $(am__objects_1) $(am__objects_5) \
202 @SERVER_TRUE@ src/main.$(OBJEXT) src/plugin.$(OBJEXT) \
203 @SERVER_TRUE@ src/logging.$(OBJEXT) src/btio.$(OBJEXT) \
204 @SERVER_TRUE@ src/manager.$(OBJEXT) src/obex.$(OBJEXT) \
205-@SERVER_TRUE@ src/bluetooth.$(OBJEXT) src/mimetype.$(OBJEXT) \
206-@SERVER_TRUE@ src/service.$(OBJEXT)
207-@SERVER_TRUE@am__objects_4 = plugins/phonebook.$(OBJEXT)
208-@SERVER_TRUE@am__objects_5 = $(am__objects_4)
209-@SERVER_TRUE@nodist_src_obexd_OBJECTS = $(am__objects_5)
210+@SERVER_TRUE@ src/mimetype.$(OBJEXT) src/service.$(OBJEXT) \
211+@SERVER_TRUE@ src/transport.$(OBJEXT) src/server.$(OBJEXT)
212+@SERVER_TRUE@am__objects_6 = plugins/phonebook.$(OBJEXT)
213+@SERVER_TRUE@am__objects_7 = $(am__objects_6)
214+@SERVER_TRUE@nodist_src_obexd_OBJECTS = $(am__objects_7)
215 src_obexd_OBJECTS = $(am_src_obexd_OBJECTS) \
216 $(nodist_src_obexd_OBJECTS)
217 src_obexd_DEPENDENCIES =
218@@ -230,6 +241,8 @@
219 INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
220 LD = @LD@
221 LDFLAGS = @LDFLAGS@
222+LIBICAL_CFLAGS = @LIBICAL_CFLAGS@
223+LIBICAL_LIBS = @LIBICAL_LIBS@
224 LIBOBJS = @LIBOBJS@
225 LIBS = @LIBS@
226 LIBTOOL = @LIBTOOL@
227@@ -316,7 +329,7 @@
228 top_srcdir = @top_srcdir@
229 AM_MAKEFLAGS = --no-print-directory
230 servicedir = $(datarootdir)/dbus-1/services
231-service_in_files = $(am__append_1) $(am__append_3)
232+service_in_files = $(am__append_1) $(am__append_7)
233 doc_files = doc/obexd-api.txt doc/agent-api.txt doc/client-api.txt
234 test_files = test/simple-agent test/send-files \
235 test/pull-business-card test/exchange-business-cards \
236@@ -329,23 +342,28 @@
237 gwobex/utils.h gwobex/utils.c gwobex/log.h
238
239 @SERVER_TRUE@confdir = $(sysconfdir)/obex
240-@SERVER_TRUE@builtin_modules = filesystem opp ftp pbap syncevolution
241-@SERVER_TRUE@builtin_sources = plugins/filesystem.c \
242-@SERVER_TRUE@ plugins/filesystem.h plugins/opp.c plugins/ftp.c \
243+@SERVER_TRUE@builtin_modules = bluetooth $(am__append_2) filesystem \
244+@SERVER_TRUE@ $(am__append_4) opp ftp pbap syncevolution
245+@SERVER_TRUE@builtin_sources = plugins/bluetooth.c $(am__append_3) \
246+@SERVER_TRUE@ plugins/filesystem.c plugins/filesystem.h \
247+@SERVER_TRUE@ $(am__append_5) plugins/opp.c plugins/ftp.c \
248 @SERVER_TRUE@ plugins/pbap.c plugins/phonebook.h \
249+@SERVER_TRUE@ plugins/vcard.h plugins/vcard.c \
250 @SERVER_TRUE@ plugins/syncevolution.c
251 @SERVER_TRUE@builtin_nodist = plugins/phonebook.c
252 @SERVER_TRUE@src_obexd_SOURCES = $(gdbus_sources) $(builtin_sources) \
253 @SERVER_TRUE@ src/main.c src/obexd.h src/plugin.h src/plugin.c \
254 @SERVER_TRUE@ src/logging.h src/logging.c src/btio.h src/btio.c \
255 @SERVER_TRUE@ src/dbus.h src/manager.c src/obex.h src/obex.c \
256-@SERVER_TRUE@ src/obex-priv.h src/bluetooth.h src/bluetooth.c \
257+@SERVER_TRUE@ src/obex-priv.h \
258 @SERVER_TRUE@ src/mimetype.h src/mimetype.c \
259-@SERVER_TRUE@ src/service.h src/service.c
260+@SERVER_TRUE@ src/service.h src/service.c \
261+@SERVER_TRUE@ src/transport.h src/transport.c \
262+@SERVER_TRUE@ src/server.h src/server.c
263
264 @SERVER_TRUE@src_obexd_LDADD = @DBUS_LIBS@ @GLIB_LIBS@ @GTHREAD_LIBS@ \
265 @SERVER_TRUE@ @EBOOK_LIBS@ @OPENOBEX_LIBS@ \
266-@SERVER_TRUE@ @BLUEZ_LIBS@ -ldl
267+@SERVER_TRUE@ @BLUEZ_LIBS@ @LIBICAL_LIBS@ -ldl
268
269 @SERVER_TRUE@src_obexd_LDFLAGS = -Wl,--export-dynamic
270 @SERVER_TRUE@builtin_files = src/builtin.h $(builtin_nodist)
271@@ -365,6 +383,7 @@
272 service_DATA = $(service_in_files:.service.in=.service)
273 AM_CFLAGS = @OPENOBEX_CFLAGS@ @BLUEZ_CFLAGS@ @EBOOK_CFLAGS@ \
274 @GTHREAD_CFLAGS@ @GLIB_CFLAGS@ @DBUS_CFLAGS@ \
275+ @LIBICAL_CFLAGS@ \
276 -DOBEX_PLUGIN_BUILTIN -DPLUGINDIR=\""$(plugindir)"\"
277
278 INCLUDES = -I$(builddir)/src -I$(srcdir)/src -I$(srcdir)/plugins \
279@@ -373,12 +392,13 @@
280 CLEANFILES = $(service_DATA) $(builtin_files)
281 EXTRA_DIST = src/genbuiltin $(doc_files) $(test_files) src/obex.conf \
282 src/obexd.service.in client/obex-client.service.in \
283- plugins/phonebook-dummy.c plugins/phonebook-ebook.c
284+ plugins/phonebook-dummy.c plugins/phonebook-ebook.c \
285+ plugins/phonebook-tracker.c
286
287 DISTCHECK_CONFIGURE_FLAGS = --enable-client --enable-server
288 MAINTAINERCLEANFILES = Makefile.in \
289 aclocal.m4 configure config.h.in config.sub config.guess \
290- ltmain.sh depcomp missing install-sh mkinstalldirs
291+ ltmain.sh depcomp compile missing install-sh mkinstalldirs
292
293 all: config.h
294 $(MAKE) $(AM_MAKEFLAGS) all-am
295@@ -578,14 +598,22 @@
296 plugins/$(DEPDIR)/$(am__dirstamp):
297 @$(MKDIR_P) plugins/$(DEPDIR)
298 @: > plugins/$(DEPDIR)/$(am__dirstamp)
299+plugins/bluetooth.$(OBJEXT): plugins/$(am__dirstamp) \
300+ plugins/$(DEPDIR)/$(am__dirstamp)
301+plugins/usb.$(OBJEXT): plugins/$(am__dirstamp) \
302+ plugins/$(DEPDIR)/$(am__dirstamp)
303 plugins/filesystem.$(OBJEXT): plugins/$(am__dirstamp) \
304 plugins/$(DEPDIR)/$(am__dirstamp)
305+plugins/nokia-backup.$(OBJEXT): plugins/$(am__dirstamp) \
306+ plugins/$(DEPDIR)/$(am__dirstamp)
307 plugins/opp.$(OBJEXT): plugins/$(am__dirstamp) \
308 plugins/$(DEPDIR)/$(am__dirstamp)
309 plugins/ftp.$(OBJEXT): plugins/$(am__dirstamp) \
310 plugins/$(DEPDIR)/$(am__dirstamp)
311 plugins/pbap.$(OBJEXT): plugins/$(am__dirstamp) \
312 plugins/$(DEPDIR)/$(am__dirstamp)
313+plugins/vcard.$(OBJEXT): plugins/$(am__dirstamp) \
314+ plugins/$(DEPDIR)/$(am__dirstamp)
315 plugins/syncevolution.$(OBJEXT): plugins/$(am__dirstamp) \
316 plugins/$(DEPDIR)/$(am__dirstamp)
317 src/main.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
318@@ -595,12 +623,14 @@
319 src/manager.$(OBJEXT): src/$(am__dirstamp) \
320 src/$(DEPDIR)/$(am__dirstamp)
321 src/obex.$(OBJEXT): src/$(am__dirstamp) src/$(DEPDIR)/$(am__dirstamp)
322-src/bluetooth.$(OBJEXT): src/$(am__dirstamp) \
323- src/$(DEPDIR)/$(am__dirstamp)
324 src/mimetype.$(OBJEXT): src/$(am__dirstamp) \
325 src/$(DEPDIR)/$(am__dirstamp)
326 src/service.$(OBJEXT): src/$(am__dirstamp) \
327 src/$(DEPDIR)/$(am__dirstamp)
328+src/transport.$(OBJEXT): src/$(am__dirstamp) \
329+ src/$(DEPDIR)/$(am__dirstamp)
330+src/server.$(OBJEXT): src/$(am__dirstamp) \
331+ src/$(DEPDIR)/$(am__dirstamp)
332 plugins/phonebook.$(OBJEXT): plugins/$(am__dirstamp) \
333 plugins/$(DEPDIR)/$(am__dirstamp)
334 src/obexd$(EXEEXT): $(src_obexd_OBJECTS) $(src_obexd_DEPENDENCIES) src/$(am__dirstamp)
335@@ -632,13 +662,16 @@
336 -rm -f gwobex/obex-priv.$(OBJEXT)
337 -rm -f gwobex/obex-xfer.$(OBJEXT)
338 -rm -f gwobex/utils.$(OBJEXT)
339+ -rm -f plugins/bluetooth.$(OBJEXT)
340 -rm -f plugins/filesystem.$(OBJEXT)
341 -rm -f plugins/ftp.$(OBJEXT)
342+ -rm -f plugins/nokia-backup.$(OBJEXT)
343 -rm -f plugins/opp.$(OBJEXT)
344 -rm -f plugins/pbap.$(OBJEXT)
345 -rm -f plugins/phonebook.$(OBJEXT)
346 -rm -f plugins/syncevolution.$(OBJEXT)
347- -rm -f src/bluetooth.$(OBJEXT)
348+ -rm -f plugins/usb.$(OBJEXT)
349+ -rm -f plugins/vcard.$(OBJEXT)
350 -rm -f src/btio.$(OBJEXT)
351 -rm -f src/logging.$(OBJEXT)
352 -rm -f src/main.$(OBJEXT)
353@@ -646,7 +679,9 @@
354 -rm -f src/mimetype.$(OBJEXT)
355 -rm -f src/obex.$(OBJEXT)
356 -rm -f src/plugin.$(OBJEXT)
357+ -rm -f src/server.$(OBJEXT)
358 -rm -f src/service.$(OBJEXT)
359+ -rm -f src/transport.$(OBJEXT)
360 -rm -f test/main.$(OBJEXT)
361
362 distclean-compile:
363@@ -664,13 +699,16 @@
364 @AMDEP_TRUE@@am__include@ @am__quote@gwobex/$(DEPDIR)/obex-priv.Po@am__quote@
365 @AMDEP_TRUE@@am__include@ @am__quote@gwobex/$(DEPDIR)/obex-xfer.Po@am__quote@
366 @AMDEP_TRUE@@am__include@ @am__quote@gwobex/$(DEPDIR)/utils.Po@am__quote@
367+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/bluetooth.Po@am__quote@
368 @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/filesystem.Po@am__quote@
369 @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/ftp.Po@am__quote@
370+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/nokia-backup.Po@am__quote@
371 @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/opp.Po@am__quote@
372 @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/pbap.Po@am__quote@
373 @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/phonebook.Po@am__quote@
374 @AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/syncevolution.Po@am__quote@
375-@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/bluetooth.Po@am__quote@
376+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/usb.Po@am__quote@
377+@AMDEP_TRUE@@am__include@ @am__quote@plugins/$(DEPDIR)/vcard.Po@am__quote@
378 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/btio.Po@am__quote@
379 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/logging.Po@am__quote@
380 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/main.Po@am__quote@
381@@ -678,7 +716,9 @@
382 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/mimetype.Po@am__quote@
383 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/obex.Po@am__quote@
384 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/plugin.Po@am__quote@
385+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/server.Po@am__quote@
386 @AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/service.Po@am__quote@
387+@AMDEP_TRUE@@am__include@ @am__quote@src/$(DEPDIR)/transport.Po@am__quote@
388 @AMDEP_TRUE@@am__include@ @am__quote@test/$(DEPDIR)/main.Po@am__quote@
389
390 .c.o:
391@@ -1092,7 +1132,7 @@
392 $(AM_V_GEN)$(SED) -e "s|\@libexecdir\@|$(libexecdir)|" $< > $@
393
394 plugins/phonebook.c: plugins/@PHONEBOOK_DRIVER@
395- $(AM_V_GEN)$(LN_S) $(abs_top_srcdir)/$< $@
396+ $(AM_V_GEN)$(LN_S) @abs_top_srcdir@/$< $@
397
398 # Tell versions [3.59,3.63) of GNU make to not export all variables.
399 # Otherwise a system limit (for SysV at least) may be exceeded.
400
401=== modified file 'aclocal.m4'
402--- aclocal.m4 2010-03-15 20:43:06 +0000
403+++ aclocal.m4 2010-06-15 19:18:33 +0000
404@@ -8796,6 +8796,41 @@
405 rm -f confinc confmf
406 ])
407
408+# Copyright (C) 1999, 2000, 2001, 2003, 2004, 2005, 2008
409+# Free Software Foundation, Inc.
410+#
411+# This file is free software; the Free Software Foundation
412+# gives unlimited permission to copy and/or distribute it,
413+# with or without modifications, as long as this notice is preserved.
414+
415+# serial 6
416+
417+# AM_PROG_CC_C_O
418+# --------------
419+# Like AC_PROG_CC_C_O, but changed for automake.
420+AC_DEFUN([AM_PROG_CC_C_O],
421+[AC_REQUIRE([AC_PROG_CC_C_O])dnl
422+AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
423+AC_REQUIRE_AUX_FILE([compile])dnl
424+# FIXME: we rely on the cache variable name because
425+# there is no other way.
426+set dummy $CC
427+am_cc=`echo $[2] | sed ['s/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/']`
428+eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
429+if test "$am_t" != yes; then
430+ # Losing compiler, so override with the script.
431+ # FIXME: It is wrong to rewrite CC.
432+ # But if we don't then we get into trouble of one sort or another.
433+ # A longer-term fix would be to have automake use am__CC in this case,
434+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
435+ CC="$am_aux_dir/compile $CC"
436+fi
437+dnl Make sure AC_PROG_CC is never called again, or it will override our
438+dnl setting of CC.
439+m4_define([AC_PROG_CC],
440+ [m4_fatal([AC_PROG_CC cannot be called after AM_PROG_CC_C_O])])
441+])
442+
443 # Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
444
445 # Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
446
447=== modified file 'client/main.c'
448--- client/main.c 2010-04-27 04:17:15 +0000
449+++ client/main.c 2010-06-15 19:18:33 +0000
450@@ -48,6 +48,7 @@
451 DBusMessage *message;
452 gchar *sender;
453 gchar *agent;
454+ char *filename;
455 GPtrArray *files;
456 };
457
458@@ -232,12 +233,25 @@
459 void *user_data)
460 {
461 struct send_data *data = user_data;
462+ struct transfer_data *transfer = session->pending->data;
463+
464+ if (transfer->err != 0) {
465+ DBusMessage *error = g_dbus_create_error(data->message,
466+ "org.openobex.Error.Failed",
467+ transfer->err > 0 ?
468+ OBEX_ResponseToString(transfer->err) :
469+ strerror(-transfer->err));
470+ g_dbus_send_message(data->connection, error);
471+ goto done;
472+ }
473
474 g_dbus_send_reply(data->connection, data->message, DBUS_TYPE_INVALID);
475
476+done:
477 shutdown_session(session);
478 dbus_message_unref(data->message);
479 dbus_connection_unref(data->connection);
480+ g_free(data->filename);
481 g_free(data->sender);
482 g_free(data);
483 }
484@@ -256,9 +270,8 @@
485 }
486
487 session_set_owner(session, data->sender, owner_exit);
488- g_dbus_send_reply(data->connection, data->message, DBUS_TYPE_INVALID);
489
490- session_pull(session, "text/x-vcard", "/tmp/x.vcf",
491+ session_pull(session, "text/x-vcard", data->filename,
492 pull_complete_callback, data);
493
494 return;
495@@ -266,6 +279,7 @@
496 done:
497 dbus_message_unref(data->message);
498 dbus_connection_unref(data->connection);
499+ g_free(data->filename);
500 g_free(data->sender);
501 g_free(data);
502 }
503@@ -277,6 +291,7 @@
504 struct session_data *session;
505 struct send_data *data;
506 const char *source = NULL, *dest = NULL, *target = NULL;
507+ const char *name = NULL;
508 uint8_t channel = 0;
509
510 dbus_message_iter_init(message, &iter);
511@@ -287,6 +302,14 @@
512 return g_dbus_create_error(message,
513 "org.openobex.Error.InvalidArguments", NULL);
514
515+ dbus_message_iter_next(&iter);
516+
517+ if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
518+ return g_dbus_create_error(message,
519+ "org.openobex.Error.InvalidArguments", NULL);
520+
521+ dbus_message_iter_get_basic(&iter, &name);
522+
523 data = g_try_malloc0(sizeof(*data));
524 if (data == NULL)
525 return g_dbus_create_error(message,
526@@ -295,6 +318,7 @@
527 data->connection = dbus_connection_ref(connection);
528 data->message = dbus_message_ref(message);
529 data->sender = g_strdup(dbus_message_get_sender(message));
530+ data->filename = g_strdup(name);
531
532 session = session_create(source, dest, "OPP", channel,
533 pull_session_callback, data);
534@@ -306,6 +330,7 @@
535 dbus_message_unref(data->message);
536 dbus_connection_unref(data->connection);
537 g_free(data->sender);
538+ g_free(data->filename);
539 g_free(data);
540
541 return g_dbus_create_error(message, "org.openobex.Error.Failed", NULL);
542@@ -379,7 +404,7 @@
543 const gchar *sender, *path;
544
545 if (dbus_message_get_args(message, NULL,
546- DBUS_TYPE_STRING, &path,
547+ DBUS_TYPE_OBJECT_PATH, &path,
548 DBUS_TYPE_INVALID) == FALSE)
549 return g_dbus_create_error(message,
550 "org.openobex.Error.InvalidArguments", NULL);
551
552=== modified file 'client/session.c'
553--- client/session.c 2010-04-27 04:17:15 +0000
554+++ client/session.c 2010-06-15 19:18:33 +0000
555@@ -1278,7 +1278,7 @@
556 if (session->obex == NULL)
557 return -ENOTCONN;
558
559- transfer = transfer_register(session, NULL, NULL, type, NULL);
560+ transfer = transfer_register(session, NULL, filename, type, NULL);
561 if (transfer == NULL) {
562 return -EIO;
563 }
564
565=== modified file 'client/transfer.c'
566--- client/transfer.c 2010-04-27 04:17:15 +0000
567+++ client/transfer.c 2010-06-15 19:18:33 +0000
568@@ -406,17 +406,20 @@
569 if (transfer->xfer != NULL)
570 return -EALREADY;
571
572- if (transfer->type == NULL) {
573+ if (g_strcmp0(transfer->type, "x-bt/vcard-listing") == 0 ||
574+ g_strcmp0(transfer->type, "x-obex/folder-listing") == 0)
575+ cb = get_xfer_listing_progress;
576+ else {
577 int fd = open(transfer->name ? : transfer->filename,
578 O_WRONLY | O_CREAT, 0600);
579+
580 if (transfer->fd < 0) {
581 error("open(): %s(%d)", strerror(errno), errno);
582 return -errno;
583 }
584 transfer->fd = fd;
585 cb = get_xfer_progress;
586- } else
587- cb = get_xfer_listing_progress;
588+ }
589
590 if (transfer->params != NULL)
591 transfer->xfer = gw_obex_get_async_with_apparam(session->obex,
592
593=== added file 'compile'
594--- compile 1970-01-01 00:00:00 +0000
595+++ compile 2010-06-15 19:18:33 +0000
596@@ -0,0 +1,143 @@
597+#! /bin/sh
598+# Wrapper for compilers which do not understand `-c -o'.
599+
600+scriptversion=2009-10-06.20; # UTC
601+
602+# Copyright (C) 1999, 2000, 2003, 2004, 2005, 2009 Free Software
603+# Foundation, Inc.
604+# Written by Tom Tromey <tromey@cygnus.com>.
605+#
606+# This program is free software; you can redistribute it and/or modify
607+# it under the terms of the GNU General Public License as published by
608+# the Free Software Foundation; either version 2, or (at your option)
609+# any later version.
610+#
611+# This program is distributed in the hope that it will be useful,
612+# but WITHOUT ANY WARRANTY; without even the implied warranty of
613+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
614+# GNU General Public License for more details.
615+#
616+# You should have received a copy of the GNU General Public License
617+# along with this program. If not, see <http://www.gnu.org/licenses/>.
618+
619+# As a special exception to the GNU General Public License, if you
620+# distribute this file as part of a program that contains a
621+# configuration script generated by Autoconf, you may include it under
622+# the same distribution terms that you use for the rest of that program.
623+
624+# This file is maintained in Automake, please report
625+# bugs to <bug-automake@gnu.org> or send patches to
626+# <automake-patches@gnu.org>.
627+
628+case $1 in
629+ '')
630+ echo "$0: No command. Try \`$0 --help' for more information." 1>&2
631+ exit 1;
632+ ;;
633+ -h | --h*)
634+ cat <<\EOF
635+Usage: compile [--help] [--version] PROGRAM [ARGS]
636+
637+Wrapper for compilers which do not understand `-c -o'.
638+Remove `-o dest.o' from ARGS, run PROGRAM with the remaining
639+arguments, and rename the output as expected.
640+
641+If you are trying to build a whole package this is not the
642+right script to run: please start by reading the file `INSTALL'.
643+
644+Report bugs to <bug-automake@gnu.org>.
645+EOF
646+ exit $?
647+ ;;
648+ -v | --v*)
649+ echo "compile $scriptversion"
650+ exit $?
651+ ;;
652+esac
653+
654+ofile=
655+cfile=
656+eat=
657+
658+for arg
659+do
660+ if test -n "$eat"; then
661+ eat=
662+ else
663+ case $1 in
664+ -o)
665+ # configure might choose to run compile as `compile cc -o foo foo.c'.
666+ # So we strip `-o arg' only if arg is an object.
667+ eat=1
668+ case $2 in
669+ *.o | *.obj)
670+ ofile=$2
671+ ;;
672+ *)
673+ set x "$@" -o "$2"
674+ shift
675+ ;;
676+ esac
677+ ;;
678+ *.c)
679+ cfile=$1
680+ set x "$@" "$1"
681+ shift
682+ ;;
683+ *)
684+ set x "$@" "$1"
685+ shift
686+ ;;
687+ esac
688+ fi
689+ shift
690+done
691+
692+if test -z "$ofile" || test -z "$cfile"; then
693+ # If no `-o' option was seen then we might have been invoked from a
694+ # pattern rule where we don't need one. That is ok -- this is a
695+ # normal compilation that the losing compiler can handle. If no
696+ # `.c' file was seen then we are probably linking. That is also
697+ # ok.
698+ exec "$@"
699+fi
700+
701+# Name of file we expect compiler to create.
702+cofile=`echo "$cfile" | sed 's|^.*[\\/]||; s|^[a-zA-Z]:||; s/\.c$/.o/'`
703+
704+# Create the lock directory.
705+# Note: use `[/\\:.-]' here to ensure that we don't use the same name
706+# that we are using for the .o file. Also, base the name on the expected
707+# object file name, since that is what matters with a parallel build.
708+lockdir=`echo "$cofile" | sed -e 's|[/\\:.-]|_|g'`.d
709+while true; do
710+ if mkdir "$lockdir" >/dev/null 2>&1; then
711+ break
712+ fi
713+ sleep 1
714+done
715+# FIXME: race condition here if user kills between mkdir and trap.
716+trap "rmdir '$lockdir'; exit 1" 1 2 15
717+
718+# Run the compile.
719+"$@"
720+ret=$?
721+
722+if test -f "$cofile"; then
723+ test "$cofile" = "$ofile" || mv "$cofile" "$ofile"
724+elif test -f "${cofile}bj"; then
725+ test "${cofile}bj" = "$ofile" || mv "${cofile}bj" "$ofile"
726+fi
727+
728+rmdir "$lockdir"
729+exit $ret
730+
731+# Local Variables:
732+# mode: shell-script
733+# sh-indentation: 2
734+# eval: (add-hook 'write-file-hooks 'time-stamp)
735+# time-stamp-start: "scriptversion="
736+# time-stamp-format: "%:y-%02m-%02d.%02H"
737+# time-stamp-time-zone: "UTC"
738+# time-stamp-end: "; # UTC"
739+# End:
740
741=== modified file 'config.h.in'
742--- config.h.in 2010-03-15 20:43:06 +0000
743+++ config.h.in 2010-06-15 19:18:33 +0000
744@@ -52,6 +52,9 @@
745 /* Define if threading support is required */
746 #undef NEED_THREADS
747
748+/* Define to 1 if your C compiler doesn't accept -c and -o together. */
749+#undef NO_MINUS_C_MINUS_O
750+
751 /* Name of package */
752 #undef PACKAGE
753
754
755=== modified file 'configure'
756--- configure 2010-04-27 04:17:15 +0000
757+++ configure 2010-06-15 19:18:33 +0000
758@@ -1,6 +1,6 @@
759 #! /bin/sh
760 # Guess values for system-dependent variables and create Makefiles.
761-# Generated by GNU Autoconf 2.63 for obexd 0.23.
762+# Generated by GNU Autoconf 2.63 for obexd 0.28.
763 #
764 # Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
765 # 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
766@@ -743,8 +743,8 @@
767 # Identity of this package.
768 PACKAGE_NAME='obexd'
769 PACKAGE_TARNAME='obexd'
770-PACKAGE_VERSION='0.23'
771-PACKAGE_STRING='obexd 0.23'
772+PACKAGE_VERSION='0.28'
773+PACKAGE_STRING='obexd 0.28'
774 PACKAGE_BUGREPORT=''
775
776 ac_default_prefix=/usr/local
777@@ -790,6 +790,10 @@
778 LIBOBJS
779 CLIENT_FALSE
780 CLIENT_TRUE
781+NOKIA_BACKUP_FALSE
782+NOKIA_BACKUP_TRUE
783+USB_FALSE
784+USB_TRUE
785 SERVER_FALSE
786 SERVER_TRUE
787 PHONEBOOK_DRIVER
788@@ -797,6 +801,8 @@
789 GTHREAD_CFLAGS
790 EBOOK_LIBS
791 EBOOK_CFLAGS
792+LIBICAL_LIBS
793+LIBICAL_CFLAGS
794 BLUEZ_LIBS
795 BLUEZ_CFLAGS
796 OPENOBEX_LIBS
797@@ -931,6 +937,8 @@
798 enable_debug
799 with_phonebook
800 enable_server
801+enable_usb
802+enable_nokia_backup
803 enable_client
804 '
805 ac_precious_vars='build_alias
806@@ -951,6 +959,8 @@
807 OPENOBEX_LIBS
808 BLUEZ_CFLAGS
809 BLUEZ_LIBS
810+LIBICAL_CFLAGS
811+LIBICAL_LIBS
812 EBOOK_CFLAGS
813 EBOOK_LIBS
814 GTHREAD_CFLAGS
815@@ -1507,7 +1517,7 @@
816 # Omit some internal or obsolete options to make the list less imposing.
817 # This message is too long to be a string in the A/UX 3.1 sh.
818 cat <<_ACEOF
819-\`configure' configures obexd 0.23 to adapt to many kinds of systems.
820+\`configure' configures obexd 0.28 to adapt to many kinds of systems.
821
822 Usage: $0 [OPTION]... [VAR=VALUE]...
823
824@@ -1577,7 +1587,7 @@
825
826 if test -n "$ac_init_help"; then
827 case $ac_init_help in
828- short | recursive ) echo "Configuration of obexd 0.23:";;
829+ short | recursive ) echo "Configuration of obexd 0.28:";;
830 esac
831 cat <<\_ACEOF
832
833@@ -1599,6 +1609,8 @@
834 --disable-optimization disable code optimization through compiler
835 --enable-debug enable compiling with debugging information
836 --disable-server disable compilation of OBEX server
837+ --enable-usb enable usb plugin
838+ --enable-nokia-backup enable nokia-backup plugin
839 --disable-client disable compilation of OBEX client
840
841 Optional Packages:
842@@ -1630,6 +1642,10 @@
843 BLUEZ_CFLAGS
844 C compiler flags for BLUEZ, overriding pkg-config
845 BLUEZ_LIBS linker flags for BLUEZ, overriding pkg-config
846+ LIBICAL_CFLAGS
847+ C compiler flags for LIBICAL, overriding pkg-config
848+ LIBICAL_LIBS
849+ linker flags for LIBICAL, overriding pkg-config
850 EBOOK_CFLAGS
851 C compiler flags for EBOOK, overriding pkg-config
852 EBOOK_LIBS linker flags for EBOOK, overriding pkg-config
853@@ -1703,7 +1719,7 @@
854 test -n "$ac_init_help" && exit $ac_status
855 if $ac_init_version; then
856 cat <<\_ACEOF
857-obexd configure 0.23
858+obexd configure 0.28
859 generated by GNU Autoconf 2.63
860
861 Copyright (C) 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
862@@ -1717,7 +1733,7 @@
863 This file contains any messages produced by compilers while
864 running configure, to aid debugging if configure makes a mistake.
865
866-It was created by obexd $as_me 0.23, which was
867+It was created by obexd $as_me 0.28, which was
868 generated by GNU Autoconf 2.63. Invocation command line was
869
870 $ $0 $@
871@@ -2567,7 +2583,7 @@
872
873 # Define the identity of the package.
874 PACKAGE='obexd'
875- VERSION='0.23'
876+ VERSION='0.28'
877
878
879 cat >>confdefs.h <<_ACEOF
880@@ -3811,6 +3827,138 @@
881 fi
882
883
884+if test "x$CC" != xcc; then
885+ { $as_echo "$as_me:$LINENO: checking whether $CC and cc understand -c and -o together" >&5
886+$as_echo_n "checking whether $CC and cc understand -c and -o together... " >&6; }
887+else
888+ { $as_echo "$as_me:$LINENO: checking whether cc understands -c and -o together" >&5
889+$as_echo_n "checking whether cc understands -c and -o together... " >&6; }
890+fi
891+set dummy $CC; ac_cc=`$as_echo "$2" |
892+ sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
893+if { as_var=ac_cv_prog_cc_${ac_cc}_c_o; eval "test \"\${$as_var+set}\" = set"; }; then
894+ $as_echo_n "(cached) " >&6
895+else
896+ cat >conftest.$ac_ext <<_ACEOF
897+/* confdefs.h. */
898+_ACEOF
899+cat confdefs.h >>conftest.$ac_ext
900+cat >>conftest.$ac_ext <<_ACEOF
901+/* end confdefs.h. */
902+
903+int
904+main ()
905+{
906+
907+ ;
908+ return 0;
909+}
910+_ACEOF
911+# Make sure it works both with $CC and with simple cc.
912+# We do the test twice because some compilers refuse to overwrite an
913+# existing .o file with -o, though they will create one.
914+ac_try='$CC -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
915+rm -f conftest2.*
916+if { (case "(($ac_try" in
917+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
918+ *) ac_try_echo=$ac_try;;
919+esac
920+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
921+$as_echo "$ac_try_echo") >&5
922+ (eval "$ac_try") 2>&5
923+ ac_status=$?
924+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
925+ (exit $ac_status); } &&
926+ test -f conftest2.$ac_objext && { (case "(($ac_try" in
927+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
928+ *) ac_try_echo=$ac_try;;
929+esac
930+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
931+$as_echo "$ac_try_echo") >&5
932+ (eval "$ac_try") 2>&5
933+ ac_status=$?
934+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
935+ (exit $ac_status); };
936+then
937+ eval ac_cv_prog_cc_${ac_cc}_c_o=yes
938+ if test "x$CC" != xcc; then
939+ # Test first that cc exists at all.
940+ if { ac_try='cc -c conftest.$ac_ext >&5'
941+ { (case "(($ac_try" in
942+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
943+ *) ac_try_echo=$ac_try;;
944+esac
945+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
946+$as_echo "$ac_try_echo") >&5
947+ (eval "$ac_try") 2>&5
948+ ac_status=$?
949+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
950+ (exit $ac_status); }; }; then
951+ ac_try='cc -c conftest.$ac_ext -o conftest2.$ac_objext >&5'
952+ rm -f conftest2.*
953+ if { (case "(($ac_try" in
954+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
955+ *) ac_try_echo=$ac_try;;
956+esac
957+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
958+$as_echo "$ac_try_echo") >&5
959+ (eval "$ac_try") 2>&5
960+ ac_status=$?
961+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
962+ (exit $ac_status); } &&
963+ test -f conftest2.$ac_objext && { (case "(($ac_try" in
964+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
965+ *) ac_try_echo=$ac_try;;
966+esac
967+eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
968+$as_echo "$ac_try_echo") >&5
969+ (eval "$ac_try") 2>&5
970+ ac_status=$?
971+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
972+ (exit $ac_status); };
973+ then
974+ # cc works too.
975+ :
976+ else
977+ # cc exists but doesn't like -o.
978+ eval ac_cv_prog_cc_${ac_cc}_c_o=no
979+ fi
980+ fi
981+ fi
982+else
983+ eval ac_cv_prog_cc_${ac_cc}_c_o=no
984+fi
985+rm -f core conftest*
986+
987+fi
988+if eval test \$ac_cv_prog_cc_${ac_cc}_c_o = yes; then
989+ { $as_echo "$as_me:$LINENO: result: yes" >&5
990+$as_echo "yes" >&6; }
991+else
992+ { $as_echo "$as_me:$LINENO: result: no" >&5
993+$as_echo "no" >&6; }
994+
995+cat >>confdefs.h <<\_ACEOF
996+#define NO_MINUS_C_MINUS_O 1
997+_ACEOF
998+
999+fi
1000+
1001+# FIXME: we rely on the cache variable name because
1002+# there is no other way.
1003+set dummy $CC
1004+am_cc=`echo $2 | sed 's/[^a-zA-Z0-9_]/_/g;s/^[0-9]/_/'`
1005+eval am_t=\$ac_cv_prog_cc_${am_cc}_c_o
1006+if test "$am_t" != yes; then
1007+ # Losing compiler, so override with the script.
1008+ # FIXME: It is wrong to rewrite CC.
1009+ # But if we don't then we get into trouble of one sort or another.
1010+ # A longer-term fix would be to have automake use am__CC in this case,
1011+ # and then we could set am__CC="\$(top_srcdir)/compile \$(CC)"
1012+ CC="$am_aux_dir/compile $CC"
1013+fi
1014+
1015+
1016
1017 { $as_echo "$as_me:$LINENO: checking whether ${CC-cc} accepts -fPIE" >&5
1018 $as_echo_n "checking whether ${CC-cc} accepts -fPIE... " >&6; }
1019@@ -4731,13 +4879,13 @@
1020 else
1021 lt_cv_nm_interface="BSD nm"
1022 echo "int some_variable = 0;" > conftest.$ac_ext
1023- (eval echo "\"\$as_me:4734: $ac_compile\"" >&5)
1024+ (eval echo "\"\$as_me:4882: $ac_compile\"" >&5)
1025 (eval "$ac_compile" 2>conftest.err)
1026 cat conftest.err >&5
1027- (eval echo "\"\$as_me:4737: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
1028+ (eval echo "\"\$as_me:4885: $NM \\\"conftest.$ac_objext\\\"\"" >&5)
1029 (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out)
1030 cat conftest.err >&5
1031- (eval echo "\"\$as_me:4740: output\"" >&5)
1032+ (eval echo "\"\$as_me:4888: output\"" >&5)
1033 cat conftest.out >&5
1034 if $GREP 'External.*some_variable' conftest.out > /dev/null; then
1035 lt_cv_nm_interface="MS dumpbin"
1036@@ -5943,7 +6091,7 @@
1037 ;;
1038 *-*-irix6*)
1039 # Find out which ABI we are using.
1040- echo '#line 5946 "configure"' > conftest.$ac_ext
1041+ echo '#line 6094 "configure"' > conftest.$ac_ext
1042 if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5
1043 (eval $ac_compile) 2>&5
1044 ac_status=$?
1045@@ -7766,11 +7914,11 @@
1046 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
1047 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
1048 -e 's:$: $lt_compiler_flag:'`
1049- (eval echo "\"\$as_me:7769: $lt_compile\"" >&5)
1050+ (eval echo "\"\$as_me:7917: $lt_compile\"" >&5)
1051 (eval "$lt_compile" 2>conftest.err)
1052 ac_status=$?
1053 cat conftest.err >&5
1054- echo "$as_me:7773: \$? = $ac_status" >&5
1055+ echo "$as_me:7921: \$? = $ac_status" >&5
1056 if (exit $ac_status) && test -s "$ac_outfile"; then
1057 # The compiler can only warn and ignore the option if not recognized
1058 # So say no if there are warnings other than the usual output.
1059@@ -8105,11 +8253,11 @@
1060 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
1061 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
1062 -e 's:$: $lt_compiler_flag:'`
1063- (eval echo "\"\$as_me:8108: $lt_compile\"" >&5)
1064+ (eval echo "\"\$as_me:8256: $lt_compile\"" >&5)
1065 (eval "$lt_compile" 2>conftest.err)
1066 ac_status=$?
1067 cat conftest.err >&5
1068- echo "$as_me:8112: \$? = $ac_status" >&5
1069+ echo "$as_me:8260: \$? = $ac_status" >&5
1070 if (exit $ac_status) && test -s "$ac_outfile"; then
1071 # The compiler can only warn and ignore the option if not recognized
1072 # So say no if there are warnings other than the usual output.
1073@@ -8210,11 +8358,11 @@
1074 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
1075 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
1076 -e 's:$: $lt_compiler_flag:'`
1077- (eval echo "\"\$as_me:8213: $lt_compile\"" >&5)
1078+ (eval echo "\"\$as_me:8361: $lt_compile\"" >&5)
1079 (eval "$lt_compile" 2>out/conftest.err)
1080 ac_status=$?
1081 cat out/conftest.err >&5
1082- echo "$as_me:8217: \$? = $ac_status" >&5
1083+ echo "$as_me:8365: \$? = $ac_status" >&5
1084 if (exit $ac_status) && test -s out/conftest2.$ac_objext
1085 then
1086 # The compiler can only warn and ignore the option if not recognized
1087@@ -8265,11 +8413,11 @@
1088 -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \
1089 -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \
1090 -e 's:$: $lt_compiler_flag:'`
1091- (eval echo "\"\$as_me:8268: $lt_compile\"" >&5)
1092+ (eval echo "\"\$as_me:8416: $lt_compile\"" >&5)
1093 (eval "$lt_compile" 2>out/conftest.err)
1094 ac_status=$?
1095 cat out/conftest.err >&5
1096- echo "$as_me:8272: \$? = $ac_status" >&5
1097+ echo "$as_me:8420: \$? = $ac_status" >&5
1098 if (exit $ac_status) && test -s out/conftest2.$ac_objext
1099 then
1100 # The compiler can only warn and ignore the option if not recognized
1101@@ -11068,7 +11216,7 @@
1102 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
1103 lt_status=$lt_dlunknown
1104 cat > conftest.$ac_ext <<_LT_EOF
1105-#line 11071 "configure"
1106+#line 11219 "configure"
1107 #include "confdefs.h"
1108
1109 #if HAVE_DLFCN_H
1110@@ -11164,7 +11312,7 @@
1111 lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
1112 lt_status=$lt_dlunknown
1113 cat > conftest.$ac_ext <<_LT_EOF
1114-#line 11167 "configure"
1115+#line 11315 "configure"
1116 #include "confdefs.h"
1117
1118 #if HAVE_DLFCN_H
1119@@ -12188,6 +12336,82 @@
1120 fi
1121
1122
1123+if (test "${phonebook_driver}" = "dummy"); then
1124+
1125+pkg_failed=no
1126+{ $as_echo "$as_me:$LINENO: checking for LIBICAL" >&5
1127+$as_echo_n "checking for LIBICAL... " >&6; }
1128+
1129+if test -n "$LIBICAL_CFLAGS"; then
1130+ pkg_cv_LIBICAL_CFLAGS="$LIBICAL_CFLAGS"
1131+ elif test -n "$PKG_CONFIG"; then
1132+ if test -n "$PKG_CONFIG" && \
1133+ { ($as_echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"libical\"") >&5
1134+ ($PKG_CONFIG --exists --print-errors "libical") 2>&5
1135+ ac_status=$?
1136+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
1137+ (exit $ac_status); }; then
1138+ pkg_cv_LIBICAL_CFLAGS=`$PKG_CONFIG --cflags "libical" 2>/dev/null`
1139+else
1140+ pkg_failed=yes
1141+fi
1142+ else
1143+ pkg_failed=untried
1144+fi
1145+if test -n "$LIBICAL_LIBS"; then
1146+ pkg_cv_LIBICAL_LIBS="$LIBICAL_LIBS"
1147+ elif test -n "$PKG_CONFIG"; then
1148+ if test -n "$PKG_CONFIG" && \
1149+ { ($as_echo "$as_me:$LINENO: \$PKG_CONFIG --exists --print-errors \"libical\"") >&5
1150+ ($PKG_CONFIG --exists --print-errors "libical") 2>&5
1151+ ac_status=$?
1152+ $as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
1153+ (exit $ac_status); }; then
1154+ pkg_cv_LIBICAL_LIBS=`$PKG_CONFIG --libs "libical" 2>/dev/null`
1155+else
1156+ pkg_failed=yes
1157+fi
1158+ else
1159+ pkg_failed=untried
1160+fi
1161+
1162+
1163+
1164+if test $pkg_failed = yes; then
1165+
1166+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
1167+ _pkg_short_errors_supported=yes
1168+else
1169+ _pkg_short_errors_supported=no
1170+fi
1171+ if test $_pkg_short_errors_supported = yes; then
1172+ LIBICAL_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "libical" 2>&1`
1173+ else
1174+ LIBICAL_PKG_ERRORS=`$PKG_CONFIG --print-errors "libical" 2>&1`
1175+ fi
1176+ # Put the nasty error message in config.log where it belongs
1177+ echo "$LIBICAL_PKG_ERRORS" >&5
1178+
1179+ { $as_echo "$as_me:$LINENO: result: no" >&5
1180+$as_echo "no" >&6; }
1181+ { { $as_echo "$as_me:$LINENO: error: libical is required" >&5
1182+$as_echo "$as_me: error: libical is required" >&2;}
1183+ { (exit 1); exit 1; }; }
1184+elif test $pkg_failed = untried; then
1185+ { { $as_echo "$as_me:$LINENO: error: libical is required" >&5
1186+$as_echo "$as_me: error: libical is required" >&2;}
1187+ { (exit 1); exit 1; }; }
1188+else
1189+ LIBICAL_CFLAGS=$pkg_cv_LIBICAL_CFLAGS
1190+ LIBICAL_LIBS=$pkg_cv_LIBICAL_LIBS
1191+ { $as_echo "$as_me:$LINENO: result: yes" >&5
1192+$as_echo "yes" >&6; }
1193+ dummy=yes
1194+fi
1195+
1196+
1197+fi
1198+
1199 if (test "${phonebook_driver}" = "ebook"); then
1200
1201 cat >>confdefs.h <<\_ACEOF
1202@@ -12363,6 +12587,40 @@
1203 fi
1204
1205
1206+# Check whether --enable-usb was given.
1207+if test "${enable_usb+set}" = set; then
1208+ enableval=$enable_usb;
1209+ enable_usb=${enableval}
1210+
1211+fi
1212+
1213+ if test "${enable_usb}" = "yes" &&
1214+ test "${enable_server}" != "no"; then
1215+ USB_TRUE=
1216+ USB_FALSE='#'
1217+else
1218+ USB_TRUE='#'
1219+ USB_FALSE=
1220+fi
1221+
1222+
1223+# Check whether --enable-nokia_backup was given.
1224+if test "${enable_nokia_backup+set}" = set; then
1225+ enableval=$enable_nokia_backup;
1226+ enable_nokia_backup=${enableval}
1227+
1228+fi
1229+
1230+ if test "${enable_nokia_backup}" = "yes" &&
1231+ test "${enable_server}" != "no"; then
1232+ NOKIA_BACKUP_TRUE=
1233+ NOKIA_BACKUP_FALSE='#'
1234+else
1235+ NOKIA_BACKUP_TRUE='#'
1236+ NOKIA_BACKUP_FALSE=
1237+fi
1238+
1239+
1240 # Check whether --enable-client was given.
1241 if test "${enable_client+set}" = set; then
1242 enableval=$enable_client;
1243@@ -12514,6 +12772,20 @@
1244 Usually this means the macro was only invoked conditionally." >&2;}
1245 { (exit 1); exit 1; }; }
1246 fi
1247+if test -z "${USB_TRUE}" && test -z "${USB_FALSE}"; then
1248+ { { $as_echo "$as_me:$LINENO: error: conditional \"USB\" was never defined.
1249+Usually this means the macro was only invoked conditionally." >&5
1250+$as_echo "$as_me: error: conditional \"USB\" was never defined.
1251+Usually this means the macro was only invoked conditionally." >&2;}
1252+ { (exit 1); exit 1; }; }
1253+fi
1254+if test -z "${NOKIA_BACKUP_TRUE}" && test -z "${NOKIA_BACKUP_FALSE}"; then
1255+ { { $as_echo "$as_me:$LINENO: error: conditional \"NOKIA_BACKUP\" was never defined.
1256+Usually this means the macro was only invoked conditionally." >&5
1257+$as_echo "$as_me: error: conditional \"NOKIA_BACKUP\" was never defined.
1258+Usually this means the macro was only invoked conditionally." >&2;}
1259+ { (exit 1); exit 1; }; }
1260+fi
1261 if test -z "${CLIENT_TRUE}" && test -z "${CLIENT_FALSE}"; then
1262 { { $as_echo "$as_me:$LINENO: error: conditional \"CLIENT\" was never defined.
1263 Usually this means the macro was only invoked conditionally." >&5
1264@@ -12843,7 +13115,7 @@
1265 # report actual input values of CONFIG_FILES etc. instead of their
1266 # values after options handling.
1267 ac_log="
1268-This file was extended by obexd $as_me 0.23, which was
1269+This file was extended by obexd $as_me 0.28, which was
1270 generated by GNU Autoconf 2.63. Invocation command line was
1271
1272 CONFIG_FILES = $CONFIG_FILES
1273@@ -12906,7 +13178,7 @@
1274 _ACEOF
1275 cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
1276 ac_cs_version="\\
1277-obexd config.status 0.23
1278+obexd config.status 0.28
1279 configured by $0, generated by GNU Autoconf 2.63,
1280 with options \\"`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`\\"
1281
1282
1283=== modified file 'configure.ac'
1284--- configure.ac 2010-04-27 04:17:15 +0000
1285+++ configure.ac 2010-06-15 19:18:33 +0000
1286@@ -1,5 +1,5 @@
1287 AC_PREREQ(2.60)
1288-AC_INIT(obexd, 0.23)
1289+AC_INIT(obexd, 0.28)
1290
1291 AM_INIT_AUTOMAKE([foreign subdir-objects])
1292 AM_CONFIG_HEADER(config.h)
1293@@ -30,6 +30,7 @@
1294 AC_LANG_C
1295
1296 AC_PROG_CC
1297+AM_PROG_CC_C_O
1298 AC_PROG_CC_PIE
1299 AC_PROG_INSTALL
1300 AC_PROG_SED
1301@@ -114,6 +115,13 @@
1302 fi
1303 ])
1304
1305+if (test "${phonebook_driver}" = "dummy"); then
1306+ PKG_CHECK_MODULES(LIBICAL, libical, dummy=yes,
1307+ AC_MSG_ERROR(libical is required))
1308+ AC_SUBST(LIBICAL_CFLAGS)
1309+ AC_SUBST(LIBICAL_LIBS)
1310+fi
1311+
1312 if (test "${phonebook_driver}" = "ebook"); then
1313 AC_DEFINE(NEED_THREADS, 1, [Define if threading support is required])
1314
1315@@ -136,6 +144,20 @@
1316 ])
1317 AM_CONDITIONAL(SERVER, test "${enable_server}" != "no")
1318
1319+AC_ARG_ENABLE(usb, AC_HELP_STRING([--enable-usb],
1320+ [enable usb plugin]), [
1321+ enable_usb=${enableval}
1322+])
1323+AM_CONDITIONAL(USB, test "${enable_usb}" = "yes" &&
1324+ test "${enable_server}" != "no")
1325+
1326+AC_ARG_ENABLE(nokia_backup, AC_HELP_STRING([--enable-nokia-backup],
1327+ [enable nokia-backup plugin]), [
1328+ enable_nokia_backup=${enableval}
1329+])
1330+AM_CONDITIONAL(NOKIA_BACKUP, test "${enable_nokia_backup}" = "yes" &&
1331+ test "${enable_server}" != "no")
1332+
1333 AC_ARG_ENABLE(client, AC_HELP_STRING([--disable-client],
1334 [disable compilation of OBEX client]), [
1335 enable_client=${enableval}
1336
1337=== modified file 'debian/changelog'
1338--- debian/changelog 2010-04-27 04:17:15 +0000
1339+++ debian/changelog 2010-06-15 19:18:33 +0000
1340@@ -1,3 +1,43 @@
1341+obexd (0.28-0ubuntu1) UNRELEASED; urgency=low
1342+
1343+ * New upstream release.
1344+ - version 0.28:
1345+ + Fix broken assumption about contacts.
1346+ + Fix issue with exporting empty contacts.
1347+ + Fix issue with not always including the TEL header.
1348+ + Fix wrong response code for PBAP PUT operation.
1349+ + Fix handling of Tracker optional parameters.
1350+ + Fix queries for incoming and outgoing folders.
1351+ + Fix ordering during folder listing.
1352+ + Fix complex logic discovering the type of call.
1353+ + Add support for the X-IRMC-CALL-DATETIME field.
1354+ - version 0.27:
1355+ + Fix GET name handling with FTP service.
1356+ + Fix service driver matching when who is not specified.
1357+ + Fix object name not being updated when agent changes it.
1358+ + Fix inconsistency when using vCard version 2.1.
1359+ + Fix wrong response code to PUT requests for PBAP.
1360+ + Fix crash on PBAP SetPhoneBook function.
1361+ + Add support for transport drivers.
1362+ + Add support for Nokia backup plugin.
1363+ - version 0.26:
1364+ + Fix the order of the calls handles.
1365+ + Fix crash when receiving small objects.
1366+ + Fix invalid memory access when removing a file.
1367+ + Fix inverting the list with wrong search attribute.
1368+ + Fix wrong response code for dummy PullvCardListing.
1369+ + Fix sending the Not Found response asynchronously.
1370+ + Fix not resetting buffered data count when resetting the session.
1371+ + Add support for multiple telephone numbers.
1372+ + Add support for the ADR filter.
1373+ - version 0.25:
1374+ + Fix issue with missing phonebook-tracker.c file.
1375+ * debian/rules:
1376+ - enable usb and enable-nokia-backup plugins
1377+ * New upstream release.
1378+
1379+ -- Baptiste Mille-Mathias <baptiste.millemathias@gmail.com> Tue, 15 Jun 2010 20:48:39 +0200
1380+
1381 obexd (0.23-1) unstable; urgency=low
1382
1383 * New upstream release (Closes: #558710).
1384
1385=== modified file 'debian/control'
1386--- debian/control 2010-04-27 04:17:15 +0000
1387+++ debian/control 2010-06-15 19:18:33 +0000
1388@@ -7,7 +7,8 @@
1389 libglib2.0-dev,
1390 libdbus-1-dev,
1391 libopenobex1-dev,
1392- libbluetooth-dev (>= 4)
1393+ libbluetooth-dev (>= 4),
1394+ libical-dev
1395 Vcs-Svn: svn://svn.debian.org/svn/pkg-bluetooth/packages/obexd
1396 Vcs-Browser: http://svn.debian.org/wsvn/pkg-bluetooth/packages/obexd
1397 Homepage: http://www.bluez.org
1398
1399=== modified file 'debian/rules'
1400--- debian/rules 2009-07-27 19:02:30 +0000
1401+++ debian/rules 2010-06-15 19:18:33 +0000
1402@@ -3,3 +3,7 @@
1403 include /usr/share/cdbs/1/rules/debhelper.mk
1404 include /usr/share/cdbs/1/rules/simple-patchsys.mk
1405 include /usr/share/cdbs/1/class/autotools.mk
1406+
1407+DEB_CONFIGURE_EXTRA_FLAGS += \
1408+ --enable-usb \
1409+ --enable-nokia-backup
1410
1411=== modified file 'gdbus/object.c'
1412--- gdbus/object.c 2010-03-15 20:43:06 +0000
1413+++ gdbus/object.c 2010-06-15 19:18:33 +0000
1414@@ -308,8 +308,10 @@
1415 goto done;
1416
1417 if (!dbus_connection_get_object_path_data(conn, parent_path,
1418- (void *) &data))
1419+ (void *) &data)) {
1420+ invalidate_parent_data(conn, parent_path);
1421 goto done;
1422+ }
1423
1424 if (!data)
1425 goto done;
1426@@ -514,8 +516,10 @@
1427 if (data == NULL)
1428 return FALSE;
1429
1430- if (find_interface(data->interfaces, name))
1431+ if (find_interface(data->interfaces, name)) {
1432+ object_path_unref(connection, path);
1433 return FALSE;
1434+ }
1435
1436 add_interface(data, name, methods, signals,
1437 properties, user_data, destroy);
1438
1439=== added file 'plugins/bluetooth.c'
1440--- plugins/bluetooth.c 1970-01-01 00:00:00 +0000
1441+++ plugins/bluetooth.c 2010-06-15 19:18:33 +0000
1442@@ -0,0 +1,609 @@
1443+/*
1444+ *
1445+ * OBEX Server
1446+ *
1447+ * Copyright (C) 2007-2010 Nokia Corporation
1448+ * Copyright (C) 2007-2010 Marcel Holtmann <marcel@holtmann.org>
1449+ *
1450+ *
1451+ * This program is free software; you can redistribute it and/or modify
1452+ * it under the terms of the GNU General Public License as published by
1453+ * the Free Software Foundation; either version 2 of the License, or
1454+ * (at your option) any later version.
1455+ *
1456+ * This program is distributed in the hope that it will be useful,
1457+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
1458+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1459+ * GNU General Public License for more details.
1460+ *
1461+ * You should have received a copy of the GNU General Public License
1462+ * along with this program; if not, write to the Free Software
1463+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1464+ *
1465+ */
1466+
1467+#ifdef HAVE_CONFIG_H
1468+#include <config.h>
1469+#endif
1470+
1471+#include <errno.h>
1472+#include <string.h>
1473+
1474+#include <openobex/obex.h>
1475+#include <openobex/obex_const.h>
1476+
1477+#include <glib.h>
1478+#include <gdbus.h>
1479+
1480+#include "plugin.h"
1481+#include "server.h"
1482+#include "obex.h"
1483+#include "transport.h"
1484+#include "service.h"
1485+#include "logging.h"
1486+#include "btio.h"
1487+
1488+#define BT_RX_MTU 32767
1489+#define BT_TX_MTU 32767
1490+
1491+#define TIMEOUT 60*1000 /* Timeout for user response (miliseconds) */
1492+
1493+struct pending_request {
1494+ DBusPendingCall *call;
1495+ struct bluetooth_service *service;
1496+ char *adapter_path;
1497+ char address[18];
1498+ unsigned int watch;
1499+ GIOChannel *io;
1500+};
1501+
1502+struct bluetooth_service {
1503+ struct obex_server *server;
1504+ struct obex_service_driver *driver;
1505+ uint32_t handle;
1506+};
1507+
1508+struct adapter_any {
1509+ char *path; /* Adapter ANY path */
1510+ GSList *services; /* List of services to register records */
1511+};
1512+
1513+static DBusConnection *connection = NULL;
1514+static struct adapter_any *any = NULL;
1515+
1516+static void add_record_reply(DBusPendingCall *call, void *user_data)
1517+{
1518+ struct bluetooth_service *service = user_data;
1519+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
1520+ DBusError derr;
1521+ uint32_t handle;
1522+
1523+ dbus_error_init(&derr);
1524+ if (dbus_set_error_from_message(&derr, reply)) {
1525+ error("bluetooth: Replied with an error: %s, %s",
1526+ derr.name, derr.message);
1527+ dbus_error_free(&derr);
1528+ handle = 0;
1529+ } else {
1530+ dbus_message_get_args(reply, NULL,
1531+ DBUS_TYPE_UINT32, &handle,
1532+ DBUS_TYPE_INVALID);
1533+
1534+ service->handle = handle;
1535+
1536+ debug("bluetooth: Registered: %s, handle: 0x%x",
1537+ service->driver->name, service->handle);
1538+ }
1539+
1540+ dbus_message_unref(reply);
1541+}
1542+
1543+static int add_record(const char *path, const char *xml,
1544+ struct bluetooth_service *service)
1545+{
1546+ DBusMessage *msg;
1547+ DBusPendingCall *call;
1548+ int ret = 0;
1549+
1550+ msg = dbus_message_new_method_call("org.bluez", path,
1551+ "org.bluez.Service", "AddRecord");
1552+
1553+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &xml,
1554+ DBUS_TYPE_INVALID);
1555+
1556+ if (dbus_connection_send_with_reply(connection,
1557+ msg, &call, -1) == FALSE) {
1558+ ret = -1;
1559+ goto failed;
1560+ }
1561+
1562+ dbus_pending_call_set_notify(call, add_record_reply, service, NULL);
1563+ dbus_pending_call_unref(call);
1564+
1565+failed:
1566+ dbus_message_unref(msg);
1567+ return ret;
1568+}
1569+
1570+static struct bluetooth_service *find_service(
1571+ struct obex_service_driver *driver,
1572+ uint8_t channel)
1573+{
1574+ GSList *l;
1575+
1576+ for (l = any->services; l; l = l->next) {
1577+ struct bluetooth_service *service = l->data;
1578+
1579+ if (driver != NULL && service->driver != driver)
1580+ continue;
1581+
1582+ if (channel != 0 && service->driver->channel != channel)
1583+ continue;
1584+
1585+ return service;
1586+ }
1587+
1588+ return NULL;
1589+}
1590+
1591+static void register_record(struct obex_server *server)
1592+{
1593+ const GSList *l;
1594+
1595+ if (connection == NULL)
1596+ return;
1597+
1598+ for (l = server->drivers; l; l = l->next) {
1599+ struct obex_service_driver *driver = l->data;
1600+ struct bluetooth_service *service;
1601+ char *xml;
1602+
1603+ service = find_service(driver, 0);
1604+ if (service == NULL) {
1605+ service = g_new0(struct bluetooth_service, 1);
1606+ service->driver = driver;
1607+ service->server = server;
1608+ any->services = g_slist_append(any->services, service);
1609+ }
1610+
1611+ /* Service already has a record registered */
1612+ if (service->handle != 0)
1613+ continue;
1614+
1615+ /* Adapter ANY is not available yet: Add record later */
1616+ if (any->path == NULL)
1617+ continue;
1618+
1619+ xml = g_markup_printf_escaped(driver->record, driver->channel,
1620+ driver->name);
1621+ add_record(any->path, xml, service);
1622+ g_free(xml);
1623+ }
1624+}
1625+
1626+static void find_adapter_any_reply(DBusPendingCall *call, void *user_data)
1627+{
1628+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
1629+ const char *path;
1630+ GSList *l;
1631+ DBusError derr;
1632+
1633+ dbus_error_init(&derr);
1634+ if (dbus_set_error_from_message(&derr, reply)) {
1635+ error("bluetooth: Replied with an error: %s, %s",
1636+ derr.name, derr.message);
1637+ dbus_error_free(&derr);
1638+ goto done;
1639+ }
1640+
1641+ dbus_message_get_args(reply, NULL,
1642+ DBUS_TYPE_OBJECT_PATH, &path,
1643+ DBUS_TYPE_INVALID);
1644+ any->path = g_strdup(path);
1645+
1646+ for (l = any->services; l; l = l->next) {
1647+ struct bluetooth_service *service = l->data;
1648+ char *xml;
1649+
1650+ xml = g_markup_printf_escaped(service->driver->record,
1651+ service->driver->channel,
1652+ service->driver->name);
1653+ add_record(any->path, xml, service);
1654+ g_free(xml);
1655+ }
1656+
1657+done:
1658+ dbus_message_unref(reply);
1659+}
1660+
1661+static DBusPendingCall *find_adapter(const char *pattern,
1662+ DBusPendingCallNotifyFunction function,
1663+ void *user_data)
1664+{
1665+ DBusMessage *msg;
1666+ DBusPendingCall *call;
1667+
1668+ debug("bluetooth: FindAdapter(%s)", pattern);
1669+
1670+ msg = dbus_message_new_method_call("org.bluez", "/",
1671+ "org.bluez.Manager", "FindAdapter");
1672+ if (!msg)
1673+ return NULL;
1674+
1675+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &pattern,
1676+ DBUS_TYPE_INVALID);
1677+
1678+ if (!dbus_connection_send_with_reply(connection, msg, &call, -1)) {
1679+ dbus_message_unref(msg);
1680+ return NULL;
1681+ }
1682+
1683+ dbus_pending_call_set_notify(call, function, user_data, NULL);
1684+
1685+ dbus_message_unref(msg);
1686+
1687+ return call;
1688+}
1689+
1690+static void name_acquired(DBusConnection *conn, void *user_data)
1691+{
1692+ DBusPendingCall *call;
1693+
1694+ call = find_adapter("any", find_adapter_any_reply, NULL);
1695+ if (call)
1696+ dbus_pending_call_unref(call);
1697+}
1698+
1699+static void name_released(DBusConnection *conn, void *user_data)
1700+{
1701+ GSList *l;
1702+
1703+ /* reset handles so the services got register next time */
1704+ for (l = any->services; l; l = l->next) {
1705+ struct bluetooth_service *service = l->data;
1706+
1707+ service->handle = 0;
1708+ }
1709+
1710+ g_free(any->path);
1711+ any->path = NULL;
1712+
1713+}
1714+
1715+static void service_cancel(struct pending_request *pending)
1716+{
1717+ DBusMessage *msg;
1718+
1719+ msg = dbus_message_new_method_call("org.bluez",
1720+ pending->adapter_path,
1721+ "org.bluez.Service",
1722+ "CancelAuthorization");
1723+
1724+ g_dbus_send_message(connection, msg);
1725+}
1726+
1727+static void pending_request_free(struct pending_request *pending)
1728+{
1729+ if (pending->call)
1730+ dbus_pending_call_unref(pending->call);
1731+ g_io_channel_unref(pending->io);
1732+ g_free(pending->adapter_path);
1733+ g_free(pending);
1734+}
1735+
1736+static void connect_event(GIOChannel *io, GError *err, void *user_data)
1737+{
1738+ struct bluetooth_service *service = user_data;
1739+ struct obex_server *server = service->server;
1740+
1741+ if (err)
1742+ goto drop;
1743+
1744+ if (obex_server_new_connection(server, io, BT_TX_MTU, BT_RX_MTU) < 0)
1745+ g_io_channel_shutdown(io, TRUE, NULL);
1746+
1747+ return;
1748+
1749+drop:
1750+ error("%s", err->message);
1751+ g_io_channel_shutdown(io, TRUE, NULL);
1752+ return;
1753+}
1754+
1755+static void service_reply(DBusPendingCall *call, void *user_data)
1756+{
1757+ struct pending_request *pending = user_data;
1758+ GIOChannel *io = pending->io;
1759+ struct bluetooth_service *service = pending->service;
1760+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
1761+ DBusError derr;
1762+ GError *err = NULL;
1763+
1764+ dbus_error_init(&derr);
1765+ if (dbus_set_error_from_message(&derr, reply)) {
1766+ error("bluetooth: RequestAuthorization error: %s, %s",
1767+ derr.name, derr.message);
1768+
1769+ if (dbus_error_has_name(&derr, DBUS_ERROR_NO_REPLY))
1770+ service_cancel(pending);
1771+
1772+ dbus_error_free(&derr);
1773+ g_io_channel_shutdown(io, TRUE, NULL);
1774+ goto done;
1775+ }
1776+
1777+ debug("bluetooth: RequestAuthorization succeeded");
1778+
1779+ if (!bt_io_accept(io, connect_event, service, NULL, &err)) {
1780+ error("%s", err->message);
1781+ g_error_free(err);
1782+ g_io_channel_shutdown(io, TRUE, NULL);
1783+ }
1784+
1785+done:
1786+ g_source_remove(pending->watch);
1787+ pending_request_free(pending);
1788+ dbus_message_unref(reply);
1789+}
1790+
1791+static gboolean service_error(GIOChannel *io, GIOCondition cond,
1792+ void *user_data)
1793+{
1794+ struct pending_request *pending = user_data;
1795+
1796+ service_cancel(pending);
1797+
1798+ dbus_pending_call_cancel(pending->call);
1799+
1800+ pending_request_free(pending);
1801+
1802+ return FALSE;
1803+}
1804+
1805+static void find_adapter_reply(DBusPendingCall *call, void *user_data)
1806+{
1807+ struct pending_request *pending = user_data;
1808+ DBusMessage *reply = dbus_pending_call_steal_reply(call);
1809+ DBusMessage *msg;
1810+ DBusPendingCall *pcall;
1811+ const char *path, *paddr = pending->address;
1812+ DBusError derr;
1813+
1814+ dbus_error_init(&derr);
1815+ if (dbus_set_error_from_message(&derr, reply)) {
1816+ error("Replied with an error: %s, %s",
1817+ derr.name, derr.message);
1818+ dbus_error_free(&derr);
1819+ goto failed;
1820+ }
1821+
1822+ dbus_message_get_args(reply, NULL,
1823+ DBUS_TYPE_OBJECT_PATH, &path,
1824+ DBUS_TYPE_INVALID);
1825+
1826+ debug("bluetooth: FindAdapter -> %s", path);
1827+ pending->adapter_path = g_strdup(path);
1828+ dbus_message_unref(reply);
1829+
1830+ msg = dbus_message_new_method_call("org.bluez", path,
1831+ "org.bluez.Service", "RequestAuthorization");
1832+
1833+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &paddr,
1834+ DBUS_TYPE_UINT32, &pending->service->handle,
1835+ DBUS_TYPE_INVALID);
1836+
1837+ if (!dbus_connection_send_with_reply(connection,
1838+ msg, &pcall, TIMEOUT)) {
1839+ dbus_message_unref(msg);
1840+ goto failed;
1841+ }
1842+
1843+ dbus_message_unref(msg);
1844+
1845+ debug("bluetooth: RequestAuthorization(%s, %x)", paddr,
1846+ pending->service->handle);
1847+
1848+ if (!dbus_pending_call_set_notify(pcall, service_reply, pending,
1849+ NULL)) {
1850+ dbus_pending_call_unref(pcall);
1851+ goto failed;
1852+ }
1853+
1854+ dbus_pending_call_unref(pending->call);
1855+ pending->call = pcall;
1856+
1857+ /* Catches errors before authorization response comes */
1858+ pending->watch = g_io_add_watch(pending->io,
1859+ G_IO_HUP | G_IO_ERR | G_IO_NVAL,
1860+ service_error, pending);
1861+
1862+ return;
1863+
1864+failed:
1865+ g_io_channel_shutdown(pending->io, TRUE, NULL);
1866+ pending_request_free(pending);
1867+}
1868+
1869+static int request_service_authorization(struct bluetooth_service *service,
1870+ GIOChannel *io, const char *address)
1871+{
1872+ struct pending_request *pending;
1873+ char source[18];
1874+ GError *err = NULL;
1875+
1876+ if (connection == NULL || any->path == NULL)
1877+ return -1;
1878+
1879+ bt_io_get(io, BT_IO_RFCOMM, &err,
1880+ BT_IO_OPT_SOURCE, source,
1881+ BT_IO_OPT_INVALID);
1882+ if (err) {
1883+ error("%s", err->message);
1884+ g_error_free(err);
1885+ return -EINVAL;
1886+ }
1887+
1888+ pending = g_new0(struct pending_request, 1);
1889+ pending->call = find_adapter(source, find_adapter_reply, pending);
1890+ if (!pending->call) {
1891+ g_free(pending);
1892+ return -ENOMEM;
1893+ }
1894+
1895+ pending->service = service;
1896+ pending->io = g_io_channel_ref(io);
1897+ memcpy(pending->address, address, sizeof(pending->address));
1898+
1899+ return 0;
1900+}
1901+
1902+static void confirm_event(GIOChannel *io, void *user_data)
1903+{
1904+ struct bluetooth_service *service;
1905+ GError *err = NULL;
1906+ char address[18];
1907+ uint8_t channel;
1908+
1909+ bt_io_get(io, BT_IO_RFCOMM, &err,
1910+ BT_IO_OPT_DEST, address,
1911+ BT_IO_OPT_CHANNEL, &channel,
1912+ BT_IO_OPT_INVALID);
1913+ if (err) {
1914+ error("%s", err->message);
1915+ g_error_free(err);
1916+ goto drop;
1917+ }
1918+
1919+ info("bluetooth: New connection from: %s, channel %u", address,
1920+ channel);
1921+
1922+ service = find_service(NULL, channel);
1923+ if (service == NULL) {
1924+ error("bluetooth: Unable to find service");
1925+ goto drop;
1926+ }
1927+
1928+ if (service->driver->service != OBEX_OPP) {
1929+ if (request_service_authorization(service, io, address) < 0)
1930+ goto drop;
1931+
1932+ return;
1933+ }
1934+
1935+ if (!bt_io_accept(io, connect_event, service, NULL, &err)) {
1936+ error("%s", err->message);
1937+ g_error_free(err);
1938+ goto drop;
1939+ }
1940+
1941+ return;
1942+
1943+drop:
1944+ g_io_channel_shutdown(io, TRUE, NULL);
1945+}
1946+
1947+static GIOChannel *start(struct obex_server *server,
1948+ struct obex_service_driver *service,
1949+ BtIOSecLevel sec_level)
1950+{
1951+ GIOChannel *io;
1952+ GError *err = NULL;
1953+
1954+ io = bt_io_listen(BT_IO_RFCOMM, NULL, confirm_event,
1955+ server, NULL, &err,
1956+ BT_IO_OPT_CHANNEL, service->channel,
1957+ BT_IO_OPT_SEC_LEVEL, sec_level,
1958+ BT_IO_OPT_INVALID);
1959+ if (io == NULL) {
1960+ error("bluetooth: unable to listen in channel %d: %s",
1961+ service->channel, err->message);
1962+ g_error_free(err);
1963+ } else
1964+ debug("bluetooth: listening on channel %d", service->channel);
1965+
1966+ return io;
1967+}
1968+
1969+static void *bluetooth_start(struct obex_server *server, int *err)
1970+{
1971+ BtIOSecLevel sec_level;
1972+ GSList *ios = NULL;
1973+ const GSList *l;
1974+
1975+ if (server->secure == TRUE)
1976+ sec_level = BT_IO_SEC_MEDIUM;
1977+ else
1978+ sec_level = BT_IO_SEC_LOW;
1979+
1980+ for (l = server->drivers; l; l = l->next) {
1981+ struct obex_service_driver *service = l->data;
1982+ GIOChannel *io;
1983+
1984+ io = start(server, service, sec_level);
1985+ if (io == NULL)
1986+ continue;
1987+
1988+ ios = g_slist_prepend(ios, io);
1989+ }
1990+
1991+ register_record(server);
1992+
1993+ return ios;
1994+}
1995+
1996+static void stop(gpointer data, gpointer user_data)
1997+{
1998+ GIOChannel *io = data;
1999+
2000+ g_io_channel_shutdown(io, TRUE, NULL);
2001+ g_io_channel_unref(io);
2002+}
2003+
2004+static void bluetooth_stop(void *data)
2005+{
2006+ GSList *ios = data;
2007+
2008+ g_slist_foreach(ios, stop, NULL);
2009+ g_slist_free(ios);
2010+}
2011+
2012+static struct obex_transport_driver driver = {
2013+ .name = "bluetooth",
2014+ .start = bluetooth_start,
2015+ .stop = bluetooth_stop
2016+};
2017+
2018+static unsigned int listener_id = 0;
2019+
2020+static int bluetooth_init(void)
2021+{
2022+ any = g_new0(struct adapter_any, 1);
2023+
2024+ connection = g_dbus_setup_private(DBUS_BUS_SYSTEM, NULL, NULL);
2025+ if (connection == NULL)
2026+ return -EPERM;
2027+
2028+ listener_id = g_dbus_add_service_watch(connection, "org.bluez",
2029+ name_acquired, name_released, NULL, NULL);
2030+
2031+ return obex_transport_driver_register(&driver);
2032+}
2033+
2034+static void bluetooth_exit(void)
2035+{
2036+ g_dbus_remove_watch(connection, listener_id);
2037+
2038+ if (any) {
2039+ g_slist_foreach(any->services, (GFunc) g_free, NULL);
2040+ g_slist_free(any->services);
2041+ g_free(any->path);
2042+ g_free(any);
2043+ }
2044+
2045+ if (connection)
2046+ dbus_connection_unref(connection);
2047+
2048+ obex_transport_driver_unregister(&driver);
2049+}
2050+
2051+OBEX_PLUGIN_DEFINE(bluetooth, bluetooth_init, bluetooth_exit)
2052
2053=== modified file 'plugins/filesystem.c'
2054--- plugins/filesystem.c 2010-04-27 04:17:15 +0000
2055+++ plugins/filesystem.c 2010-06-15 19:18:33 +0000
2056@@ -58,7 +58,7 @@
2057 #define FL_TYPE "<!DOCTYPE folder-listing SYSTEM \"obex-folder-listing.dtd\">" EOL_CHARS
2058
2059 #define FL_TYPE_PCSUITE "<!DOCTYPE folder-listing SYSTEM \"obex-folder-listing.dtd\"" EOL_CHARS \
2060- " [ <!ATTLIST folder mem-type CDATA #IMPLIED> ]>" EOL_CHARS
2061+ " [ <!ATTLIST folder mem-type CDATA #IMPLIED> ]>" EOL_CHARS
2062
2063 #define FL_BODY_BEGIN "<folder-listing version=\"1.0\">" EOL_CHARS
2064
2065@@ -77,16 +77,22 @@
2066 " modified=\"%s\" mem-type=\"DEV\"" \
2067 " created=\"%s\"/>" EOL_CHARS
2068
2069-static const guint8 FTP_TARGET[TARGET_SIZE] = {
2070+static const uint8_t FTP_TARGET[TARGET_SIZE] = {
2071 0xF9, 0xEC, 0x7B, 0xC4, 0x95, 0x3C, 0x11, 0xD2,
2072 0x98, 0x4E, 0x52, 0x54, 0x00, 0xDC, 0x9E, 0x09 };
2073
2074-static gchar *file_stat_line(gchar *filename, struct stat *fstat,
2075- struct stat *dstat, gboolean root,
2076- gboolean pcsuite)
2077+#define PCSUITE_WHO_SIZE 8
2078+
2079+static const uint8_t PCSUITE_WHO[PCSUITE_WHO_SIZE] = {
2080+ 'P','C',' ','S','u','i','t','e' };
2081+
2082+
2083+static char *file_stat_line(char *filename, struct stat *fstat,
2084+ struct stat *dstat, gboolean root,
2085+ gboolean pcsuite)
2086 {
2087- gchar perm[51], atime[18], ctime[18], mtime[18];
2088- gchar *escaped, *ret = NULL;
2089+ char perm[51], atime[18], ctime[18], mtime[18];
2090+ char *escaped, *ret = NULL;
2091
2092 snprintf(perm, 50, "user-perm=\"%s%s%s\" group-perm=\"%s%s%s\" "
2093 "other-perm=\"%s%s%s\"",
2094@@ -113,22 +119,26 @@
2095 mtime, ctime);
2096 else
2097 ret = g_strdup_printf(FL_FOLDER_ELEMENT, escaped, perm,
2098- atime, mtime, ctime);
2099+ atime, mtime, ctime);
2100 } else if (S_ISREG(fstat->st_mode))
2101 ret = g_strdup_printf(FL_FILE_ELEMENT, escaped, fstat->st_size,
2102- perm, atime, mtime, ctime);
2103+ perm, atime, mtime, ctime);
2104
2105 g_free(escaped);
2106
2107 return ret;
2108 }
2109
2110-static gpointer filesystem_open(const char *name, int oflag, mode_t mode,
2111- gpointer context, size_t *size, int *err)
2112+static void *filesystem_open(const char *name, int oflag, mode_t mode,
2113+ void *context, size_t *size, int *err)
2114 {
2115 struct stat stats;
2116 struct statvfs buf;
2117+ const char *root_folder;
2118+ char *folder;
2119+ gboolean root;
2120 int fd = open(name, oflag, mode);
2121+ uint64_t avail;
2122
2123 if (fd < 0) {
2124 if (err)
2125@@ -142,6 +152,21 @@
2126 goto failed;
2127 }
2128
2129+ root_folder = obex_option_root_folder();
2130+ folder = g_path_get_dirname(name);
2131+ root = g_strcmp0(folder, root_folder);
2132+
2133+ g_free(folder);
2134+
2135+ if (!root || obex_option_symlinks()) {
2136+ if (S_ISLNK(stats.st_mode)) {
2137+ if (err)
2138+ *err = -EPERM;
2139+ goto failed;
2140+ }
2141+
2142+ }
2143+
2144 if (oflag == O_RDONLY) {
2145 if (size)
2146 *size = stats.st_size;
2147@@ -157,7 +182,8 @@
2148 if (size == NULL)
2149 goto done;
2150
2151- if (buf.f_bsize * buf.f_bavail < *size) {
2152+ avail = (uint64_t) buf.f_bsize * buf.f_bavail;
2153+ if (avail < *size) {
2154 if (err)
2155 *err = -ENOSPC;
2156 goto failed;
2157@@ -174,7 +200,7 @@
2158 return NULL;
2159 }
2160
2161-static int filesystem_close(gpointer object)
2162+static int filesystem_close(void *object)
2163 {
2164 if (close(GPOINTER_TO_INT(object)) < 0)
2165 return -errno;
2166@@ -182,7 +208,8 @@
2167 return 0;
2168 }
2169
2170-static ssize_t filesystem_read(gpointer object, void *buf, size_t count)
2171+static ssize_t filesystem_read(void *object, void *buf, size_t count,
2172+ uint8_t *hi)
2173 {
2174 ssize_t ret;
2175
2176@@ -190,10 +217,12 @@
2177 if (ret < 0)
2178 return -errno;
2179
2180+ *hi = OBEX_HDR_BODY;
2181+
2182 return ret;
2183 }
2184
2185-static ssize_t filesystem_write(gpointer object, const void *buf, size_t count)
2186+static ssize_t filesystem_write(void *object, const void *buf, size_t count)
2187 {
2188 ssize_t ret;
2189
2190@@ -208,11 +237,11 @@
2191 int pid;
2192 int output;
2193 int err;
2194- guint watch;
2195+ unsigned int watch;
2196 GString *buffer;
2197 };
2198
2199-static void script_exited(GPid pid, gint status, gpointer data)
2200+static void script_exited(GPid pid, int status, void *data)
2201 {
2202 struct capability_object *object = data;
2203 char buf[128];
2204@@ -246,11 +275,11 @@
2205 return pid;
2206 }
2207
2208-static gpointer capability_open(const char *name, int oflag, mode_t mode,
2209- gpointer context, size_t *size, int *err)
2210+static void *capability_open(const char *name, int oflag, mode_t mode,
2211+ void *context, size_t *size, int *err)
2212 {
2213 struct capability_object *object = NULL;
2214- gchar *buf;
2215+ char *buf;
2216 const char *argv[2];
2217
2218 if (oflag != O_RDONLY)
2219@@ -306,25 +335,26 @@
2220 return NULL;
2221 }
2222
2223-static gpointer folder_open(const char *name, int oflag, mode_t mode,
2224- gpointer context, size_t *size, int *err)
2225-{
2226- struct obex_session *os = context;
2227+static GString *append_pcsuite_preamble(GString *object)
2228+{
2229+ return g_string_append(object, FL_TYPE_PCSUITE);
2230+}
2231+
2232+static GString *append_folder_preamble(GString *object)
2233+{
2234+ return g_string_append(object, FL_TYPE);
2235+}
2236+
2237+static GString *append_listing(GString *object, const char *name,
2238+ gboolean pcsuite, size_t *size, int *err)
2239+{
2240 struct stat fstat, dstat;
2241 struct dirent *ep;
2242- GString *object;
2243 DIR *dp;
2244- gboolean root, pcsuite, symlinks;
2245- gint ret;
2246-
2247- pcsuite = obex_get_service(os) & OBEX_PCSUITE ? TRUE : FALSE;
2248-
2249- object = g_string_new(FL_VERSION);
2250- object = g_string_append(object, pcsuite ? FL_TYPE_PCSUITE : FL_TYPE);
2251-
2252- object = g_string_append(object, FL_BODY_BEGIN);
2253-
2254- root = g_str_equal(name, obex_get_root_folder(os));
2255+ gboolean root, symlinks;
2256+ int ret;
2257+
2258+ root = g_str_equal(name, obex_option_root_folder());
2259
2260 dp = opendir(name);
2261 if (dp == NULL) {
2262@@ -333,7 +363,7 @@
2263 goto failed;
2264 }
2265
2266- symlinks = obex_get_symlinks(os);
2267+ symlinks = obex_option_symlinks();
2268 if (root && symlinks)
2269 ret = stat(name, &dstat);
2270 else {
2271@@ -348,9 +378,9 @@
2272 }
2273
2274 while ((ep = readdir(dp))) {
2275- gchar *filename;
2276- gchar *fullname;
2277- gchar *line;
2278+ char *filename;
2279+ char *fullname;
2280+ char *line;
2281
2282 if (ep->d_name[0] == '.')
2283 continue;
2284@@ -378,7 +408,7 @@
2285
2286 g_free(fullname);
2287
2288- line = file_stat_line(filename, &fstat, &dstat, root, pcsuite);
2289+ line = file_stat_line(filename, &fstat, &dstat, root, FALSE);
2290 if (line == NULL) {
2291 g_free(filename);
2292 continue;
2293@@ -409,7 +439,31 @@
2294 return NULL;
2295 }
2296
2297-int string_free(gpointer object)
2298+static void *folder_open(const char *name, int oflag, mode_t mode,
2299+ void *context, size_t *size, int *err)
2300+{
2301+ GString *object;
2302+
2303+ object = g_string_new(FL_VERSION);
2304+ object = append_folder_preamble(object);
2305+ object = g_string_append(object, FL_BODY_BEGIN);
2306+
2307+ return append_listing(object, name, FALSE, size, err);
2308+}
2309+
2310+static void *pcsuite_open(const char *name, int oflag, mode_t mode,
2311+ void *context, size_t *size, int *err)
2312+{
2313+ GString *object;
2314+
2315+ object = g_string_new(FL_VERSION);
2316+ object = append_pcsuite_preamble(object);
2317+ object = g_string_append(object, FL_BODY_BEGIN);
2318+
2319+ return append_listing(object, name, TRUE, size, err);
2320+}
2321+
2322+int string_free(void *object)
2323 {
2324 GString *string = object;
2325
2326@@ -418,7 +472,7 @@
2327 return 0;
2328 }
2329
2330-ssize_t string_read(gpointer object, void *buf, size_t count)
2331+ssize_t string_read(void *object, void *buf, size_t count)
2332 {
2333 GString *string = object;
2334 ssize_t len;
2335@@ -433,10 +487,19 @@
2336 return len;
2337 }
2338
2339-static ssize_t capability_read(gpointer object, void *buf, size_t count)
2340+static ssize_t folder_read(void *object, void *buf, size_t count, uint8_t *hi)
2341+{
2342+ *hi = OBEX_HDR_BODY;
2343+ return string_read(object, buf, count);
2344+}
2345+
2346+static ssize_t capability_read(void *object, void *buf, size_t count,
2347+ uint8_t *hi)
2348 {
2349 struct capability_object *obj = object;
2350
2351+ *hi = OBEX_HDR_BODY;
2352+
2353 if (obj->buffer)
2354 return string_read(obj->buffer, buf, count);
2355
2356@@ -446,7 +509,7 @@
2357 return read(obj->output, buf, count);
2358 }
2359
2360-static int capability_close(gpointer object)
2361+static int capability_close(void *object)
2362 {
2363 struct capability_object *obj = object;
2364
2365@@ -464,7 +527,7 @@
2366 return 0;
2367 }
2368
2369-struct obex_mime_type_driver file = {
2370+static struct obex_mime_type_driver file = {
2371 .open = filesystem_open,
2372 .close = filesystem_close,
2373 .read = filesystem_read,
2374@@ -472,7 +535,7 @@
2375 .remove = remove,
2376 };
2377
2378-struct obex_mime_type_driver capability = {
2379+static struct obex_mime_type_driver capability = {
2380 .target = FTP_TARGET,
2381 .mimetype = "x-obex/capability",
2382 .open = capability_open,
2383@@ -480,12 +543,22 @@
2384 .read = capability_read,
2385 };
2386
2387-struct obex_mime_type_driver folder = {
2388+static struct obex_mime_type_driver folder = {
2389 .target = FTP_TARGET,
2390 .mimetype = "x-obex/folder-listing",
2391 .open = folder_open,
2392 .close = string_free,
2393- .read = string_read,
2394+ .read = folder_read,
2395+};
2396+
2397+static struct obex_mime_type_driver pcsuite = {
2398+ .target = FTP_TARGET,
2399+ .who = PCSUITE_WHO,
2400+ .who_size = PCSUITE_WHO_SIZE,
2401+ .mimetype = "x-obex/folder-listing",
2402+ .open = pcsuite_open,
2403+ .close = string_free,
2404+ .read = folder_read,
2405 };
2406
2407 static int filesystem_init(void)
2408@@ -500,6 +573,10 @@
2409 if (err < 0)
2410 return err;
2411
2412+ err = obex_mime_type_driver_register(&pcsuite);
2413+ if (err < 0)
2414+ return err;
2415+
2416 return obex_mime_type_driver_register(&file);
2417 }
2418
2419
2420=== modified file 'plugins/filesystem.h'
2421--- plugins/filesystem.h 2010-04-27 04:17:15 +0000
2422+++ plugins/filesystem.h 2010-06-15 19:18:33 +0000
2423@@ -21,5 +21,5 @@
2424 *
2425 */
2426
2427-int string_free(gpointer object);
2428-ssize_t string_read(gpointer object, void *buf, size_t count);
2429+int string_free(void *object);
2430+ssize_t string_read(void *object, void *buf, size_t count);
2431
2432=== modified file 'plugins/ftp.c'
2433--- plugins/ftp.c 2010-04-27 04:17:15 +0000
2434+++ plugins/ftp.c 2010-06-15 19:18:33 +0000
2435@@ -54,99 +54,100 @@
2436 #define LST_TYPE "x-obex/folder-listing"
2437 #define CAP_TYPE "x-obex/capability"
2438
2439-#define FTP_CHANNEL 10
2440-#define FTP_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
2441-<record> \
2442- <attribute id=\"0x0001\"> \
2443- <sequence> \
2444- <uuid value=\"0x1106\"/> \
2445- </sequence> \
2446- </attribute> \
2447- \
2448- <attribute id=\"0x0004\"> \
2449- <sequence> \
2450- <sequence> \
2451- <uuid value=\"0x0100\"/> \
2452- </sequence> \
2453- <sequence> \
2454- <uuid value=\"0x0003\"/> \
2455- <uint8 value=\"%u\" name=\"channel\"/> \
2456- </sequence> \
2457- <sequence> \
2458- <uuid value=\"0x0008\"/> \
2459- </sequence> \
2460- </sequence> \
2461- </attribute> \
2462- \
2463- <attribute id=\"0x0009\"> \
2464- <sequence> \
2465- <sequence> \
2466- <uuid value=\"0x1106\"/> \
2467- <uint16 value=\"0x0100\" name=\"version\"/> \
2468- </sequence> \
2469- </sequence> \
2470- </attribute> \
2471- \
2472- <attribute id=\"0x0100\"> \
2473- <text value=\"%s\" name=\"name\"/> \
2474- </attribute> \
2475+#define FTP_CHANNEL 10
2476+#define FTP_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
2477+<record> \
2478+ <attribute id=\"0x0001\"> \
2479+ <sequence> \
2480+ <uuid value=\"0x1106\"/> \
2481+ </sequence> \
2482+ </attribute> \
2483+ \
2484+ <attribute id=\"0x0004\"> \
2485+ <sequence> \
2486+ <sequence> \
2487+ <uuid value=\"0x0100\"/> \
2488+ </sequence> \
2489+ <sequence> \
2490+ <uuid value=\"0x0003\"/> \
2491+ <uint8 value=\"%u\" name=\"channel\"/> \
2492+ </sequence> \
2493+ <sequence> \
2494+ <uuid value=\"0x0008\"/> \
2495+ </sequence> \
2496+ </sequence> \
2497+ </attribute> \
2498+ \
2499+ <attribute id=\"0x0009\"> \
2500+ <sequence> \
2501+ <sequence> \
2502+ <uuid value=\"0x1106\"/> \
2503+ <uint16 value=\"0x0100\" name=\"version\"/> \
2504+ </sequence> \
2505+ </sequence> \
2506+ </attribute> \
2507+ \
2508+ <attribute id=\"0x0100\"> \
2509+ <text value=\"%s\" name=\"name\"/> \
2510+ </attribute> \
2511 </record>"
2512
2513-#define PCSUITE_CHANNEL 24
2514+#define PCSUITE_CHANNEL 24
2515 #define PCSUITE_WHO_SIZE 8
2516-#define PCSUITE_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
2517-<record> \
2518- <attribute id=\"0x0001\"> \
2519- <sequence> \
2520- <uuid value=\"00005005-0000-1000-8000-0002ee000001\"/> \
2521- </sequence> \
2522- </attribute> \
2523- \
2524- <attribute id=\"0x0004\"> \
2525- <sequence> \
2526- <sequence> \
2527- <uuid value=\"0x0100\"/> \
2528- </sequence> \
2529- <sequence> \
2530- <uuid value=\"0x0003\"/> \
2531- <uint8 value=\"%u\" name=\"channel\"/> \
2532- </sequence> \
2533- <sequence> \
2534- <uuid value=\"0x0008\"/> \
2535- </sequence> \
2536- </sequence> \
2537- </attribute> \
2538- \
2539- <attribute id=\"0x0005\"> \
2540- <sequence> \
2541- <uuid value=\"0x1002\"/> \
2542- </sequence> \
2543- </attribute> \
2544- \
2545- <attribute id=\"0x0009\"> \
2546- <sequence> \
2547- <sequence> \
2548- <uuid value=\"00005005-0000-1000-8000-0002ee000001\"/> \
2549- <uint16 value=\"0x0100\" name=\"version\"/> \
2550- </sequence> \
2551- </sequence> \
2552- </attribute> \
2553- \
2554- <attribute id=\"0x0100\"> \
2555- <text value=\"%s\" name=\"name\"/> \
2556- </attribute> \
2557+
2558+#define PCSUITE_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
2559+<record> \
2560+ <attribute id=\"0x0001\"> \
2561+ <sequence> \
2562+ <uuid value=\"00005005-0000-1000-8000-0002ee000001\"/> \
2563+ </sequence> \
2564+ </attribute> \
2565+ \
2566+ <attribute id=\"0x0004\"> \
2567+ <sequence> \
2568+ <sequence> \
2569+ <uuid value=\"0x0100\"/> \
2570+ </sequence> \
2571+ <sequence> \
2572+ <uuid value=\"0x0003\"/> \
2573+ <uint8 value=\"%u\" name=\"channel\"/> \
2574+ </sequence> \
2575+ <sequence> \
2576+ <uuid value=\"0x0008\"/> \
2577+ </sequence> \
2578+ </sequence> \
2579+ </attribute> \
2580+ \
2581+ <attribute id=\"0x0005\"> \
2582+ <sequence> \
2583+ <uuid value=\"0x1002\"/> \
2584+ </sequence> \
2585+ </attribute> \
2586+ \
2587+ <attribute id=\"0x0009\"> \
2588+ <sequence> \
2589+ <sequence> \
2590+ <uuid value=\"00005005-0000-1000-8000-0002ee000001\"/> \
2591+ <uint16 value=\"0x0100\" name=\"version\"/> \
2592+ </sequence> \
2593+ </sequence> \
2594+ </attribute> \
2595+ \
2596+ <attribute id=\"0x0100\"> \
2597+ <text value=\"%s\" name=\"name\"/> \
2598+ </attribute> \
2599 </record>"
2600
2601-static const guint8 FTP_TARGET[TARGET_SIZE] = {
2602- 0xF9, 0xEC, 0x7B, 0xC4, 0x95, 0x3C, 0x11, 0xD2,
2603- 0x98, 0x4E, 0x52, 0x54, 0x00, 0xDC, 0x9E, 0x09 };
2604+static const uint8_t FTP_TARGET[TARGET_SIZE] = {
2605+ 0xF9, 0xEC, 0x7B, 0xC4, 0x95, 0x3C, 0x11, 0xD2,
2606+ 0x98, 0x4E, 0x52, 0x54, 0x00, 0xDC, 0x9E, 0x09 };
2607
2608-static const guint8 PCSUITE_WHO[PCSUITE_WHO_SIZE] = {
2609+static const uint8_t PCSUITE_WHO[PCSUITE_WHO_SIZE] = {
2610 'P','C',' ','S','u','i','t','e' };
2611
2612 struct ftp_session {
2613 struct obex_session *os;
2614- gchar *folder;
2615+ char *folder;
2616 };
2617
2618 static void set_folder(struct ftp_session *ftp, const char *new_folder)
2619@@ -156,49 +157,32 @@
2620 ftp->folder = new_folder ? g_strdup(new_folder) : NULL;
2621 }
2622
2623-static gint get_by_type(struct ftp_session *ftp, const gchar *type)
2624+static int get_by_type(struct ftp_session *ftp, const char *type)
2625 {
2626 struct obex_session *os = ftp->os;
2627 const char *capability = obex_get_capability_path(os);
2628-
2629- if (type == NULL)
2630- return -ENOENT;
2631-
2632- if (g_str_equal(type, CAP_TYPE))
2633- return obex_stream_start(os, capability, NULL);
2634-
2635- if (g_str_equal(type, LST_TYPE))
2636- return obex_stream_start(os, ftp->folder, os);
2637-
2638- return -ENOENT;
2639-}
2640-
2641-static gint ftp_prepare_get(struct ftp_session *ftp, gchar *file)
2642-{
2643- struct obex_session *os = ftp->os;
2644- const char *root_folder = obex_get_root_folder(os);
2645- gboolean root;
2646-
2647- root = g_str_equal(root_folder, ftp->folder);
2648-
2649- if (!root || !obex_get_symlinks(os)) {
2650- struct stat dstat;
2651- gint err;
2652-
2653- if (lstat(file, &dstat) < 0) {
2654- err = -errno;
2655- debug("lstat: %s(%d)", strerror(errno), errno);
2656- return err;
2657- }
2658-
2659- if (S_ISLNK(dstat.st_mode))
2660- return -EPERM;
2661- }
2662-
2663- return obex_stream_start(os, file, NULL);
2664-}
2665-
2666-static gpointer ftp_connect(struct obex_session *os, int *err)
2667+ const char *name = obex_get_name(os);
2668+ char *path;
2669+ int err;
2670+
2671+ if (type == NULL && name == NULL)
2672+ return -EBADR;
2673+
2674+ if (g_strcmp0(type, CAP_TYPE) == 0)
2675+ return obex_get_stream_start(os, capability);
2676+
2677+ if (g_strcmp0(type, LST_TYPE) == 0)
2678+ return obex_get_stream_start(os, ftp->folder);
2679+
2680+ path = g_build_filename(ftp->folder, name, NULL);
2681+ err = obex_get_stream_start(os, path);
2682+
2683+ g_free(path);
2684+
2685+ return err;
2686+}
2687+
2688+static void *ftp_connect(struct obex_session *os, int *err)
2689 {
2690 struct ftp_session *ftp;
2691 const char *root_folder;
2692@@ -218,43 +202,28 @@
2693 }
2694
2695 static int ftp_get(struct obex_session *os, obex_object_t *obj,
2696- gpointer user_data)
2697+ gboolean *stream, void *user_data)
2698 {
2699 struct ftp_session *ftp = user_data;
2700 const char *type = obex_get_type(os);
2701- const char *name = obex_get_name(os);
2702- gint err;
2703- gchar *path;
2704-
2705- if (ftp->folder == NULL) {
2706- err = -ENOENT;
2707- goto fail;
2708- }
2709-
2710- err = get_by_type(ftp, type);
2711- if (err < 0) {
2712- if (!name)
2713- goto fail;
2714-
2715- path = g_build_filename(ftp->folder, name, NULL);
2716-
2717- err = ftp_prepare_get(ftp, path);
2718-
2719- g_free(path);
2720-
2721- if (err < 0)
2722- goto fail;
2723- }
2724+ int ret;
2725+
2726+ if (ftp->folder == NULL)
2727+ return -ENOENT;
2728+
2729+ ret = get_by_type(ftp, type);
2730+ if (ret < 0)
2731+ return ret;
2732+
2733+ if (stream)
2734+ *stream = TRUE;
2735
2736 return 0;
2737-
2738-fail:
2739- return err;
2740 }
2741
2742-static gint ftp_delete(struct ftp_session *ftp, const char *name)
2743+static int ftp_delete(struct ftp_session *ftp, const char *name)
2744 {
2745- gchar *path;
2746+ char *path;
2747 int ret = 0;
2748
2749 if (!(ftp->folder && name))
2750@@ -270,26 +239,29 @@
2751 return ret;
2752 }
2753
2754-static gint ftp_chkput(struct obex_session *os, gpointer user_data)
2755+static int ftp_chkput(struct obex_session *os, void *user_data)
2756 {
2757 struct ftp_session *ftp = user_data;
2758- const gchar *name = obex_get_name(os);
2759- gchar *path;
2760+ const char *name = obex_get_name(os);
2761+ char *path;
2762 int ret;
2763
2764+ if (name == NULL)
2765+ return -EBADR;
2766+
2767 if (obex_get_size(os) == OBJECT_SIZE_DELETE)
2768 return 0;
2769
2770 path = g_build_filename(ftp->folder, name, NULL);
2771
2772- ret = obex_prepare_put(os, path);
2773+ ret = obex_put_stream_start(os, path);
2774
2775 g_free(path);
2776
2777 return ret;
2778 }
2779
2780-static int ftp_put(struct obex_session *os, gpointer user_data)
2781+static int ftp_put(struct obex_session *os, void *user_data)
2782 {
2783 struct ftp_session *ftp = user_data;
2784 const char *name = obex_get_name(os);
2785@@ -308,12 +280,12 @@
2786 }
2787
2788 static int ftp_setpath(struct obex_session *os, obex_object_t *obj,
2789- gpointer user_data)
2790+ void *user_data)
2791 {
2792 struct ftp_session *ftp = user_data;
2793- const gchar *root_folder, *name;
2794- guint8 *nonhdr;
2795- gchar *fullname;
2796+ const char *root_folder, *name;
2797+ uint8_t *nonhdr;
2798+ char *fullname;
2799 struct stat dstat;
2800 gboolean root;
2801 int err;
2802@@ -370,11 +342,13 @@
2803 err = lstat(fullname, &dstat);
2804
2805 if (err < 0) {
2806- int err = errno;
2807+ err = -errno;
2808+
2809+ if (err == -ENOENT)
2810+ goto not_found;
2811+
2812 debug("%s: %s(%d)", root ? "stat" : "lstat",
2813- strerror(err), err);
2814- if (err == ENOENT)
2815- goto not_found;
2816+ strerror(-err), -err);
2817
2818 goto done;
2819 }
2820@@ -395,10 +369,12 @@
2821 }
2822
2823 if (mkdir(fullname, 0755) < 0) {
2824- err = -EPERM;
2825+ err = -errno;
2826+ debug("mkdir: %s(%d)", strerror(-err), -err);
2827 goto done;
2828 }
2829
2830+ err = 0;
2831 set_folder(ftp, fullname);
2832
2833 done:
2834@@ -406,7 +382,7 @@
2835 return err;
2836 }
2837
2838-static void ftp_disconnect(struct obex_session *os, gpointer user_data)
2839+static void ftp_disconnect(struct obex_session *os, void *user_data)
2840 {
2841 struct ftp_session *ftp = user_data;
2842
2843@@ -416,7 +392,7 @@
2844 g_free(ftp);
2845 }
2846
2847-struct obex_service_driver pcsuite = {
2848+static struct obex_service_driver pcsuite = {
2849 .name = "Nokia OBEX PC Suite Services",
2850 .service = OBEX_PCSUITE,
2851 .channel = PCSUITE_CHANNEL,
2852@@ -433,7 +409,7 @@
2853 .disconnect = ftp_disconnect
2854 };
2855
2856-struct obex_service_driver ftp = {
2857+static struct obex_service_driver ftp = {
2858 .name = "File Transfer server",
2859 .service = OBEX_FTP,
2860 .channel = FTP_CHANNEL,
2861
2862=== added file 'plugins/nokia-backup.c'
2863--- plugins/nokia-backup.c 1970-01-01 00:00:00 +0000
2864+++ plugins/nokia-backup.c 2010-06-15 19:18:33 +0000
2865@@ -0,0 +1,295 @@
2866+/*
2867+ *
2868+ * OBEX Server
2869+ *
2870+ * Copyright (C) 2010 Nokia Corporation
2871+ * Copyright (C) 2010 Marcel Holtmann <marcel@holtmann.org>
2872+ *
2873+ *
2874+ * This program is free software; you can redistribute it and/or modify
2875+ * it under the terms of the GNU General Public License as published by
2876+ * the Free Software Foundation; either version 2 of the License, or
2877+ * (at your option) any later version.
2878+ *
2879+ * This program is distributed in the hope that it will be useful,
2880+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2881+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2882+ * GNU General Public License for more details.
2883+ *
2884+ * You should have received a copy of the GNU General Public License
2885+ * along with this program; if not, write to the Free Software
2886+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
2887+ *
2888+ */
2889+
2890+#ifdef HAVE_CONFIG_H
2891+#include <config.h>
2892+#endif
2893+
2894+#include <stdio.h>
2895+#include <errno.h>
2896+#include <stdlib.h>
2897+#include <string.h>
2898+#include <unistd.h>
2899+#include <dirent.h>
2900+#include <sys/stat.h>
2901+#include <sys/types.h>
2902+#include <sys/stat.h>
2903+#include <sys/statvfs.h>
2904+#include <fcntl.h>
2905+#include <wait.h>
2906+
2907+#include <glib.h>
2908+#include "gdbus.h"
2909+
2910+
2911+#include <openobex/obex.h>
2912+#include <openobex/obex_const.h>
2913+
2914+#include "plugin.h"
2915+#include "logging.h"
2916+#include "obex.h"
2917+#include "mimetype.h"
2918+#include "service.h"
2919+
2920+#define BACKUP_BUS_NAME "com.nokia.backup.plugin"
2921+#define BACKUP_PATH "/com/nokia/backup"
2922+#define BACKUP_PLUGIN_INTERFACE "com.nokia.backup.plugin"
2923+#define BACKUP_DBUS_TIMEOUT (1000 * 60 * 15)
2924+
2925+static const uint8_t FTP_TARGET[TARGET_SIZE] = {
2926+ 0xF9, 0xEC, 0x7B, 0xC4, 0x95, 0x3C, 0x11, 0xD2,
2927+ 0x98, 0x4E, 0x52, 0x54, 0x00, 0xDC, 0x9E, 0x09 };
2928+
2929+struct backup_object{
2930+ gchar *cmd;
2931+ int fd;
2932+ int oflag;
2933+ int error_code;
2934+ mode_t mode;
2935+ DBusPendingCall *pending_call;
2936+ DBusConnection *conn;
2937+};
2938+
2939+static void on_backup_dbus_notify(DBusPendingCall *pending_call,
2940+ void *user_data)
2941+{
2942+ struct backup_object *obj = user_data;
2943+ DBusMessage *reply;
2944+ const char *filename;
2945+ int error_code;
2946+
2947+ debug("backup: Notification received for pending call - %s", obj->cmd);
2948+
2949+ reply = dbus_pending_call_steal_reply(pending_call);
2950+
2951+ if (reply && dbus_message_get_args(reply, NULL, DBUS_TYPE_INT32,
2952+ &error_code, DBUS_TYPE_STRING,
2953+ &filename, DBUS_TYPE_INVALID)) {
2954+
2955+ obj->error_code = error_code;
2956+
2957+ if (filename) {
2958+ debug("backup: Notification - file path = %s,"
2959+ "error_code = %d", filename,
2960+ error_code);
2961+ if (error_code == 0)
2962+ obj->fd = open(filename,obj->oflag,obj->mode);
2963+ }
2964+
2965+ } else
2966+ debug("backup: Notification timed out or connection got closed");
2967+
2968+ if (reply)
2969+ dbus_message_unref(reply);
2970+
2971+ dbus_pending_call_unref(pending_call);
2972+ obj->pending_call = NULL;
2973+ dbus_connection_unref(obj->conn);
2974+ obj->conn = NULL;
2975+
2976+ if (obj->fd >= 0) {
2977+ debug("backup: File opened, setting io flags, cmd = %s",
2978+ obj->cmd);
2979+ if (obj->oflag == O_RDONLY)
2980+ obex_object_set_io_flags(user_data, G_IO_IN, 0);
2981+ else
2982+ obex_object_set_io_flags(user_data, G_IO_OUT, 0);
2983+ } else {
2984+ debug("backup: File open error, setting io error, cmd = %s",
2985+ obj->cmd);
2986+ obex_object_set_io_flags(user_data, G_IO_ERR, -EPERM);
2987+ }
2988+}
2989+
2990+static gboolean send_backup_dbus_message(const char *oper,
2991+ struct backup_object *obj,
2992+ size_t *size)
2993+{
2994+ DBusConnection *conn;
2995+ DBusMessage *msg;
2996+ DBusPendingCall *pending_call;
2997+ gboolean ret = FALSE;
2998+ dbus_uint32_t file_size;
2999+
3000+ file_size = size ? *size : 0;
3001+
3002+ conn = g_dbus_setup_bus(DBUS_BUS_SESSION, NULL, NULL);
3003+
3004+ if (conn == NULL)
3005+ return FALSE;
3006+
3007+ msg = dbus_message_new_method_call(BACKUP_BUS_NAME, BACKUP_PATH,
3008+ BACKUP_PLUGIN_INTERFACE,
3009+ "request");
3010+ if (msg == NULL) {
3011+ dbus_connection_unref(conn);
3012+ return FALSE;
3013+ }
3014+
3015+ dbus_message_append_args(msg, DBUS_TYPE_STRING, &oper,
3016+ DBUS_TYPE_STRING, &obj->cmd,
3017+ DBUS_TYPE_INT32, &file_size,
3018+ DBUS_TYPE_INVALID);
3019+
3020+ ret = dbus_connection_send_with_reply(conn, msg, &pending_call,
3021+ BACKUP_DBUS_TIMEOUT);
3022+
3023+ dbus_message_unref(msg);
3024+
3025+ if (ret && (strcmp(oper, "open") == 0)) {
3026+ obj->conn = conn;
3027+ obj->pending_call = pending_call;
3028+ ret = dbus_pending_call_set_notify(pending_call,
3029+ on_backup_dbus_notify,
3030+ obj, NULL);
3031+ } else {
3032+ dbus_pending_call_unref(pending_call);
3033+ dbus_connection_unref(conn);
3034+ }
3035+
3036+ return ret;
3037+}
3038+
3039+static void *backup_open(const char *name, int oflag, mode_t mode,
3040+ void *context, size_t *size, int *err)
3041+{
3042+ struct backup_object *obj = g_new0(struct backup_object, 1);
3043+
3044+ debug("backup: open(), cmd = %s", name);
3045+
3046+ obj->cmd = g_path_get_basename(name);
3047+ obj->oflag = oflag;
3048+ obj->mode = mode;
3049+ obj->fd = -1;
3050+ obj->pending_call = NULL;
3051+ obj->conn = NULL;
3052+ obj->error_code = 0;
3053+
3054+ if (send_backup_dbus_message("open", obj, size) == FALSE) {
3055+ g_free(obj);
3056+ obj = NULL;
3057+ }
3058+
3059+ if (err)
3060+ *err = 0;
3061+
3062+ return obj;
3063+}
3064+
3065+static int backup_close(void *object)
3066+{
3067+ struct backup_object *obj = object;
3068+ size_t size = 0;
3069+
3070+ debug("backup: close(), cmd = %s", obj->cmd);
3071+
3072+ if (obj->fd != -1)
3073+ close(obj->fd);
3074+
3075+ if (obj->pending_call) {
3076+ dbus_pending_call_cancel(obj->pending_call);
3077+ dbus_pending_call_unref(obj->pending_call);
3078+ dbus_connection_unref(obj->conn);
3079+ }
3080+
3081+ send_backup_dbus_message("close", obj, &size);
3082+
3083+ g_free(obj->cmd);
3084+ g_free(obj);
3085+
3086+ return 0;
3087+}
3088+
3089+static ssize_t backup_read(void *object, void *buf, size_t count, uint8_t *hi)
3090+{
3091+ struct backup_object *obj = object;
3092+ ssize_t ret = 0;
3093+
3094+ *hi = OBEX_HDR_BODY;
3095+
3096+ if (obj->pending_call) {
3097+ debug("backup: read(), cmd = %s, IN WAITING STAGE", obj->cmd);
3098+ return -EAGAIN;
3099+ }
3100+
3101+ if (obj->fd != -1) {
3102+ debug("backup: read(), cmd = %s, READING DATA", obj->cmd);
3103+ ret = read(obj->fd, buf, count);
3104+ if (ret < 0)
3105+ ret = -errno;
3106+ } else {
3107+ debug("backup: read(), cmd = %s, PERMANENT FAILURE", obj->cmd);
3108+ ret = obj->error_code?(-obj->error_code):(-ENOENT);
3109+ }
3110+
3111+ return ret;
3112+}
3113+
3114+static ssize_t backup_write(void *object, const void *buf, size_t count)
3115+{
3116+ struct backup_object *obj = object;
3117+ ssize_t ret = 0;
3118+
3119+ if (obj->pending_call) {
3120+ debug("backup: write(), cmd = %s, IN WAITING STAGE", obj->cmd);
3121+ return -EAGAIN;
3122+ }
3123+
3124+ if (obj->fd != -1) {
3125+ ret = write(obj->fd, buf, count);
3126+
3127+ debug("backup: write(), cmd = %s, WRITTING", obj->cmd);
3128+
3129+ if (ret < 0) {
3130+ debug("backup: write() error, cmd = %s", obj->cmd);
3131+ ret = -errno;
3132+ }
3133+ } else {
3134+ debug("backup: write() error, cmd = %s", obj->cmd);
3135+ ret = obj->error_code ? -obj->error_code : -ENOENT;
3136+ }
3137+
3138+ return ret;
3139+}
3140+
3141+static struct obex_mime_type_driver backup = {
3142+ .target = FTP_TARGET,
3143+ .mimetype = "application/vnd.nokia-backup",
3144+ .open = backup_open,
3145+ .close = backup_close,
3146+ .read = backup_read,
3147+ .write = backup_write,
3148+};
3149+
3150+static int backup_init(void)
3151+{
3152+ return obex_mime_type_driver_register(&backup);
3153+}
3154+
3155+static void backup_exit(void)
3156+{
3157+ obex_mime_type_driver_unregister(&backup);
3158+}
3159+
3160+OBEX_PLUGIN_DEFINE(backup, backup_init, backup_exit)
3161
3162=== modified file 'plugins/opp.c'
3163--- plugins/opp.c 2010-04-27 04:17:15 +0000
3164+++ plugins/opp.c 2010-06-15 19:18:33 +0000
3165@@ -27,6 +27,7 @@
3166 #endif
3167
3168 #include <errno.h>
3169+#include <string.h>
3170
3171 #include <openobex/obex.h>
3172 #include <openobex/obex_const.h>
3173@@ -44,56 +45,56 @@
3174
3175 #define OPP_CHANNEL 9
3176 #define OPP_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
3177-<record> \
3178- <attribute id=\"0x0001\"> \
3179- <sequence> \
3180- <uuid value=\"0x1105\"/> \
3181- </sequence> \
3182- </attribute> \
3183- \
3184- <attribute id=\"0x0004\"> \
3185- <sequence> \
3186- <sequence> \
3187- <uuid value=\"0x0100\"/> \
3188- </sequence> \
3189- <sequence> \
3190- <uuid value=\"0x0003\"/> \
3191- <uint8 value=\"%u\" name=\"channel\"/> \
3192- </sequence> \
3193- <sequence> \
3194- <uuid value=\"0x0008\"/> \
3195- </sequence> \
3196- </sequence> \
3197- </attribute> \
3198- \
3199- <attribute id=\"0x0009\"> \
3200- <sequence> \
3201- <sequence> \
3202- <uuid value=\"0x1105\"/> \
3203- <uint16 value=\"0x0100\" name=\"version\"/> \
3204- </sequence> \
3205- </sequence> \
3206- </attribute> \
3207- \
3208- <attribute id=\"0x0100\"> \
3209- <text value=\"%s\" name=\"name\"/> \
3210- </attribute> \
3211- \
3212- <attribute id=\"0x0303\"> \
3213- <sequence> \
3214- <uint8 value=\"0x01\"/> \
3215- <uint8 value=\"0x01\"/> \
3216- <uint8 value=\"0x02\"/> \
3217- <uint8 value=\"0x03\"/> \
3218- <uint8 value=\"0x04\"/> \
3219- <uint8 value=\"0x05\"/> \
3220- <uint8 value=\"0x06\"/> \
3221- <uint8 value=\"0xff\"/> \
3222- </sequence> \
3223- </attribute> \
3224+<record> \
3225+ <attribute id=\"0x0001\"> \
3226+ <sequence> \
3227+ <uuid value=\"0x1105\"/> \
3228+ </sequence> \
3229+ </attribute> \
3230+ \
3231+ <attribute id=\"0x0004\"> \
3232+ <sequence> \
3233+ <sequence> \
3234+ <uuid value=\"0x0100\"/> \
3235+ </sequence> \
3236+ <sequence> \
3237+ <uuid value=\"0x0003\"/> \
3238+ <uint8 value=\"%u\" name=\"channel\"/> \
3239+ </sequence> \
3240+ <sequence> \
3241+ <uuid value=\"0x0008\"/> \
3242+ </sequence> \
3243+ </sequence> \
3244+ </attribute> \
3245+ \
3246+ <attribute id=\"0x0009\"> \
3247+ <sequence> \
3248+ <sequence> \
3249+ <uuid value=\"0x1105\"/> \
3250+ <uint16 value=\"0x0100\" name=\"version\"/> \
3251+ </sequence> \
3252+ </sequence> \
3253+ </attribute> \
3254+ \
3255+ <attribute id=\"0x0100\"> \
3256+ <text value=\"%s\" name=\"name\"/> \
3257+ </attribute> \
3258+ \
3259+ <attribute id=\"0x0303\"> \
3260+ <sequence> \
3261+ <uint8 value=\"0x01\"/> \
3262+ <uint8 value=\"0x01\"/> \
3263+ <uint8 value=\"0x02\"/> \
3264+ <uint8 value=\"0x03\"/> \
3265+ <uint8 value=\"0x04\"/> \
3266+ <uint8 value=\"0x05\"/> \
3267+ <uint8 value=\"0x06\"/> \
3268+ <uint8 value=\"0xff\"/> \
3269+ </sequence> \
3270+ </attribute> \
3271 </record>"
3272
3273-static gpointer opp_connect(struct obex_session *os, int *err)
3274+static void *opp_connect(struct obex_session *os, int *err)
3275 {
3276 manager_register_transfer(os);
3277
3278@@ -103,17 +104,17 @@
3279 return NULL;
3280 }
3281
3282-static void opp_progress(struct obex_session *os, gpointer user_data)
3283+static void opp_progress(struct obex_session *os, void *user_data)
3284 {
3285 manager_emit_transfer_progress(os);
3286 }
3287
3288-static gint opp_chkput(struct obex_session *os, gpointer user_data)
3289+static int opp_chkput(struct obex_session *os, void *user_data)
3290 {
3291- gchar *folder, *name;
3292- gchar *path;
3293- gint32 time;
3294- gint ret;
3295+ char *folder, *name;
3296+ char *path;
3297+ int32_t time;
3298+ int ret;
3299
3300 if (obex_get_size(os) == OBJECT_SIZE_DELETE)
3301 return -EINVAL;
3302@@ -136,11 +137,17 @@
3303 name = g_strdup(obex_get_name(os));
3304
3305 skip_auth:
3306+ if (name == NULL || strlen(name) == 0)
3307+ return -EBADR;
3308+
3309+ if (g_strcmp0(name, obex_get_name(os)) != 0)
3310+ obex_set_name(os, name);
3311+
3312 path = g_build_filename(folder, name, NULL);
3313
3314 manager_emit_transfer_started(os);
3315
3316- ret = obex_prepare_put(os, path);
3317+ ret = obex_put_stream_start(os, path);
3318
3319 g_free(path);
3320 g_free(folder);
3321@@ -149,7 +156,7 @@
3322 return ret;
3323 }
3324
3325-static int opp_put(struct obex_session *os, gpointer user_data)
3326+static int opp_put(struct obex_session *os, void *user_data)
3327 {
3328 const char *name = obex_get_name(os);
3329 const char *folder = obex_get_root_folder(os);
3330@@ -164,7 +171,7 @@
3331 }
3332
3333 static int opp_get(struct obex_session *os, obex_object_t *obj,
3334- gpointer user_data)
3335+ gboolean *stream, void *user_data)
3336 {
3337 const char *type;
3338
3339@@ -177,26 +184,29 @@
3340 return -EPERM;
3341
3342 if (g_str_equal(type, VCARD_TYPE)) {
3343- if (obex_stream_start(os, VCARD_FILE, NULL) < 0)
3344+ if (obex_get_stream_start(os, VCARD_FILE) < 0)
3345 return -ENOENT;
3346
3347 } else
3348 return -EPERM;
3349
3350+ if (stream)
3351+ *stream = TRUE;
3352+
3353 return 0;
3354 }
3355
3356-static void opp_disconnect(struct obex_session *os, gpointer user_data)
3357+static void opp_disconnect(struct obex_session *os, void *user_data)
3358 {
3359 manager_unregister_transfer(os);
3360 }
3361
3362-static void opp_reset(struct obex_session *os, gpointer user_data)
3363+static void opp_reset(struct obex_session *os, void *user_data)
3364 {
3365 manager_emit_transfer_completed(os);
3366 }
3367
3368-struct obex_service_driver driver = {
3369+static struct obex_service_driver driver = {
3370 .name = "Object Push server",
3371 .service = OBEX_OPP,
3372 .channel = OPP_CHANNEL,
3373
3374=== modified file 'plugins/pbap.c'
3375--- plugins/pbap.c 2010-04-27 04:17:15 +0000
3376+++ plugins/pbap.c 2010-06-15 19:18:33 +0000
3377@@ -26,11 +26,13 @@
3378 #include <config.h>
3379 #endif
3380
3381+#include <stdio.h>
3382 #include <string.h>
3383 #include <errno.h>
3384 #include <glib.h>
3385 #include <stdlib.h>
3386 #include <unistd.h>
3387+#include <arpa/inet.h>
3388 #include <sys/types.h>
3389 #include <sys/stat.h>
3390 #include <fcntl.h>
3391@@ -71,87 +73,382 @@
3392 #define PHONEBOOKSIZE_LEN 2
3393 #define NEWMISSEDCALLS_LEN 1
3394
3395-#define MCH "telecom/mch.vcf"
3396-#define SIM1_MCH "SIM1/telecom/mch.vcf"
3397-
3398-#define DEFAULT_COUNT 65535
3399-
3400-#define APPARAM_HDR_SIZE 2
3401-
3402 #define PBAP_CHANNEL 15
3403
3404 #define PBAP_RECORD "<?xml version=\"1.0\" encoding=\"UTF-8\" ?> \
3405-<record> \
3406- <attribute id=\"0x0001\"> \
3407- <sequence> \
3408- <uuid value=\"0x112f\"/> \
3409- </sequence> \
3410- </attribute> \
3411- \
3412- <attribute id=\"0x0004\"> \
3413- <sequence> \
3414- <sequence> \
3415- <uuid value=\"0x0100\"/> \
3416- </sequence> \
3417- <sequence> \
3418- <uuid value=\"0x0003\"/> \
3419- <uint8 value=\"%u\" name=\"channel\"/> \
3420- </sequence> \
3421- <sequence> \
3422- <uuid value=\"0x0008\"/> \
3423- </sequence> \
3424- </sequence> \
3425- </attribute> \
3426- \
3427- <attribute id=\"0x0009\"> \
3428- <sequence> \
3429- <sequence> \
3430- <uuid value=\"0x1130\"/> \
3431- <uint16 value=\"0x0100\" name=\"version\"/> \
3432- </sequence> \
3433- </sequence> \
3434- </attribute> \
3435- \
3436- <attribute id=\"0x0100\"> \
3437- <text value=\"%s\" name=\"name\"/> \
3438- </attribute> \
3439- \
3440- <attribute id=\"0x0314\"> \
3441- <uint8 value=\"0x01\"/> \
3442- </attribute> \
3443+<record> \
3444+ <attribute id=\"0x0001\"> \
3445+ <sequence> \
3446+ <uuid value=\"0x112f\"/> \
3447+ </sequence> \
3448+ </attribute> \
3449+ \
3450+ <attribute id=\"0x0004\"> \
3451+ <sequence> \
3452+ <sequence> \
3453+ <uuid value=\"0x0100\"/> \
3454+ </sequence> \
3455+ <sequence> \
3456+ <uuid value=\"0x0003\"/> \
3457+ <uint8 value=\"%u\" name=\"channel\"/> \
3458+ </sequence> \
3459+ <sequence> \
3460+ <uuid value=\"0x0008\"/> \
3461+ </sequence> \
3462+ </sequence> \
3463+ </attribute> \
3464+ \
3465+ <attribute id=\"0x0009\"> \
3466+ <sequence> \
3467+ <sequence> \
3468+ <uuid value=\"0x1130\"/> \
3469+ <uint16 value=\"0x0100\" name=\"version\"/> \
3470+ </sequence> \
3471+ </sequence> \
3472+ </attribute> \
3473+ \
3474+ <attribute id=\"0x0100\"> \
3475+ <text value=\"%s\" name=\"name\"/> \
3476+ </attribute> \
3477+ \
3478+ <attribute id=\"0x0314\"> \
3479+ <uint8 value=\"0x01\"/> \
3480+ </attribute> \
3481 </record>"
3482
3483 struct aparam_header {
3484- uint8_t tag;
3485- uint8_t len;
3486- uint8_t val[0];
3487+ uint8_t tag;
3488+ uint8_t len;
3489+ uint8_t val[0];
3490 } __attribute__ ((packed));
3491
3492+struct cache {
3493+ gboolean valid;
3494+ uint32_t index;
3495+ char *folder;
3496+ GSList *entries;
3497+};
3498+
3499+struct cache_entry {
3500+ uint32_t handle;
3501+ char *id;
3502+ char *name;
3503+ char *sound;
3504+ char *tel;
3505+};
3506+
3507 struct pbap_session {
3508- struct obex_session *os;
3509 struct apparam_field *params;
3510- gchar *folder;
3511+ char *folder;
3512+ uint32_t find_handle;
3513 GString *buffer;
3514+ struct cache cache;
3515 };
3516
3517-static const guint8 PBAP_TARGET[TARGET_SIZE] = {
3518+static const uint8_t PBAP_TARGET[TARGET_SIZE] = {
3519 0x79, 0x61, 0x35, 0xF0, 0xF0, 0xC5, 0x11, 0xD8,
3520 0x09, 0x66, 0x08, 0x00, 0x20, 0x0C, 0x9A, 0x66 };
3521
3522-static void set_folder(struct pbap_session *pbap, const char *new_folder)
3523-{
3524- g_free(pbap->folder);
3525-
3526- pbap->folder = new_folder ? g_strdup(new_folder) : NULL;
3527-}
3528-
3529-static struct apparam_field *parse_aparam(const guint8 *buffer, guint32 hlen)
3530+typedef int (*cache_entry_find_f) (const struct cache_entry *entry,
3531+ const char *value);
3532+
3533+static void cache_entry_free(struct cache_entry *entry)
3534+{
3535+ g_free(entry->id);
3536+ g_free(entry->name);
3537+ g_free(entry->sound);
3538+ g_free(entry->tel);
3539+ g_free(entry);
3540+}
3541+
3542+static gboolean entry_name_find(const struct cache_entry *entry,
3543+ const char *value)
3544+{
3545+ char *name;
3546+ gboolean ret;
3547+
3548+ if (!entry->name)
3549+ return FALSE;
3550+
3551+ if (strlen(value) == 0)
3552+ return TRUE;
3553+
3554+ name = g_utf8_strdown(entry->name, -1);
3555+ ret = (g_strstr_len(name, -1, value) ? TRUE : FALSE);
3556+ g_free(name);
3557+
3558+ return ret;
3559+}
3560+
3561+static gboolean entry_sound_find(const struct cache_entry *entry,
3562+ const char *value)
3563+{
3564+ if (!entry->sound)
3565+ return FALSE;
3566+
3567+ return (g_strstr_len(entry->sound, -1, value) ? TRUE : FALSE);
3568+}
3569+
3570+static gboolean entry_tel_find(const struct cache_entry *entry,
3571+ const char *value)
3572+{
3573+ if (!entry->tel)
3574+ return FALSE;
3575+
3576+ return (g_strstr_len(entry->tel, -1, value) ? TRUE : FALSE);
3577+}
3578+
3579+static const char *cache_find(struct cache *cache, uint32_t handle)
3580+{
3581+ GSList *l;
3582+
3583+ for (l = cache->entries; l; l = l->next) {
3584+ struct cache_entry *entry = l->data;
3585+
3586+ if (entry->handle == handle)
3587+ return entry->id;
3588+ }
3589+
3590+ return NULL;
3591+}
3592+
3593+static void cache_clear(struct cache *cache)
3594+{
3595+ g_free(cache->folder);
3596+ g_slist_foreach(cache->entries, (GFunc) cache_entry_free, NULL);
3597+ g_slist_free(cache->entries);
3598+ cache->entries = NULL;
3599+}
3600+
3601+static void phonebook_size_result(const char *buffer, size_t bufsize,
3602+ int vcards, int missed, void *user_data)
3603+{
3604+ struct pbap_session *pbap = user_data;
3605+ char aparam[4];
3606+ struct aparam_header *hdr = (struct aparam_header *) aparam;
3607+ uint16_t phonebooksize;
3608+
3609+ DBG("vcards %d", vcards);
3610+
3611+ phonebooksize = htons(vcards);
3612+
3613+ hdr->tag = PHONEBOOKSIZE_TAG;
3614+ hdr->len = PHONEBOOKSIZE_LEN;
3615+ memcpy(hdr->val, &phonebooksize, sizeof(phonebooksize));
3616+
3617+ pbap->buffer = g_string_new_len(aparam, sizeof(aparam));
3618+
3619+ obex_object_set_io_flags(pbap, G_IO_IN, 0);
3620+}
3621+
3622+static void query_result(const char *buffer, size_t bufsize, int vcards,
3623+ int missed, void *user_data)
3624+{
3625+ struct pbap_session *pbap = user_data;
3626+
3627+ DBG("");
3628+
3629+ if (!pbap->buffer)
3630+ pbap->buffer = g_string_new_len(buffer, bufsize);
3631+ else
3632+ pbap->buffer = g_string_append_len(pbap->buffer, buffer,
3633+ bufsize);
3634+
3635+ obex_object_set_io_flags(pbap, G_IO_IN, 0);
3636+}
3637+
3638+static void cache_entry_notify(const char *id, uint32_t handle,
3639+ const char *name, const char *sound,
3640+ const char *tel, void *user_data)
3641+{
3642+ struct pbap_session *pbap = user_data;
3643+ struct cache_entry *entry = g_new0(struct cache_entry, 1);
3644+ struct cache *cache = &pbap->cache;
3645+
3646+ if (handle != PHONEBOOK_INVALID_HANDLE)
3647+ entry->handle = handle;
3648+ else
3649+ entry->handle = ++pbap->cache.index;
3650+
3651+ entry->id = g_strdup(id);
3652+ entry->name = g_strdup(name);
3653+ entry->sound = g_strdup(sound);
3654+ entry->tel = g_strdup(tel);
3655+
3656+ cache->entries = g_slist_append(cache->entries, entry);
3657+}
3658+
3659+static int alpha_sort(gconstpointer a, gconstpointer b)
3660+{
3661+ const struct cache_entry *e1 = a;
3662+ const struct cache_entry *e2 = b;
3663+
3664+ return g_strcmp0(e1->name, e2->name);
3665+}
3666+
3667+static int indexed_sort(gconstpointer a, gconstpointer b)
3668+{
3669+ const struct cache_entry *e1 = a;
3670+ const struct cache_entry *e2 = b;
3671+
3672+ return (e1->handle - e2->handle);
3673+}
3674+
3675+static int phonetical_sort(gconstpointer a, gconstpointer b)
3676+{
3677+ const struct cache_entry *e1 = a;
3678+ const struct cache_entry *e2 = b;
3679+
3680+ /* SOUND attribute is optional. Use Indexed sort if not present. */
3681+ if (!e1->sound || !e2->sound)
3682+ return indexed_sort(a, b);
3683+
3684+ return g_strcmp0(e1->sound, e2->sound);
3685+}
3686+
3687+static GSList *sort_entries(GSList *l, uint8_t order, uint8_t search_attrib,
3688+ const char *value)
3689+{
3690+ GSList *sorted = NULL;
3691+ cache_entry_find_f find;
3692+ GCompareFunc sort;
3693+ char *searchval;
3694+
3695+ /*
3696+ * Default sorter is "Indexed". Some backends doesn't inform the index,
3697+ * for this case a sequential internal index is assigned.
3698+ * 0x00 = indexed
3699+ * 0x01 = alphanumeric
3700+ * 0x02 = phonetic
3701+ */
3702+ switch (order) {
3703+ case 0x01:
3704+ sort = alpha_sort;
3705+ break;
3706+ case 0x02:
3707+ sort = phonetical_sort;
3708+ break;
3709+ default:
3710+ sort = indexed_sort;
3711+ break;
3712+ }
3713+
3714+ /*
3715+ * This implementation checks if the given field CONTAINS the
3716+ * search value(case insensitive). Name is the default field
3717+ * when the attribute is not provided.
3718+ */
3719+ switch (search_attrib) {
3720+ /* Number */
3721+ case 1:
3722+ find = entry_tel_find;
3723+ break;
3724+ /* Sound */
3725+ case 2:
3726+ find = entry_sound_find;
3727+ break;
3728+ default:
3729+ find = entry_name_find;
3730+ break;
3731+ }
3732+
3733+ searchval = value ? g_utf8_strdown(value, -1) : NULL;
3734+ for (; l; l = l->next) {
3735+ struct cache_entry *entry = l->data;
3736+
3737+ if (searchval && !find(entry, (const char *) searchval))
3738+ continue;
3739+
3740+ sorted = g_slist_insert_sorted(sorted, entry, sort);
3741+ }
3742+
3743+ g_free(searchval);
3744+
3745+ return sorted;
3746+}
3747+
3748+static void cache_ready_notify(void *user_data)
3749+{
3750+ struct pbap_session *pbap = user_data;
3751+ GSList *sorted;
3752+ GSList *l;
3753+ uint16_t max = pbap->params->maxlistcount;
3754+
3755+ DBG("");
3756+
3757+ if (max == 0) {
3758+ /* Ignore all other parameter and return PhoneBookSize */
3759+ char aparam[4];
3760+ struct aparam_header *hdr = (struct aparam_header *) aparam;
3761+ uint16_t size = htons(g_slist_length(pbap->cache.entries));
3762+
3763+ hdr->tag = PHONEBOOKSIZE_TAG;
3764+ hdr->len = PHONEBOOKSIZE_LEN;
3765+ memcpy(hdr->val, &size, sizeof(size));
3766+
3767+ pbap->buffer = g_string_new_len(aparam, sizeof(aparam));
3768+ goto done;
3769+ }
3770+ /*
3771+ * Don't free the sorted list content: this list contains
3772+ * only the reference for the "real" cache entry.
3773+ */
3774+ sorted = sort_entries(pbap->cache.entries, pbap->params->order,
3775+ pbap->params->searchattrib,
3776+ (const char *) pbap->params->searchval);
3777+
3778+ /* Computing offset considering first entry of the phonebook */
3779+ l = g_slist_nth(sorted, pbap->params->liststartoffset);
3780+
3781+ pbap->buffer = g_string_new(VCARD_LISTING_BEGIN);
3782+ for (; l && max; l = l->next, max--) {
3783+ const struct cache_entry *entry = l->data;
3784+
3785+ g_string_append_printf(pbap->buffer, VCARD_LISTING_ELEMENT,
3786+ entry->handle, entry->name);
3787+ }
3788+
3789+ pbap->buffer = g_string_append(pbap->buffer, VCARD_LISTING_END);
3790+
3791+ g_slist_free(sorted);
3792+
3793+done:
3794+ if (!pbap->cache.valid) {
3795+ pbap->cache.valid = TRUE;
3796+ obex_object_set_io_flags(pbap, G_IO_IN, 0);
3797+ }
3798+}
3799+
3800+static void cache_entry_done(void *user_data)
3801+{
3802+ struct pbap_session *pbap = user_data;
3803+ const char *id;
3804+ int ret;
3805+
3806+ DBG("");
3807+
3808+ pbap->cache.valid = TRUE;
3809+
3810+ id = cache_find(&pbap->cache, pbap->find_handle);
3811+ if (id == NULL) {
3812+ debug("Entry %d not found on cache", pbap->find_handle);
3813+ obex_object_set_io_flags(pbap, G_IO_ERR, -ENOENT);
3814+ return;
3815+ }
3816+
3817+ ret = phonebook_get_entry(pbap->folder, id, pbap->params,
3818+ query_result, pbap);
3819+ if (ret < 0)
3820+ obex_object_set_io_flags(pbap, G_IO_ERR, ret);
3821+}
3822+
3823+static struct apparam_field *parse_aparam(const uint8_t *buffer, uint32_t hlen)
3824 {
3825 struct apparam_field *param;
3826 struct aparam_header *hdr;
3827- guint32 len = 0;
3828- guint16 val16;
3829- guint64 val64;
3830+ uint64_t val64;
3831+ uint32_t len = 0;
3832+ uint16_t val16;
3833
3834 param = g_new0(struct apparam_field, 1);
3835
3836@@ -173,6 +470,9 @@
3837 param->searchattrib = hdr->val[0];
3838 break;
3839 case SEARCHVALUE_TAG:
3840+ if (hdr->len == 0)
3841+ goto failed;
3842+
3843 param->searchval = g_try_malloc0(hdr->len + 1);
3844 if (param->searchval)
3845 memcpy(param->searchval, hdr->val, hdr->len);
3846@@ -212,6 +512,11 @@
3847 len += hdr->len + sizeof(struct aparam_header);
3848 }
3849
3850+ DBG("o %x sa %x sv %s fil %" G_GINT64_MODIFIER "x for %x max %x off %x",
3851+ param->order, param->searchattrib, param->searchval,
3852+ param->filter, param->format, param->maxlistcount,
3853+ param->liststartoffset);
3854+
3855 return param;
3856
3857 failed:
3858@@ -220,7 +525,7 @@
3859 return NULL;
3860 }
3861
3862-static gpointer pbap_connect(struct obex_session *os, int *err)
3863+static void *pbap_connect(struct obex_session *os, int *err)
3864 {
3865 struct pbap_session *pbap;
3866
3867@@ -228,7 +533,7 @@
3868
3869 pbap = g_new0(struct pbap_session, 1);
3870 pbap->folder = g_strdup("/");
3871- pbap->os = os;
3872+ pbap->find_handle = PHONEBOOK_INVALID_HANDLE;
3873
3874 if (err)
3875 *err = 0;
3876@@ -237,24 +542,42 @@
3877 }
3878
3879 static int pbap_get(struct obex_session *os, obex_object_t *obj,
3880- gpointer user_data)
3881+ gboolean *stream, void *user_data)
3882 {
3883 struct pbap_session *pbap = user_data;
3884- const gchar *type = obex_get_type(os);
3885- const gchar *name = obex_get_name(os);
3886+ const char *type = obex_get_type(os);
3887+ const char *name = obex_get_name(os);
3888 struct apparam_field *params;
3889- const guint8 *buffer;
3890- gchar *path;
3891+ const uint8_t *buffer;
3892+ char *path;
3893 ssize_t rsize;
3894- gint ret;
3895+ int ret;
3896+
3897+ DBG("name %s type %s pbap %p", name, type, pbap);
3898
3899 if (type == NULL)
3900 return -EBADR;
3901
3902- if (strcmp(type, PHONEBOOK_TYPE) == 0)
3903+ rsize = obex_aparam_read(os, obj, &buffer);
3904+ if (rsize < 0)
3905+ return -EBADR;
3906+
3907+ params = parse_aparam(buffer, rsize);
3908+ if (params == NULL)
3909+ return -EBADR;
3910+
3911+ if (pbap->params) {
3912+ g_free(pbap->params->searchval);
3913+ g_free(pbap->params);
3914+ }
3915+
3916+ pbap->params = params;
3917+
3918+ if (strcmp(type, PHONEBOOK_TYPE) == 0) {
3919 /* Always contains the absolute path */
3920 path = g_strdup(name);
3921- else if (strcmp(type, VCARDLISTING_TYPE) == 0)
3922+ *stream = (params->maxlistcount == 0 ? FALSE : TRUE);
3923+ } else if (strcmp(type, VCARDLISTING_TYPE) == 0) {
3924 /* Always relative */
3925 if (!name || strlen(name) == 0)
3926 /* Current folder */
3927@@ -263,47 +586,30 @@
3928 /* Current folder + relative path */
3929 path = g_build_filename(pbap->folder, name, NULL);
3930
3931- else if (strcmp(type, VCARDENTRY_TYPE) == 0)
3932- /* Always relative */
3933- path = g_build_filename(pbap->folder, name, NULL);
3934- else
3935+ *stream = (params->maxlistcount == 0 ? FALSE : TRUE);
3936+ } else if (strcmp(type, VCARDENTRY_TYPE) == 0) {
3937+ /* File name only */
3938+ path = g_strdup(name);
3939+ *stream = TRUE;
3940+ } else
3941 return -EBADR;
3942
3943- rsize = obex_aparam_read(os, obj, &buffer);
3944- if (rsize < 0) {
3945- ret = -EBADR;
3946- goto failed;
3947- }
3948-
3949- params = parse_aparam(buffer, rsize);
3950- if (params == NULL) {
3951- ret = -EBADR;
3952- goto failed;
3953- }
3954-
3955- if (pbap->params) {
3956- g_free(pbap->params->searchval);
3957- g_free(pbap->params);
3958- }
3959-
3960 pbap->params = params;
3961- ret = obex_stream_start(os, path, pbap);
3962+ ret = obex_get_stream_start(os, path);
3963
3964-failed:
3965 g_free(path);
3966
3967 return ret;
3968 }
3969
3970-
3971 static int pbap_setpath(struct obex_session *os, obex_object_t *obj,
3972- gpointer user_data)
3973+ void *user_data)
3974 {
3975 struct pbap_session *pbap = user_data;
3976- const gchar *name;
3977- guint8 *nonhdr;
3978- gchar *fullname;
3979- int ret;
3980+ const char *name;
3981+ uint8_t *nonhdr;
3982+ char *fullname;
3983+ int err;
3984
3985 if (OBEX_ObjectGetNonHdrData(obj, &nonhdr) != 2) {
3986 error("Set path failed: flag and constants not found!");
3987@@ -312,24 +618,27 @@
3988
3989 name = obex_get_name(os);
3990
3991- ret = phonebook_set_folder(pbap->folder, name, nonhdr[0]);
3992- if (ret < 0)
3993- return ret;
3994-
3995- if (!pbap->folder)
3996- fullname = g_strdup(name);
3997- else
3998- fullname = g_build_filename(pbap->folder, name, NULL);
3999-
4000- set_folder(pbap, fullname);
4001-
4002- g_free(fullname);
4003+ DBG("name %s folder %s nonhdr 0x%x%x", name, pbap->folder,
4004+ nonhdr[0], nonhdr[1]);
4005+
4006+ fullname = phonebook_set_folder(pbap->folder, name, nonhdr[0], &err);
4007+ if (err < 0)
4008+ return err;
4009+
4010+ g_free(pbap->folder);
4011+ pbap->folder = fullname;
4012+
4013+ /*
4014+ * FIXME: Define a criteria to mark the cache as invalid
4015+ */
4016+ pbap->cache.valid = FALSE;
4017+ pbap->cache.index = 0;
4018+ cache_clear(&pbap->cache);
4019
4020 return 0;
4021 }
4022
4023-static void pbap_disconnect(struct obex_session *os,
4024- gpointer user_data)
4025+static void pbap_disconnect(struct obex_session *os, void *user_data)
4026 {
4027 struct pbap_session *pbap = user_data;
4028
4029@@ -340,18 +649,18 @@
4030 g_free(pbap->params);
4031 }
4032
4033+ cache_clear(&pbap->cache);
4034 g_free(pbap->folder);
4035 g_free(pbap);
4036 }
4037
4038-static gint pbap_chkput(struct obex_session *os,
4039- gpointer user_data)
4040+static int pbap_chkput(struct obex_session *os, void *user_data)
4041 {
4042 /* Rejects all PUTs */
4043- return -EINVAL;
4044+ return -EBADR;
4045 }
4046
4047-struct obex_service_driver pbap = {
4048+static struct obex_service_driver pbap = {
4049 .name = "Phonebook Access server",
4050 .service = OBEX_PBAP,
4051 .channel = PBAP_CHANNEL,
4052@@ -365,57 +674,189 @@
4053 .chkput = pbap_chkput
4054 };
4055
4056-static void query_result(const gchar *buffer, size_t bufsize,
4057- gint vcards, gint missed, gpointer user_data)
4058-{
4059- struct pbap_session *pbap = user_data;
4060-
4061- if (!pbap->buffer)
4062- pbap->buffer = g_string_new_len(buffer, bufsize);
4063- else
4064- pbap->buffer = g_string_append_len(pbap->buffer, buffer, bufsize);
4065-
4066- obex_object_set_io_flags(pbap, G_IO_IN, 0);
4067-}
4068-
4069-static gpointer vobject_open(const char *name, int oflag, mode_t mode,
4070- gpointer context, size_t *size, int *err)
4071-{
4072- struct pbap_session *pbap = context;
4073- int ret;
4074-
4075- if (oflag != O_RDONLY) {
4076- ret = -EPERM;
4077- goto fail;
4078- }
4079-
4080- ret = phonebook_pull(name, pbap->params, query_result, pbap);
4081- if (ret < 0)
4082- goto fail;
4083-
4084- if (size)
4085- *size = OBJECT_SIZE_UNKNOWN;
4086-
4087- return pbap;
4088-
4089-fail:
4090- if (err)
4091- *err = ret;
4092-
4093- return NULL;
4094-}
4095-
4096-static ssize_t vobject_read(gpointer object, void *buf, size_t count)
4097-{
4098- struct pbap_session *pbap = object;
4099-
4100- if (pbap->buffer)
4101- return string_read(pbap->buffer, buf, count);
4102-
4103- return -EAGAIN;
4104-}
4105-
4106-static int vobject_close(gpointer object)
4107+static void *vobject_pull_open(const char *name, int oflag, mode_t mode,
4108+ void *context, size_t *size, int *err)
4109+{
4110+ struct pbap_session *pbap = context;
4111+ phonebook_cb cb;
4112+ int ret;
4113+
4114+ DBG("name %s context %p maxlistcount %d", name, context,
4115+ pbap->params->maxlistcount);
4116+
4117+ if (oflag != O_RDONLY) {
4118+ ret = -EPERM;
4119+ goto fail;
4120+ }
4121+
4122+ if (pbap->params->maxlistcount == 0)
4123+ cb = phonebook_size_result;
4124+ else
4125+ cb = query_result;
4126+
4127+ ret = phonebook_pull(name, pbap->params, cb, pbap);
4128+ if (ret < 0)
4129+ goto fail;
4130+
4131+ if (size)
4132+ *size = OBJECT_SIZE_UNKNOWN;
4133+
4134+ return pbap;
4135+
4136+fail:
4137+ if (err)
4138+ *err = ret;
4139+
4140+ return NULL;
4141+}
4142+
4143+static void *vobject_list_open(const char *name, int oflag, mode_t mode,
4144+ void *context, size_t *size, int *err)
4145+{
4146+ struct pbap_session *pbap = context;
4147+ int ret;
4148+
4149+ DBG("name %s context %p valid %d", name, context, pbap->cache.valid);
4150+
4151+ if (oflag != O_RDONLY) {
4152+ ret = -EPERM;
4153+ goto fail;
4154+ }
4155+
4156+ /* PullvCardListing always get the contacts from the cache */
4157+
4158+ if (pbap->cache.valid) {
4159+ cache_ready_notify(pbap);
4160+ goto done;
4161+ }
4162+
4163+ ret = phonebook_create_cache(name,
4164+ cache_entry_notify, cache_ready_notify, pbap);
4165+
4166+ if (ret < 0)
4167+ goto fail;
4168+
4169+done:
4170+ if (size)
4171+ *size = OBJECT_SIZE_UNKNOWN;
4172+
4173+ return pbap;
4174+
4175+fail:
4176+ if (err)
4177+ *err = ret;
4178+
4179+ return NULL;
4180+}
4181+
4182+static void *vobject_vcard_open(const char *name, int oflag, mode_t mode,
4183+ void *context, size_t *size, int *err)
4184+{
4185+ struct pbap_session *pbap = context;
4186+ const char *id;
4187+ uint32_t handle;
4188+ int ret;
4189+
4190+ DBG("name %s context %p valid %d", name, context, pbap->cache.valid);
4191+
4192+ if (oflag != O_RDONLY) {
4193+ ret = -EPERM;
4194+ goto fail;
4195+ }
4196+
4197+ if (sscanf(name, "%u.vcf", &handle) != 1) {
4198+ ret = -EBADR;
4199+ goto fail;
4200+ }
4201+
4202+ if (pbap->cache.valid == FALSE) {
4203+ pbap->find_handle = handle;
4204+ ret = phonebook_create_cache(pbap->folder, cache_entry_notify,
4205+ cache_entry_done, pbap);
4206+ goto done;
4207+ }
4208+
4209+ id = cache_find(&pbap->cache, handle);
4210+ if (!id) {
4211+ ret = -ENOENT;
4212+ goto fail;
4213+ }
4214+
4215+ ret = phonebook_get_entry(pbap->folder, id, pbap->params, query_result,
4216+ pbap);
4217+
4218+done:
4219+ if (ret < 0)
4220+ goto fail;
4221+
4222+ if (size)
4223+ *size = OBJECT_SIZE_UNKNOWN;
4224+
4225+ return pbap;
4226+
4227+fail:
4228+ if (err)
4229+ *err = ret;
4230+
4231+ return NULL;
4232+}
4233+
4234+static ssize_t vobject_pull_read(void *object, void *buf, size_t count,
4235+ uint8_t *hi)
4236+{
4237+ struct pbap_session *pbap = object;
4238+
4239+ DBG("buffer %p maxlistcount %d", pbap->buffer,
4240+ pbap->params->maxlistcount);
4241+
4242+ if (!pbap->buffer)
4243+ return -EAGAIN;
4244+
4245+ /* PhoneBookSize */
4246+ if (pbap->params->maxlistcount == 0)
4247+ *hi = OBEX_HDR_APPARAM;
4248+ else
4249+ /* Stream data */
4250+ *hi = OBEX_HDR_BODY;
4251+
4252+ return string_read(pbap->buffer, buf, count);
4253+}
4254+
4255+static ssize_t vobject_list_read(void *object, void *buf, size_t count,
4256+ uint8_t *hi)
4257+{
4258+ struct pbap_session *pbap = object;
4259+
4260+ DBG("valid %d maxlistcount %d", pbap->cache.valid,
4261+ pbap->params->maxlistcount);
4262+
4263+ /* Backend still busy reading contacts */
4264+ if (!pbap->cache.valid)
4265+ return -EAGAIN;
4266+
4267+ if (pbap->params->maxlistcount == 0)
4268+ *hi = OBEX_HDR_APPARAM;
4269+ else
4270+ *hi = OBEX_HDR_BODY;
4271+
4272+ return string_read(pbap->buffer, buf, count);
4273+}
4274+
4275+static ssize_t vobject_vcard_read(void *object, void *buf, size_t count,
4276+ uint8_t *hi)
4277+{
4278+ struct pbap_session *pbap = object;
4279+
4280+ DBG("buffer %p", pbap->buffer);
4281+
4282+ if (!pbap->buffer)
4283+ return -EAGAIN;
4284+
4285+ *hi = OBEX_HDR_BODY;
4286+ return string_read(pbap->buffer, buf, count);
4287+}
4288+
4289+static int vobject_close(void *object)
4290 {
4291 struct pbap_session *pbap = object;
4292
4293@@ -427,28 +868,28 @@
4294 return 0;
4295 }
4296
4297-struct obex_mime_type_driver mime_pull = {
4298- .target = PBAP_TARGET,
4299- .mimetype = "x-bt/phonebook",
4300- .open = vobject_open,
4301- .close = vobject_close,
4302- .read = vobject_read,
4303-};
4304-
4305-struct obex_mime_type_driver mime_list = {
4306- .target = PBAP_TARGET,
4307- .mimetype = "x-bt/vcard-listing",
4308- .open = vobject_open,
4309- .close = vobject_close,
4310- .read = vobject_read,
4311-};
4312-
4313-struct obex_mime_type_driver mime_vcard = {
4314- .target = PBAP_TARGET,
4315- .mimetype = "x-bt/vcard",
4316- .open = vobject_open,
4317- .close = vobject_close,
4318- .read = vobject_read,
4319+static struct obex_mime_type_driver mime_pull = {
4320+ .target = PBAP_TARGET,
4321+ .mimetype = "x-bt/phonebook",
4322+ .open = vobject_pull_open,
4323+ .close = vobject_close,
4324+ .read = vobject_pull_read,
4325+};
4326+
4327+static struct obex_mime_type_driver mime_list = {
4328+ .target = PBAP_TARGET,
4329+ .mimetype = "x-bt/vcard-listing",
4330+ .open = vobject_list_open,
4331+ .close = vobject_close,
4332+ .read = vobject_list_read,
4333+};
4334+
4335+static struct obex_mime_type_driver mime_vcard = {
4336+ .target = PBAP_TARGET,
4337+ .mimetype = "x-bt/vcard",
4338+ .open = vobject_vcard_open,
4339+ .close = vobject_close,
4340+ .read = vobject_vcard_read,
4341 };
4342
4343 static int pbap_init(void)
4344
4345=== modified file 'plugins/phonebook-dummy.c'
4346--- plugins/phonebook-dummy.c 2010-04-27 04:17:15 +0000
4347+++ plugins/phonebook-dummy.c 2010-06-15 19:18:33 +0000
4348@@ -26,61 +26,513 @@
4349 #include <config.h>
4350 #endif
4351
4352+#include <dirent.h>
4353+#include <errno.h>
4354+#include <stdio.h>
4355+#include <stdint.h>
4356 #include <string.h>
4357 #include <glib.h>
4358+#include <stdlib.h>
4359+#include <sys/types.h>
4360+#include <sys/stat.h>
4361+#include <fcntl.h>
4362+#include <unistd.h>
4363+#include <libical/ical.h>
4364+#include <libical/vobject.h>
4365+#include <libical/vcc.h>
4366
4367 #include "logging.h"
4368 #include "phonebook.h"
4369
4370-#define VCARD0 \
4371- "BEGIN:VCARD\n" \
4372- "VERSION:3.0\n" \
4373- "N:Klaus;Santa\n" \
4374- "FN:\n" \
4375- "TEL:+001122334455\n" \
4376- "END:VCARD\n"
4377+typedef void (*vcard_func_t) (const char *file, VObject *vo, void *user_data);
4378
4379 struct dummy_data {
4380- phonebook_cb cb;
4381- gpointer user_data;
4382+ phonebook_cb cb;
4383+ void *user_data;
4384 const struct apparam_field *apparams;
4385-};
4386+ char *folder;
4387+ int fd;
4388+};
4389+
4390+struct cache_query {
4391+ phonebook_entry_cb entry_cb;
4392+ phonebook_cache_ready_cb ready_cb;
4393+ void *user_data;
4394+ DIR *dp;
4395+};
4396+
4397+static char *root_folder = NULL;
4398+
4399+static void dummy_free(void *user_data)
4400+{
4401+ struct dummy_data *dummy = user_data;
4402+
4403+ if (dummy->fd >= 0)
4404+ close(dummy->fd);
4405+
4406+ g_free(dummy->folder);
4407+ g_free(dummy);
4408+}
4409+
4410+static void query_free(void *user_data)
4411+{
4412+ struct cache_query *query = user_data;
4413+
4414+ if (query->dp)
4415+ closedir(query->dp);
4416+
4417+ g_free(query);
4418+}
4419
4420 int phonebook_init(void)
4421 {
4422+ /* FIXME: It should NOT be hard-coded */
4423+ root_folder = g_build_filename(getenv("HOME"), "phonebook", NULL);
4424+
4425 return 0;
4426 }
4427
4428 void phonebook_exit(void)
4429 {
4430-}
4431-
4432-static gboolean dummy_result(gpointer data)
4433-{
4434- struct dummy_data *dummy = data;
4435-
4436- dummy->cb(VCARD0, strlen(VCARD0), 1, 0, dummy->user_data);
4437-
4438- return FALSE;
4439-}
4440-
4441-int phonebook_set_folder(const gchar *current_folder,
4442- const gchar *new_folder, guint8 flags)
4443-{
4444- return 0;
4445-}
4446-
4447-int phonebook_pull(const gchar *name, const struct apparam_field *params,
4448- phonebook_cb cb, gpointer user_data)
4449-{
4450- struct dummy_data *dummy;
4451-
4452- dummy = g_new0(struct dummy_data, 1);
4453- dummy->cb = cb;
4454- dummy->user_data = user_data;
4455- dummy->apparams = params;
4456-
4457- g_idle_add_full(G_PRIORITY_DEFAULT_IDLE,
4458- dummy_result, dummy, g_free);
4459+ g_free(root_folder);
4460+}
4461+
4462+static int handle_cmp(gconstpointer a, gconstpointer b)
4463+{
4464+ const char *f1 = a;
4465+ const char *f2 = b;
4466+ unsigned int i1, i2;
4467+
4468+ if (sscanf(f1, "%u.vcf", &i1) != 1)
4469+ return -1;
4470+
4471+ if (sscanf(f2, "%u.vcf", &i2) != 1)
4472+ return -1;
4473+
4474+ return (i1 - i2);
4475+}
4476+
4477+static int foreach_vcard(DIR *dp, vcard_func_t func, uint16_t offset,
4478+ uint16_t maxlistcount, void *user_data, uint16_t *count)
4479+{
4480+ struct dirent *ep;
4481+ GSList *sorted = NULL, *l;
4482+ VObject *v;
4483+ FILE *fp;
4484+ int err, fd, folderfd;
4485+ uint16_t n = 0;
4486+
4487+ folderfd = dirfd(dp);
4488+ if (folderfd < 0) {
4489+ err = errno;
4490+ error("dirfd(): %s(%d)", strerror(err), err);
4491+ return -err;
4492+ }
4493+
4494+ /*
4495+ * Sorting vcards by file name. versionsort is a GNU extension.
4496+ * The simple sorting function implemented on handle_cmp address
4497+ * vcards handle only(handle is always a number). This sort function
4498+ * doesn't address filename started by "0".
4499+ */
4500+ while ((ep = readdir(dp))) {
4501+ char *filename;
4502+
4503+ if (ep->d_name[0] == '.')
4504+ continue;
4505+
4506+ filename = g_filename_to_utf8(ep->d_name, -1, NULL, NULL, NULL);
4507+ if (filename == NULL) {
4508+ error("g_filename_to_utf8: invalid filename");
4509+ continue;
4510+ }
4511+
4512+ if (!g_str_has_suffix(filename, ".vcf")) {
4513+ g_free(filename);
4514+ continue;
4515+ }
4516+
4517+ sorted = g_slist_insert_sorted(sorted, filename, handle_cmp);
4518+ }
4519+
4520+ /*
4521+ * Filtering only the requested vCards attributes. Offset
4522+ * shall be based on the first entry of the phonebook.
4523+ */
4524+ for (l = g_slist_nth(sorted, offset);
4525+ l && n < maxlistcount; l = l->next) {
4526+ const char *filename = l->data;
4527+
4528+ fd = openat(folderfd, filename, O_RDONLY);
4529+ if (fd < 0) {
4530+ err = errno;
4531+ error("openat(%s): %s(%d)", filename, strerror(err), err);
4532+ continue;
4533+ }
4534+
4535+ fp = fdopen(fd, "r");
4536+ v = Parse_MIME_FromFile(fp);
4537+ if (v != NULL) {
4538+ func(filename, v, user_data);
4539+ deleteVObject(v);
4540+ n++;
4541+ }
4542+
4543+ close(fd);
4544+ }
4545+
4546+ g_slist_foreach(sorted, (GFunc) g_free, NULL);
4547+ g_slist_free(sorted);
4548+
4549+ if (count)
4550+ *count = n;
4551+
4552+ return 0;
4553+}
4554+
4555+static void entry_concat(const char *filename, VObject *v, void *user_data)
4556+{
4557+ GString *buffer = user_data;
4558+ char tmp[1024];
4559+ int len;
4560+
4561+ /*
4562+ * VObject API uses len for IN and OUT
4563+ * Written bytes is also returned in the len variable
4564+ */
4565+ len = sizeof(tmp);
4566+ memset(tmp, 0, len);
4567+
4568+ writeMemVObject(tmp, &len, v);
4569+
4570+ /* FIXME: only the requested fields must be added */
4571+ g_string_append_len(buffer, tmp, len);
4572+}
4573+
4574+static gboolean read_dir(void *user_data)
4575+{
4576+ struct dummy_data *dummy = user_data;
4577+ GString *buffer;
4578+ DIR *dp;
4579+ uint16_t count, max, offset;
4580+
4581+ buffer = g_string_new("");
4582+
4583+ dp = opendir(dummy->folder);
4584+ if (dp == NULL) {
4585+ int err = errno;
4586+ debug("opendir(): %s(%d)", strerror(err), err);
4587+ goto done;
4588+ }
4589+
4590+ /*
4591+ * For PullPhoneBook function, the decision of returning the size
4592+ * or contacts is made in the PBAP core. When MaxListCount is ZERO,
4593+ * PCE wants to know the size of a given folder, PSE shall ignore all
4594+ * other applicattion parameters that may be present in the request.
4595+ */
4596+ if (dummy->apparams->maxlistcount == 0) {
4597+ max = 0xffff;
4598+ offset = 0;
4599+ } else {
4600+ max = dummy->apparams->maxlistcount;
4601+ offset = dummy->apparams->liststartoffset;
4602+ }
4603+
4604+ foreach_vcard(dp, entry_concat, offset, max, buffer, &count);
4605+
4606+ closedir(dp);
4607+done:
4608+ /* FIXME: Missing vCards fields filtering */
4609+ dummy->cb(buffer->str, buffer->len, count, 0, dummy->user_data);
4610+
4611+ g_string_free(buffer, TRUE);
4612+
4613+ return FALSE;
4614+}
4615+
4616+static void entry_notify(const char *filename, VObject *v, void *user_data)
4617+{
4618+ struct cache_query *query = user_data;
4619+ VObject *property, *subproperty;
4620+ GString *name;
4621+ const char *tel;
4622+ long unsigned int handle;
4623+
4624+ property = isAPropertyOf(v, VCNameProp);
4625+ if (!property)
4626+ return;
4627+
4628+ if (sscanf(filename, "%lu.vcf", &handle) != 1)
4629+ return;
4630+
4631+ if (handle > UINT32_MAX)
4632+ return;
4633+
4634+ /* LastName; FirstName; MiddleName; Prefix; Suffix */
4635+
4636+ name = g_string_new("");
4637+ subproperty = isAPropertyOf(property, VCFamilyNameProp);
4638+ if (subproperty) {
4639+ g_string_append(name,
4640+ fakeCString(vObjectUStringZValue(subproperty)));
4641+ }
4642+
4643+ subproperty = isAPropertyOf(property, VCGivenNameProp);
4644+ if (subproperty)
4645+ g_string_append_printf(name, ";%s",
4646+ fakeCString(vObjectUStringZValue(subproperty)));
4647+
4648+ subproperty = isAPropertyOf(property, VCAdditionalNamesProp);
4649+ if (subproperty)
4650+ g_string_append_printf(name, ";%s",
4651+ fakeCString(vObjectUStringZValue(subproperty)));
4652+
4653+ subproperty = isAPropertyOf(property, VCNamePrefixesProp);
4654+ if (subproperty)
4655+ g_string_append_printf(name, ";%s",
4656+ fakeCString(vObjectUStringZValue(subproperty)));
4657+
4658+
4659+ subproperty = isAPropertyOf(property, VCNameSuffixesProp);
4660+ if (subproperty)
4661+ g_string_append_printf(name, ";%s",
4662+ fakeCString(vObjectUStringZValue(subproperty)));
4663+
4664+ property = isAPropertyOf(v, VCTelephoneProp);
4665+
4666+ tel = property ? fakeCString(vObjectUStringZValue(property)) : NULL;
4667+
4668+ query->entry_cb(filename, handle, name->str, NULL, tel,
4669+ query->user_data);
4670+ g_string_free(name, TRUE);
4671+}
4672+
4673+static gboolean create_cache(void *user_data)
4674+{
4675+ struct cache_query *query = user_data;
4676+
4677+ /*
4678+ * MaxListCount and ListStartOffset shall not be used
4679+ * when creating the cache. All entries shall be fetched.
4680+ * PBAP core is responsible for consider these application
4681+ * parameters before reply the entries.
4682+ */
4683+ foreach_vcard(query->dp, entry_notify, 0, 0xffff, query, NULL);
4684+
4685+ query->ready_cb(query->user_data);
4686+
4687+ return FALSE;
4688+}
4689+
4690+static gboolean read_entry(void *user_data)
4691+{
4692+ struct dummy_data *dummy = user_data;
4693+ char buffer[1024];
4694+ ssize_t count;
4695+
4696+ memset(buffer, 0, sizeof(buffer));
4697+ count = read(dummy->fd, buffer, sizeof(buffer));
4698+
4699+ if (count < 0) {
4700+ int err = errno;
4701+ error("read(): %s(%d)", strerror(err), err);
4702+ count = 0;
4703+ }
4704+
4705+ /* FIXME: Missing vCards fields filtering */
4706+
4707+ dummy->cb(buffer, count, 1, 0, dummy->user_data);
4708+
4709+ return FALSE;
4710+}
4711+
4712+static gboolean is_dir(const char *dir)
4713+{
4714+ struct stat st;
4715+
4716+ if (stat(dir, &st) < 0) {
4717+ int err = errno;
4718+ error("stat(%s): %s (%d)", dir, strerror(err), err);
4719+ return FALSE;
4720+ }
4721+
4722+ return S_ISDIR(st.st_mode);
4723+}
4724+
4725+char *phonebook_set_folder(const char *current_folder,
4726+ const char *new_folder, uint8_t flags, int *err)
4727+{
4728+ gboolean root, child;
4729+ char *tmp1, *tmp2, *base, *absolute, *relative = NULL;
4730+ int len, ret = 0;
4731+
4732+ root = (g_strcmp0("/", current_folder) == 0);
4733+ child = (new_folder && strlen(new_folder) != 0);
4734+
4735+ switch (flags) {
4736+ case 0x02:
4737+ /* Go back to root */
4738+ if (!child) {
4739+ relative = g_strdup("/");
4740+ goto done;
4741+ }
4742+
4743+ relative = g_build_filename(current_folder, new_folder, NULL);
4744+ break;
4745+ case 0x03:
4746+ /* Go up 1 level */
4747+ if (root) {
4748+ /* Already root */
4749+ ret = -EBADR;
4750+ goto done;
4751+ }
4752+
4753+ /*
4754+ * Removing one level of the current folder. Current folder
4755+ * contains AT LEAST one level since it is not at root folder.
4756+ * Use glib utility functions to handle invalid chars in the
4757+ * folder path properly.
4758+ */
4759+ tmp1 = g_path_get_basename(current_folder);
4760+ tmp2 = g_strrstr(current_folder, tmp1);
4761+ len = tmp2 - (current_folder + 1);
4762+
4763+ g_free(tmp1);
4764+
4765+ if (len == 0)
4766+ base = g_strdup("/");
4767+ else
4768+ base = g_strndup(current_folder, len);
4769+
4770+ /* Return: one level only */
4771+ if (!child) {
4772+ relative = base;
4773+ goto done;
4774+ }
4775+
4776+ relative = g_build_filename(base, new_folder, NULL);
4777+ g_free(base);
4778+
4779+ break;
4780+ default:
4781+ ret = -EBADR;
4782+ break;
4783+ }
4784+
4785+done:
4786+ if (!relative) {
4787+ if (err)
4788+ *err = ret;
4789+
4790+ return NULL;
4791+ }
4792+
4793+ absolute = g_build_filename(root_folder, relative, NULL);
4794+ if (!is_dir(absolute)) {
4795+ g_free(relative);
4796+ relative = NULL;
4797+ ret = -ENOENT;
4798+ }
4799+
4800+ g_free(absolute);
4801+
4802+ if (err)
4803+ *err = ret;
4804+
4805+ return relative;
4806+}
4807+
4808+int phonebook_pull(const char *name, const struct apparam_field *params,
4809+ phonebook_cb cb, void *user_data)
4810+{
4811+ struct dummy_data *dummy;
4812+ char *filename, *folder;
4813+
4814+ /*
4815+ * Main phonebook objects will be created dinamically based on the
4816+ * folder content. All vcards inside the given folder will be appended
4817+ * in the "virtual" main phonebook object.
4818+ */
4819+
4820+ filename = g_build_filename(root_folder, name, NULL);
4821+
4822+ if (!g_str_has_suffix(filename, ".vcf")) {
4823+ g_free(filename);
4824+ return -EBADR;
4825+ }
4826+
4827+ folder = g_strndup(filename, strlen(filename) - 4);
4828+ g_free(filename);
4829+ if (!is_dir(folder)) {
4830+ g_free(folder);
4831+ return -ENOENT;
4832+ }
4833+
4834+ dummy = g_new0(struct dummy_data, 1);
4835+ dummy->cb = cb;
4836+ dummy->user_data = user_data;
4837+ dummy->apparams = params;
4838+ dummy->folder = folder;
4839+ dummy->fd = -1;
4840+
4841+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, read_dir, dummy, dummy_free);
4842+
4843+ return 0;
4844+}
4845+
4846+int phonebook_get_entry(const char *folder, const char *id,
4847+ const struct apparam_field *params,
4848+ phonebook_cb cb, void *user_data)
4849+{
4850+ struct dummy_data *dummy;
4851+ char *filename;
4852+ int fd;
4853+
4854+ filename = g_build_filename(root_folder, folder, id, NULL);
4855+
4856+ fd = open(filename, O_RDONLY);
4857+ if (fd < 0) {
4858+ int err = errno;
4859+ debug("open(): %s(%d)", strerror(err), err);
4860+ return -ENOENT;
4861+ }
4862+
4863+ dummy = g_new0(struct dummy_data, 1);
4864+ dummy->cb = cb;
4865+ dummy->user_data = user_data;
4866+ dummy->apparams = params;
4867+ dummy->fd = fd;
4868+
4869+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, read_entry, dummy, dummy_free);
4870+
4871+ return 0;
4872+}
4873+
4874+int phonebook_create_cache(const char *name, phonebook_entry_cb entry_cb,
4875+ phonebook_cache_ready_cb ready_cb, void *user_data)
4876+{
4877+ struct cache_query *query;
4878+ char *foldername;
4879+ DIR *dp;
4880+
4881+ foldername = g_build_filename(root_folder, name, NULL);
4882+ dp = opendir(foldername);
4883+ g_free(foldername);
4884+
4885+ if (dp == NULL) {
4886+ int err = errno;
4887+ debug("opendir(): %s(%d)", strerror(err), err);
4888+ return -ENOENT;
4889+ }
4890+
4891+ query = g_new0(struct cache_query, 1);
4892+ query->entry_cb = entry_cb;
4893+ query->ready_cb = ready_cb;
4894+ query->user_data = user_data;
4895+ query->dp = dp;
4896+
4897+ g_idle_add_full(G_PRIORITY_DEFAULT_IDLE, create_cache, query,
4898+ query_free);
4899 return 0;
4900 }
4901
4902=== modified file 'plugins/phonebook-ebook.c'
4903--- plugins/phonebook-ebook.c 2010-04-27 04:17:15 +0000
4904+++ plugins/phonebook-ebook.c 2010-06-15 19:18:33 +0000
4905@@ -41,54 +41,250 @@
4906 #include "service.h"
4907 #include "phonebook.h"
4908
4909-#define EOL_CHARS "\n"
4910-#define VL_VERSION "<?xml version=\"1.0\"?>" EOL_CHARS
4911-#define VL_TYPE "<!DOCTYPE vcard-listing SYSTEM \"vcard-listing.dtd\">" EOL_CHARS
4912-#define VL_BODY_BEGIN "<vCard-listing version=\"1.0\">" EOL_CHARS
4913-#define VL_BODY_END "</vCard-listing>" EOL_CHARS
4914-#define VL_ELEMENT "<card handle = \"%d.vcf\" name = \"%s\"/>" EOL_CHARS
4915-
4916-#define QUERY_FAMILY_NAME "(contains \"family_name\" \"%s\")"
4917-#define QUERY_GIVEN_NAME "(contains \"given_name\" \"%s\")"
4918+#define QUERY_FN "(contains \"family_name\" \"%s\")"
4919+#define QUERY_NAME "(contains \"given_name\" \"%s\")"
4920 #define QUERY_PHONE "(contains \"phone\" \"%s\")"
4921
4922-struct query_data {
4923+struct contacts_query {
4924 const struct apparam_field *params;
4925 phonebook_cb cb;
4926- gpointer user_data;
4927+ void *user_data;
4928+};
4929+
4930+struct cache_query {
4931+ phonebook_entry_cb entry_cb;
4932+ phonebook_cache_ready_cb ready_cb;
4933+ void *user_data;
4934 };
4935
4936 static EBook *ebook = NULL;
4937
4938-static void ebookpull_cb(EBook *book, EBookStatus status, GList *contacts,
4939- gpointer user_data)
4940-{
4941- struct query_data *data = user_data;
4942+static char *attribute_mask[] = {
4943+/* 0 */ "VERSION",
4944+ "FN",
4945+ "N",
4946+ "PHOTO",
4947+ "BDAY",
4948+ "ADR",
4949+ "LABEL",
4950+ "TEL",
4951+/* 8 */ "EMAIL",
4952+ "MAILER",
4953+ "TZ",
4954+ "GEO",
4955+ "TITLE",
4956+ "ROLE",
4957+ "LOGO",
4958+ "AGENT",
4959+/* 16 */ "ORG",
4960+ "NOTE",
4961+ "REV",
4962+ "SOUND",
4963+ "URL",
4964+ "UID",
4965+ "KEY",
4966+ "NICKNAME",
4967+/* 24 */ "CATEGORIES",
4968+ "PROID",
4969+ "CLASS",
4970+ "SORT-STRING",
4971+/* 28 */ "X-IRMC-CALL-DATETIME",
4972+ NULL
4973+
4974+};
4975+
4976+static char *evcard_to_string(EVCard *evcard, unsigned int format,
4977+ uint64_t filter)
4978+{
4979+ EVCard *evcard2;
4980+ char *vcard;
4981+ unsigned int i;
4982+
4983+ if (!filter)
4984+ return e_vcard_to_string(evcard, format);
4985+
4986+ /*
4987+ * Mandatory attributes for vCard 2.1 are VERSION ,N and TEL.
4988+ * Mandatory attributes for vCard 3.0 are VERSION, N, FN and TEL
4989+ */
4990+ filter = format == EVC_FORMAT_VCARD_30 ? filter | 0x85: filter | 0x87;
4991+
4992+ evcard2 = e_vcard_new();
4993+ for (i = 0; i < 29; i++) {
4994+ EVCardAttribute *attrib;
4995+
4996+ if (!(filter & (1 << i)))
4997+ continue;
4998+
4999+ attrib = e_vcard_get_attribute(evcard, attribute_mask[i]);
5000+ if (!attrib)
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches