obexftp-0.24.2-Source/AUTHORS000644 001750 001750 00000000124 12115272461 016664 0ustar00hendrikhendrik000000 000000 Christian W. Zuckschwerdt Hendrik Sattler obexftp-0.24.2-Source/Doxyfile000644 001750 001750 00000023673 12115454223 017336 0ustar00hendrikhendrik000000 000000 # Doxyfile 1.4.7 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = ObexFTP PROJECT_NUMBER = 0.24 OUTPUT_DIRECTORY = doc/api CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO BUILTIN_STL_SUPPORT = NO DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = YES EXTRACT_PRIVATE = NO EXTRACT_STATIC = NO EXTRACT_LOCAL_CLASSES = NO EXTRACT_LOCAL_METHODS = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = NO FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = bfb/bfb.c bfb/bfb.h \ multicobex/multi_cobex.c multicobex/multi_cobex.h \ obexftp/cache.c obexftp/client.c obexftp/client.h \ obexftp/obexftp.h obexftp/uuid.h \ Doxyfile.coverpage FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py \ *.C \ *.CC \ *.C++ \ *.II \ *.I++ \ *.H \ *.HH \ *.H++ \ *.CS \ *.PHP \ *.PHP3 \ *.M \ *.MM \ *.PY RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = *_private.h EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES USE_HTAGS = NO VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = NO LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = YES MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO obexftp-0.24.2-Source/Doxyfile.coverpage000644 001750 001750 00000007556 11351376660 021323 0ustar00hendrikhendrik000000 000000 /** \mainpage \section intro_sec Introduction ObexFTP implements the Object Exchange (OBEX) file transfer feature for clients and servers. The standard is defined in more detail in section K12.5 (Profiles: OBEX FTP) in Bluetooth V1.1 Profile Specifications. ObexFTP works out-of-the-box with all transports supported by OpenOBEX. Currently there is IrDA, Bluetooth, USB and network (TCP) transport support. ObexFTP also comes with ready to use custom transport support for many mobile phones serial cables. It's well tested with Siemens and Sony/Ericsson mobile phones. But then most Motorola and Sharp (generic) as well as Samsung phones will work too, please contact the author if not. This ObexFTP distribution contains libraries as well as some applications. Applications to access e.g. Flex. Memory and Multimedia- /Secure Digital Card memory on mobile equipment: - obexftp - all in one client application (heavy on options) - Symlinks to obexftp for default operations: - obexls - list the mobiles contents - obexget - copy files(s) to mobile - obexput - copy files(s) from mobile - obexrm - remove files on the mobile - obexftpd - obex ftp server application (experimental) Applications to hack Siemens mobile equipment using datalink cable - bfb_keysim - simulate key presses on the mobile - bfb_eeprom - list and examine the user eeprom on the mobile Library parts to be used in other applications - obexftp - high level abstraction of OBEX FTP (SYNC, PUSH also) protocol - multicobex - cable OBEX support for many phones (i.e. Siemens BFB and BFC Sony/Ericsson, Motorola and generic (Sharp) modes) - bfb - Siemens mobile datalink cable protocol layer \section install_sec Short Installation Instructions To compile and install: \verbatim # ./configure # make # make install (as superuser) \endverbatim If you plan to use a Siemens x45 or x55 series (e.g. S45 or C55, not S65) use \verbatim CFLAGS="$CFLAGS -DCOMPAT_S45" ./configure \endverbatim instead Consider using pedantic error checking: \verbatim CFLAGS="$CFLAGS -Werror" ./configure \endverbatim If compiling doesn't work, try to disable some of the language bindings on configure. \verbatim --disable-perl --disable-python --disable-ruby --disable-tcl \endverbatim \section development_sec Further Development If this tool lacks support for your phone or just won't work quite right please let me know. Development will focus on your needs. This package lacks advanced examples using the bindings. There are some 3rd party GUIs and other projects like a obex file system though. Please see the OpenOBEX / ObexFTP web site for details. Developers are free to use the bindings as well as obexftp, multicobex and bfb libraries. Please join the mailing list and keep in touch - You'll recieve pre-releases and support. That way your application can benefit from the newest library features and further development can focus on your needs. \section debugging_sec Debugging remove all ObexFTP installations from your system. Build using \verbatim CFLAGS="-DOBEXFTP_DEBUG=5" ./configure make clean ; make \endverbatim Start debugging using \verbatim ./apps/obexftp [...] \endverbatim You might want to try picking up compiler warnings too (and mail them to me) \verbatim CFLAGS="$CFLAGS -g -Wall -Wmissing-declarations -Wmissing-prototypes \ -Werror" ./configure make clean ; make \endverbatim Please mail me all warnings and errors, if any. The bindings use language-native installers which are missing the uninstall targets. Our distcheck will boldly ignore those files. \section contact_sec Author and Contact Author: Christian W. Zuckschwerdt - http://dev.zuckschwerdt.org/openobex/ - http://openobex.sourceforge.net/ - http://sourceforge.net/tracker/?group_id=8960 - http://sourceforge.net/forum/?group_id=8960 */ obexftp-0.24.2-Source/Doxyfile.developer000644 001750 001750 00000023461 11351376660 021326 0ustar00hendrikhendrik000000 000000 # Doxyfile 1.4.7 #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = ObexFTP PROJECT_NUMBER = 0.22 OUTPUT_DIRECTORY = doc/handbook CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English BRIEF_MEMBER_DESC = YES REPEAT_BRIEF = YES ABBREVIATE_BRIEF = "The $name class" \ "The $name widget" \ "The $name file" \ is \ provides \ specifies \ contains \ represents \ a \ an \ the ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO FULL_PATH_NAMES = YES STRIP_FROM_PATH = STRIP_FROM_INC_PATH = SHORT_NAMES = NO JAVADOC_AUTOBRIEF = YES MULTILINE_CPP_IS_BRIEF = NO DETAILS_AT_TOP = NO INHERIT_DOCS = YES SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 ALIASES = OPTIMIZE_OUTPUT_FOR_C = YES OPTIMIZE_OUTPUT_JAVA = NO BUILTIN_STL_SUPPORT = NO DISTRIBUTE_GROUP_DOC = NO SUBGROUPING = YES #--------------------------------------------------------------------------- # Build related configuration options #--------------------------------------------------------------------------- EXTRACT_ALL = YES EXTRACT_PRIVATE = YES EXTRACT_STATIC = YES EXTRACT_LOCAL_CLASSES = YES EXTRACT_LOCAL_METHODS = NO HIDE_UNDOC_MEMBERS = NO HIDE_UNDOC_CLASSES = NO HIDE_FRIEND_COMPOUNDS = NO HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO CASE_SENSE_NAMES = YES HIDE_SCOPE_NAMES = NO SHOW_INCLUDE_FILES = YES INLINE_INFO = YES SORT_MEMBER_DOCS = YES SORT_BRIEF_DOCS = NO SORT_BY_SCOPE_NAME = NO GENERATE_TODOLIST = YES GENERATE_TESTLIST = YES GENERATE_BUGLIST = YES GENERATE_DEPRECATEDLIST= YES ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 SHOW_USED_FILES = YES SHOW_DIRECTORIES = NO FILE_VERSION_FILTER = #--------------------------------------------------------------------------- # configuration options related to warning and progress messages #--------------------------------------------------------------------------- QUIET = NO WARNINGS = YES WARN_IF_UNDOCUMENTED = YES WARN_IF_DOC_ERROR = YES WARN_NO_PARAMDOC = NO WARN_FORMAT = "$file:$line: $text" WARN_LOGFILE = #--------------------------------------------------------------------------- # configuration options related to the input files #--------------------------------------------------------------------------- INPUT = bfb multicobex obexftp includes Doxyfile.coverpage FILE_PATTERNS = *.c \ *.cc \ *.cxx \ *.cpp \ *.c++ \ *.d \ *.java \ *.ii \ *.ixx \ *.ipp \ *.i++ \ *.inl \ *.h \ *.hh \ *.hxx \ *.hpp \ *.h++ \ *.idl \ *.odl \ *.cs \ *.php \ *.php3 \ *.inc \ *.m \ *.mm \ *.dox \ *.py \ *.C \ *.CC \ *.C++ \ *.II \ *.I++ \ *.H \ *.HH \ *.H++ \ *.CS \ *.PHP \ *.PHP3 \ *.M \ *.MM \ *.PY RECURSIVE = NO EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = *_private.h EXAMPLE_PATH = EXAMPLE_PATTERNS = * EXAMPLE_RECURSIVE = NO IMAGE_PATH = INPUT_FILTER = FILTER_PATTERNS = FILTER_SOURCE_FILES = NO #--------------------------------------------------------------------------- # configuration options related to source browsing #--------------------------------------------------------------------------- SOURCE_BROWSER = NO INLINE_SOURCES = NO STRIP_CODE_COMMENTS = YES REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO REFERENCES_LINK_SOURCE = YES USE_HTAGS = NO VERBATIM_HEADERS = NO #--------------------------------------------------------------------------- # configuration options related to the alphabetical class index #--------------------------------------------------------------------------- ALPHABETICAL_INDEX = NO COLS_IN_ALPHA_INDEX = 5 IGNORE_PREFIX = #--------------------------------------------------------------------------- # configuration options related to the HTML output #--------------------------------------------------------------------------- GENERATE_HTML = YES HTML_OUTPUT = html HTML_FILE_EXTENSION = .html HTML_HEADER = HTML_FOOTER = HTML_STYLESHEET = HTML_ALIGN_MEMBERS = YES GENERATE_HTMLHELP = NO CHM_FILE = HHC_LOCATION = GENERATE_CHI = NO BINARY_TOC = NO TOC_EXPAND = NO DISABLE_INDEX = NO ENUM_VALUES_PER_LINE = 4 GENERATE_TREEVIEW = NO TREEVIEW_WIDTH = 250 #--------------------------------------------------------------------------- # configuration options related to the LaTeX output #--------------------------------------------------------------------------- GENERATE_LATEX = NO LATEX_OUTPUT = latex LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex COMPACT_LATEX = NO PAPER_TYPE = a4wide EXTRA_PACKAGES = LATEX_HEADER = PDF_HYPERLINKS = NO USE_PDFLATEX = NO LATEX_BATCHMODE = NO LATEX_HIDE_INDICES = NO #--------------------------------------------------------------------------- # configuration options related to the RTF output #--------------------------------------------------------------------------- GENERATE_RTF = NO RTF_OUTPUT = rtf COMPACT_RTF = NO RTF_HYPERLINKS = NO RTF_STYLESHEET_FILE = RTF_EXTENSIONS_FILE = #--------------------------------------------------------------------------- # configuration options related to the man page output #--------------------------------------------------------------------------- GENERATE_MAN = NO MAN_OUTPUT = man MAN_EXTENSION = .3 MAN_LINKS = NO #--------------------------------------------------------------------------- # configuration options related to the XML output #--------------------------------------------------------------------------- GENERATE_XML = NO XML_OUTPUT = xml XML_SCHEMA = XML_DTD = XML_PROGRAMLISTING = YES #--------------------------------------------------------------------------- # configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- GENERATE_AUTOGEN_DEF = NO #--------------------------------------------------------------------------- # configuration options related to the Perl module output #--------------------------------------------------------------------------- GENERATE_PERLMOD = NO PERLMOD_LATEX = NO PERLMOD_PRETTY = YES PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- ENABLE_PREPROCESSING = YES MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = PREDEFINED = EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- # Configuration::additions related to external references #--------------------------------------------------------------------------- TAGFILES = GENERATE_TAGFILE = ALLEXTERNALS = NO EXTERNAL_GROUPS = YES PERL_PATH = /usr/bin/perl #--------------------------------------------------------------------------- # Configuration options related to the dot tool #--------------------------------------------------------------------------- CLASS_DIAGRAMS = YES HIDE_UNDOC_RELATIONS = YES HAVE_DOT = NO CLASS_GRAPH = YES COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES UML_LOOK = NO TEMPLATE_RELATIONS = NO INCLUDE_GRAPH = YES INCLUDED_BY_GRAPH = YES CALL_GRAPH = NO CALLER_GRAPH = NO GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES DOT_IMAGE_FORMAT = png DOT_PATH = DOTFILE_DIRS = DOT_TRANSPARENT = NO DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES DOT_CLEANUP = YES #--------------------------------------------------------------------------- # Configuration::additions related to the search engine #--------------------------------------------------------------------------- SEARCHENGINE = NO obexftp-0.24.2-Source/NEWS000644 001750 001750 00000001347 11351376660 016332 0ustar00hendrikhendrik000000 000000 ObexFTP recent NEWS =================== * proper unicode support * support for transparent OBEX-over-AT mode * working win32 support (again) * full Series 60 support * Newer Siemens phones (BFC support) * Sharp support (PCSOFTWARE uuid) * added motorola support * 3GPP 27.007 cable support (CPROT=0) * 64-bit clean * obexftpd daemon application * Motorola support, tested with models v710/e815 * be sure to give ObexFS a spin! * object caching and directory parsing (for things like ObexFS) * Nokia support via IrDA and Bluetooth * Siemens S65 support * Everything but data goes to stderr for more simple redirection. * VMO converter (gsm and wav) split into seperate package. * Ericsson and Siemens cable support unified (still testing). obexftp-0.24.2-Source/README000644 001750 001750 00000006177 12115276447 016522 0ustar00hendrikhendrik000000 000000 ObexFTP Readme ============== Introduction ------------ ObexFTP implements the Object Exchange (OBEX) file transfer feature for clients and servers. The standard is defined in more detail in section K12.5 (Profiles: OBEX FTP) in Bluetooth V1.1 Profile Specifications. ObexFTP works out-of-the-box with all transports supported by OpenOBEX. Currently there is IrDA, Bluetooth, USB and network (TCP) transport support. ObexFTP also comes with ready to use custom transport support for many mobile phones serial cables. It's well tested with Siemens and Sony/Ericsson mobile phones. But then most Motorola and Sharp (generic) as well as Samsung phones will work too, please contact the author if not. This ObexFTP distribution contains libraries as well as some applications. Applications to access e.g. Flex. Memory and Multimedia- /Secure Digital Card memory on mobile equipment: - obexftp - all in one client application (heavy on options) - Symlinks to obexftp for default operations: - obexls - list the mobiles contents - obexget - copy files(s) to mobile - obexput - copy files(s) from mobile - obexrm - remove files on the mobile - obexftpd - obex ftp server application (experimental) Applications to hack Siemens mobile equipment using datalink cable - bfb_keysim - simulate key presses on the mobile - bfb_eeprom - list and examine the user eeprom on the mobile Library parts to be used in other applications - obexftp - high level abstraction of OBEX FTP (SYNC, PUSH also) protocol - multicobex - cable OBEX support for many phones (i.e. Siemens BFB and BFC Sony/Ericsson, Motorola and generic (Sharp) modes) - bfb - Siemens mobile datalink cable protocol layer Short Installation Instructions ------------------------------- To compile and install: # mkdir build # cd build # cmake .. # make # make install (as superuser) If you plan to use a Siemens x45 or x55 series (e.g. S45 or C55, not S65) use # export CFLAGS="$CFLAGS -DCOMPAT_S45" before calling cmake. Consider using pedantic error checking: # export CFLAGS="$CFLAGS -Werror" If compiling doesn't work, try to disable some of the language bindings: # cmake -DENABLE_PERL=NO -DENABLE_PYTHON=NO -DENABLE_RUBY=NO -DENABLE_TCL=NO Further Development ------------------- If this tool lacks support for your phone or just won't work quite right please let me know. Development will focus on your needs. This package lacks advanced examples using the bindings. There are some 3rd party GUIs and other projects like a obex file system though. Please see the OpenOBEX / ObexFTP web site for details. Developers are free to use the bindings as well as obexftp, multicobex and bfb libraries. Please join the mailing list and keep in touch - You'll recieve pre-releases and support. That way your application can benefit from the newest library features and further development can focus on your needs. Debugging --------- remove all ObexFTP installations from your system. Rebuild using: # export CFLAGS="$CFLAGS -DOBEXFTP_DEBUG=5" Start debugging using ./apps/obexftp [...] Author and Contact ------------------ See file AUTHORS. obexftp-0.24.2-Source/THANKS000644 001750 001750 00000002451 12115273060 016530 0ustar00hendrikhendrik000000 000000 stef - helped in initial S45 (BFB) research Erich Schubert - provided a debian package Eduard Bloch - Debian maintainer since 2003. Jan Metz - supplied RH8 box and SL45i, ObexFTP info page Carsten Pfeiffer - coded a kio slave Jorge Ventura - write/select patch François Fleuret - suggested transport checks Adam Goode and Ken Booth - setpath Soren S. Jorvang - NetBSD portability fixes Bruce Simpson - FreeBSD portability fixes David Haslam - Sony-Ericsson fixes Philip Kovacs - connection id support Alan Zhang - daemon application Frode Isaksen - obexftpd improvements Simon Ruggier - cobex write patch Sergey Vlasov sugg. LDADD to LIBADD Alan J. McFarlane - rep. invalid conn_id in disconnect Dr. Johannes Zellner - spotted month/day swapping in atotime Martin Storsjö - PCSUITE over FTP sugg. for Series 60 2nd Ed. Manuel Naranjo - hci selection draft Andrey Rahmatullin - Motorola SLVR L2 cobex fix Adam Williamson - Python distutils testing obexftp-0.24.2-Source/TODO000644 001750 001750 00000000542 11351376660 016317 0ustar00hendrikhendrik000000 000000 ObexFTP to do list ================== * verify memory alloc's with bindings * cancel (async?) support for bindings * obexftp.is_connected() perhaps? * get perl and ruby to uninstall for distcheck (only python and tcl distcheck clean) * put to specified file (-p file.vcf -f telecom/pb.vcf) * Discover port and protocol to use (i.e. Bt, IrDA, TTY) obexftp-0.24.2-Source/apps/000755 001750 001750 00000000000 12701545532 016565 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/apps/CMakeLists.txt000644 001750 001750 00000001336 12655732776 021350 0ustar00hendrikhendrik000000 000000 add_definitions( -DVERSION="${obexftp_VERSION}" ) # always set this add_definitions ( -DHAVE_USB ) add_executable ( obexftp_app obexftp.c ) target_link_libraries ( obexftp_app obexftp ) set_target_properties ( obexftp_app PROPERTIES OUTPUT_NAME obexftp ) add_executable ( obexftpd_app obexftpd.c ) target_link_libraries ( obexftpd_app obexftp openobex ) set_target_properties ( obexftpd_app PROPERTIES OUTPUT_NAME obexftpd ) add_executable ( discovery_app discovery.c ) target_link_libraries ( discovery_app obexftp ) set_target_properties ( discovery_app PROPERTIES OUTPUT_NAME obexftp-discovery ) install ( TARGETS obexftp_app obexftpd_app RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications ) obexftp-0.24.2-Source/apps/discovery.c000644 001750 001750 00000022345 12656172555 020760 0ustar00hendrikhendrik000000 000000 /** \file apps/discovery.c Discover mobile and detect its class (Siemens, Ericsson). ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #define speed_t DWORD typedef HANDLE fd_t; #else #include #include typedef int fd_t; #endif #include struct mobile_param { const char *gmi; /* Manufacturer Identification to match */ const char *proto; /* Serial Protocol to use */ }; static struct mobile_param mobile_param[] = { {"siemens", "plain"}, {"ericsson", "bfb"}, {0, 0} }; struct mobile_info { char *gmi; /* AT+GMI : SIEMENS */ char *gmm; /* AT+GMM : Gipsy Soft Protocolstack */ char *gmr; /* AT+GMR : V2.550 */ char *cgmi; /* AT+CGMI : SIEMENS */ char *cgmm; /* AT+CGMM : S45 */ char *cgmr; /* AT+CGMR : 21 */ const char *ttyname; speed_t speed; }; /* S45: (auto baud) SIEMENS, Gipsy Soft Protocolstack, V2.550 SIEMENS, S45, 21 */ /* S25: (fixed at 19200) SIEMENS, Gipsy Soft Protocolstack, V2.400 SIEMENS, S25, 42 */ /* T68: Ericsson, T68, R2E006 prgCXC125326_TAE ERICSSON, 1130202-BVT68, R2E006 CXC125319 */ /* if auto-baud is enabled this will yoield the highest speed first */ #ifdef _WIN32 speed_t speeds[] = {CBR_115200, CBR_57600, CBR_38400, CBR_19200, CBR_9600, 0}; #else speed_t speeds[] = {B115200, B57600, B38400, B19200, B9600, B0}; #endif /* Send an AT-command an expect 1 line back as answer */ static int do_at_cmd(fd_t fd, const char *cmd, char *rspbuf, int rspbuflen) { #ifdef _WIN32 DWORD actual; #else fd_set ttyset; struct timeval tv; int actual; #endif char *answer; char *answer_end = NULL; int answer_size; char tmpbuf[200] = {0,}; int total = 0; int done = 0; int cmdlen; return_val_if_fail (fd > 0, -1); return_val_if_fail (cmd != NULL, -1); cmdlen = strlen(cmd); rspbuf[0] = 0; DEBUG(3, "%s() Sending %d: %s\n", __func__, cmdlen, cmd); /* Write command */ #ifdef _WIN32 if(!WriteFile(fd, cmd, cmdlen, &actual, NULL) || (actual != cmdlen)) { #else if(write(fd, cmd, cmdlen) != cmdlen) { #endif DEBUG(1, "Error writing to port\n"); return -1; } while(!done) { #ifdef _WIN32 if (!ReadFile(fd, &tmpbuf[total], sizeof(tmpbuf) - total, &actual, NULL)) { DEBUG(2, "%s() Read error: %ld\n", __func__, actual); } #else FD_ZERO(&ttyset); FD_SET(fd, &ttyset); tv.tv_sec = 2; tv.tv_usec = 0; if(select(fd+1, &ttyset, NULL, NULL, &tv)) { sleep(1); actual = read(fd, &tmpbuf[total], sizeof(tmpbuf) - total); #endif if(actual < 0) return actual; total += actual; DEBUG(3, "%s() tmpbuf=%d: %s\n", __func__, total, tmpbuf); /* Answer not found within 100 bytes. Cancel */ if(total == sizeof(tmpbuf)) return -1; if( (answer = strchr(tmpbuf, '\n')) ) { /* Remove first line (echo) */ if( (answer_end = strchr(answer+1, '\n')) ) { /* Found end of answer */ done = 1; } } #ifndef _WIN32 } else { /* Anser didn't come in time. Cancel */ return -1; } #endif } /* DEBUG(3, "%s() buf:%08lx answer:%08lx end:%08lx\n", __func__, tmpbuf, answer, answer_end); */ DEBUG(3, "%s() Answer: %s\n", __func__, answer); /* Remove heading and trailing \r */ if((*answer_end == '\r') || (*answer_end == '\n')) answer_end--; if((*answer_end == '\r') || (*answer_end == '\n')) answer_end--; if((*answer == '\r') || (*answer == '\n')) answer++; if((*answer == '\r') || (*answer == '\n')) answer++; DEBUG(3, "%s() Answer: %s\n", __func__, answer); answer_size = (answer_end) - answer +1; DEBUG(2, "%s() Answer size=%d\n", __func__, answer_size); if( (answer_size) >= rspbuflen ) return -1; strncpy(rspbuf, answer, answer_size); rspbuf[answer_size] = 0; return 0; } /* Init the phone and set it in BFB-mode */ /* Returns fd or -1 on failure */ static struct mobile_info *probe_tty(const char *ttyname) { int speed; char rspbuf[200]; struct mobile_info *info; char *p; #ifdef _WIN32 HANDLE ttyfd; DCB dcb; COMMTIMEOUTS ctTimeOuts; return_val_if_fail (ttyname != NULL, INVALID_HANDLE_VALUE); DEBUG(3, "%s() CreateFile\n", __func__); ttyfd = CreateFile (ttyname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (ttyfd == INVALID_HANDLE_VALUE) { fprintf(stderr, "Error: CreateFile()\n"); return NULL; } if(!GetCommState(ttyfd, &dcb)) fprintf(stderr, "Error: GetCommState()\n"); dcb.fBinary = TRUE; dcb.BaudRate = CBR_57600; dcb.fParity = FALSE; dcb.Parity = 0; dcb.ByteSize = 8; dcb.StopBits = 1; dcb.fInX = FALSE; dcb.fOutX = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.fOutxCtsFlow = FALSE; dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fRtsControl = RTS_CONTROL_ENABLE; if(!SetCommState(ttyfd, &dcb)) fprintf(stderr, "Error: SetCommState()\n"); ctTimeOuts.ReadIntervalTimeout = 250; ctTimeOuts.ReadTotalTimeoutMultiplier = 1; /* no good with big buffer */ ctTimeOuts.ReadTotalTimeoutConstant = 500; ctTimeOuts.WriteTotalTimeoutMultiplier = 1; ctTimeOuts.WriteTotalTimeoutConstant = 5000; if(!SetCommTimeouts(ttyfd, &ctTimeOuts)) fprintf(stderr, "Error: SetCommTimeouts()\n"); Sleep(500); /* flush all pending input */ if(!PurgeComm(ttyfd, PURGE_RXABORT | PURGE_RXCLEAR)) fprintf(stderr, "Error: PurgeComm()\n"); #else /* _WIN32 */ int ttyfd; struct termios oldtio, newtio; return_val_if_fail (ttyname != NULL, NULL); DEBUG(3, "%s() \n", __func__); info = calloc(1, sizeof(struct mobile_info)); info->ttyname = ttyname; if( (ttyfd = open(ttyname, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) < 0 ) { fprintf(stderr, "Error: Can't open tty\n"); free(info); return NULL; } /* probe mobile */ tcgetattr(ttyfd, &oldtio); for (speed = 0; speeds[speed] != B0; speed++) { memset(&newtio, 0, sizeof(newtio)); newtio.c_cflag = speeds[speed] | CS8 | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; tcflush(ttyfd, TCIFLUSH); tcsetattr(ttyfd, TCSANOW, &newtio); /* is this ok? do we need to send both cr and lf? */ if(do_at_cmd(ttyfd, "AT\r", rspbuf, sizeof(rspbuf)) < 0) { DEBUG(1, "Comm-error doing AT\n"); } else if(strcasecmp("OK", rspbuf) == 0) { DEBUG(2, "OKAY doing AT (%s)\n", rspbuf); break; } } if(speeds[speed] == B0) { close(ttyfd); free(info); DEBUG(1, "Nothing found\n"); return NULL; } info->speed = speeds[speed]; /* detect mobile */ if(do_at_cmd(ttyfd, "AT+GMI\r", rspbuf, sizeof(rspbuf)) < 0) { close(ttyfd); free(info); DEBUG(1, "Comm-error doing AT+GMI\n"); return NULL; } if ((p=strchr(rspbuf, '\r')) != NULL) *p = 0; if ((p=strchr(rspbuf, '\n')) != NULL) *p = 0; info->gmi = strdup(rspbuf); if(do_at_cmd(ttyfd, "AT+GMM\r", rspbuf, sizeof(rspbuf)) < 0) { close(ttyfd); free(info); DEBUG(1, "Comm-error doing AT+GMM\n"); return NULL; } if ((p=strchr(rspbuf, '\r')) != NULL) *p = 0; if ((p=strchr(rspbuf, '\n')) != NULL) *p = 0; info->gmm = strdup(rspbuf); if(do_at_cmd(ttyfd, "AT+GMR\r", rspbuf, sizeof(rspbuf)) < 0) { close(ttyfd); free(info); DEBUG(1, "Comm-error doing AT+GMR\n"); return NULL; } if ((p=strchr(rspbuf, '\r')) != NULL) *p = 0; if ((p=strchr(rspbuf, '\n')) != NULL) *p = 0; info->gmr= strdup(rspbuf); if(do_at_cmd(ttyfd, "AT+CGMI\r", rspbuf, sizeof(rspbuf)) < 0) { close(ttyfd); free(info); DEBUG(1, "Comm-error doing AT+CGMI\n"); return NULL; } if ((p=strchr(rspbuf, '\r')) != NULL) *p = 0; if ((p=strchr(rspbuf, '\n')) != NULL) *p = 0; info->cgmi = strdup(rspbuf); if(do_at_cmd(ttyfd, "AT+CGMM\r", rspbuf, sizeof(rspbuf)) < 0) { close(ttyfd); free(info); DEBUG(1, "Comm-error doing AT+CGMM\n"); return NULL; } if ((p=strchr(rspbuf, '\r')) != NULL) *p = 0; if ((p=strchr(rspbuf, '\n')) != NULL) *p = 0; info->cgmm = strdup(rspbuf); if(do_at_cmd(ttyfd, "AT+CGMR\r", rspbuf, sizeof(rspbuf)) < 0) { close(ttyfd); free(info); DEBUG(1, "Comm-error doing AT+CGMR\n"); return NULL; } if ((p=strchr(rspbuf, '\r')) != NULL) *p = 0; if ((p=strchr(rspbuf, '\n')) != NULL) *p = 0; info->cgmr= strdup(rspbuf); close(ttyfd); #endif return info; } int main(int argc, char *argv[]) { struct mobile_info *info; if (mobile_param != NULL) { }; if (argc > 1) info = probe_tty(argv[1]); else #ifdef _WIN32 info = probe_tty("COM1"); #else info = probe_tty("/dev/ttyS0"); #endif if (info != NULL) { printf("%s (%d):\n%s, %s, %s\n%s, %s, %s\n", info->ttyname, info->speed, info->gmi, info->gmm, info->gmr, info->cgmi, info->cgmm, info->cgmr); return (EXIT_SUCCESS); } return (EXIT_FAILURE); } obexftp-0.24.2-Source/apps/obexftpd.c000644 001750 001750 00000060617 12656172642 020565 0ustar00hendrikhendrik000000 000000 /** \file apps/obexftpd.c OBEX file server. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2003-2006 Christian W. Zuckschwerdt Alan Zhang Hendrik Sattler Frode Isaksen ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with ObexFTP. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #define S_IRGRP 0 #define S_IROTH 0 #define S_IWGRP 0 #define S_IWOTH 0 #define S_IXGRP 0 #define S_IXOTH 0 #define sleep(n) Sleep((n) * 1000) #define mkdir(dir,mode) _mkdir(dir) #define lstat stat #else #include #include #include #include #endif #include /* just until there is a server layer in obexftp */ #include #include #include #include #include /* define this to "", "\r\n" or "\n" */ #define EOLCHARS "\n" /* Application defined headers */ #define HDR_CREATOR 0xcf /* so we don't require OpenOBEX 1.3 */ #define WORK_PATH_MAX 128 #define CUR_DIR "./" static char *device = NULL; static int channel = 10; /* OBEX_PUSH_HANDLE */ static char init_work_path[WORK_PATH_MAX]; volatile int finished = 0; volatile int success = 0; volatile int obexftpd_reset = 0; uint32_t connection_id = 0; int verbose = 0; // this whole thing needs a review: static int parsehostport(const char *name, char **host, int *port) { struct hostent *e; char *p, *s; uint8_t n[4]; p = strdup(name); *port = 650; if ((s=strchr(p, ':'))) { *s = '\0'; *port = atoi(++s); } *host = "0.0.0.0"; if (sscanf(p, "%hhu.%hhu.%hhu.%hhu", &n[0], &n[1], &n[2], &n[3]) == 4) { *host = strdup(p); } else { e = gethostbyname(p); if (e) { *host = e->h_addr_list[0]; // inet_ntoa needed! } } free(p); return 0; } //BEGIN of compositor the folder listing XML document struct rawdata_stream { char *data; unsigned int block_size; unsigned int size; unsigned int max_size; }; static struct rawdata_stream* INIT_RAWDATA_STREAM(unsigned int size) { struct rawdata_stream *stream = malloc(sizeof(*stream)); if (NULL == stream) { return NULL; } stream->data = malloc(size); if (NULL == stream->data) { free(stream); return NULL; } memset(stream->data,0,size); stream->size = 0; stream->block_size = size; stream->max_size = size; return stream; } static int ADD_RAWDATA_STREAM_DATA(struct rawdata_stream *stream, const char *data) { char *databuf; unsigned int size; if (data == NULL) return 0; size = strlen(data); if (size == 0) return 0; if ((size + stream->size) >= stream->max_size) { while((size + stream->size) >= stream->max_size) { stream->max_size += stream->block_size; } databuf = realloc(stream->data, stream->max_size); if (NULL == databuf) { fprintf(stderr, "realloc() failed\n"); return -1; } stream->data = databuf; } strcat(stream->data, data); stream->size += size; return size; } static void FREE_RAWDATA_STREAM(struct rawdata_stream *stream) { free(stream->data); free(stream); } #define FL_XML_VERSION(stream) \ ADD_RAWDATA_STREAM_DATA(stream, "" EOLCHARS); #define FL_XML_TYPE(stream) \ ADD_RAWDATA_STREAM_DATA(stream, "" EOLCHARS); #define FL_XML_BODY_BEGIN(stream) \ ADD_RAWDATA_STREAM_DATA(stream, "" EOLCHARS); #define FL_XML_BODY_END(stream) \ ADD_RAWDATA_STREAM_DATA(stream, "" EOLCHARS); #define FL_XML_BODY_ITEM_BEGIN(stream) \ ADD_RAWDATA_STREAM_DATA(stream, "<"); #define FL_XML_BODY_ITEM_END(stream) \ ADD_RAWDATA_STREAM_DATA(stream, "/>" EOLCHARS); inline static void FL_XML_BODY_FOLDERNAME(struct rawdata_stream *stream, char *name) { ADD_RAWDATA_STREAM_DATA(stream, "folder name=\""); ADD_RAWDATA_STREAM_DATA(stream, name); ADD_RAWDATA_STREAM_DATA(stream, "\" "); } inline static void FL_XML_BODY_FILENAME(struct rawdata_stream *stream, char *name) { ADD_RAWDATA_STREAM_DATA(stream, "file name=\""); ADD_RAWDATA_STREAM_DATA(stream, name); ADD_RAWDATA_STREAM_DATA(stream, "\" "); } inline static void FL_XML_BODY_SIZE(struct rawdata_stream *stream, unsigned int size) { const char format[] = "size=\"%d\" "; char str_size[sizeof(format)+14]; snprintf(str_size,sizeof(str_size), format, size); ADD_RAWDATA_STREAM_DATA(stream, str_size); } inline static void FL_XML_BODY_PERM(struct rawdata_stream *stream, mode_t file, mode_t dir) { const char format[] = "user-perm=\"%s%s%s\" "; char str_perm[sizeof(format)]; snprintf(str_perm,sizeof(str_perm),format, (file & (S_IRUSR|S_IRGRP|S_IROTH)? "R": ""), (file & (S_IWUSR|S_IWGRP|S_IWOTH)? "W": ""), (dir & (S_IWUSR|S_IWGRP|S_IWOTH)? "D": "")); ADD_RAWDATA_STREAM_DATA(stream,str_perm); } inline static void FL_XML_BODY_TIME(struct rawdata_stream *stream, const char* type, time_t time) { struct tm* tm = gmtime(&time); char str_tm[sizeof("=\"yyyymmddThhmmssZ\" ")]; if (tm == NULL || stream == NULL || strftime(str_tm,sizeof(str_tm),"=\"%Y%m%dT%H%M%SZ\" ",tm) == 0) return; ADD_RAWDATA_STREAM_DATA(stream, type); ADD_RAWDATA_STREAM_DATA(stream, str_tm); } #define FL_XML_BODY_MTIME(stream,time) \ FL_XML_BODY_TIME(stream,"modified",time) #define FL_XML_BODY_CTIME(stream,time) \ FL_XML_BODY_TIME(stream,"created",time) #define FL_XML_BODY_ATIME(stream,time) \ FL_XML_BODY_TIME(stream,"accessed",time) //END of compositor the folder listing XML document inline static int is_type_fl(const char *type) { return (type && strcmp(type, XOBEX_LISTING) == 0); } static void connect_server(obex_t *handle, obex_object_t *object) { obex_headerdata_t hv; uint8_t hi; uint32_t hlen; uint8_t *target = NULL; int target_len = 0; //printf("%s()\n", __FUNCTION__); while (OBEX_ObjectGetNextHeader(handle, object, &hi, &hv, &hlen)) { switch(hi) { case OBEX_HDR_TARGET: if (0 < hlen) { if( (target = malloc(hlen))) { target_len = hlen; memcpy(target,hv.bs,target_len); } } break; default: printf("%s() Skipped header %02x\n", __FUNCTION__, hi); break; } } OBEX_ObjectSetRsp(object, OBEX_RSP_SUCCESS, OBEX_RSP_SUCCESS); hv.bq4 = connection_id; if(OBEX_ObjectAddHeader(handle, object, OBEX_HDR_CONNECTION, hv, sizeof(hv.bq4), OBEX_FL_FIT_ONE_PACKET) < 0 ) { fprintf(stderr, "Error adding header CONNECTION\n"); OBEX_ObjectDelete(handle, object); return; } if (target && target_len) { hv.bs = target; if(OBEX_ObjectAddHeader(handle,object,OBEX_HDR_WHO, hv,target_len,OBEX_FL_FIT_ONE_PACKET) < 0 ) { fprintf(stderr, "Error adding header WHO\n"); OBEX_ObjectDelete(handle, object); return; } free(target); } } static void set_server_path(obex_t *handle, obex_object_t *object) { char *name = NULL; char fullname[WORK_PATH_MAX]; // "Backup Level" and "Don't Create" flag in first byte uint8_t setpath_nohdr_dummy = 0; uint8_t *setpath_nohdr_data; obex_headerdata_t hv; uint8_t hi; uint32_t hlen; OBEX_ObjectGetNonHdrData(object, &setpath_nohdr_data); if (NULL == setpath_nohdr_data) { setpath_nohdr_data = &setpath_nohdr_dummy; printf("nohdr data not found\n"); } printf("nohdr data: %x\n", *setpath_nohdr_data); while(OBEX_ObjectGetNextHeader(handle, object, &hi, &hv, &hlen)) { switch(hi) { case OBEX_HDR_NAME: printf("%s() Found name\n", __FUNCTION__); if (0 < hlen) { if( (name = malloc(hlen / 2))) { UnicodeToChar((uint8_t*)name, hv.bs, hlen); printf("name:%s\n", name); } } else { if (verbose) printf("set path to root\n"); chdir(init_work_path); } break; default: printf("%s() Skipped header %02x\n", __FUNCTION__, hi); } } if (name) { if (strstr(name, "/../")) { OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_FORBIDDEN); } else { strcpy(fullname, CUR_DIR); strncat(fullname, name, sizeof(fullname)-1); if ((*setpath_nohdr_data & 2) == 0) { if (verbose) printf("mkdir %s\n", name); if (mkdir(fullname, 0755) < 0) { perror("requested mkdir failed"); } } if (verbose) printf("Set path to %s\n",fullname); if (chdir(fullname) < 0) { perror("requested chdir failed\n"); OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_FORBIDDEN); } } free(name); name = NULL; } } // // Get the filesize in a "portable" way // static int get_filesize(const char *filename) { struct stat stats; stat(filename, &stats); if (S_ISDIR(stats.st_mode)) { fprintf(stderr,"GET of directories not implemented !!!!\n"); return -1; } return (int) stats.st_size; } // // Read a file and alloc a buffer for it // static uint8_t* easy_readfile(const char *filename, int *file_size) { int actual; int fd; uint8_t *buf; *file_size = get_filesize(filename); printf("name=%s, size=%d\n", filename, *file_size); fd = open(filename, O_RDONLY, 0); if (fd == -1) { return NULL; } buf = malloc(*file_size); if(buf == NULL) { return NULL; } actual = read(fd, buf, *file_size); close(fd); *file_size = actual; return buf; } static void get_server(obex_t *handle, obex_object_t *object) { uint8_t *buf = NULL; obex_headerdata_t hv; uint8_t hi; uint32_t hlen; int file_size; char *name = NULL; char *type = NULL; printf("%s()\n", __FUNCTION__); while(OBEX_ObjectGetNextHeader(handle, object, &hi, &hv, &hlen)) { switch(hi) { case OBEX_HDR_NAME: printf("%s() Found name\n", __FUNCTION__); if( (name = malloc(hlen / 2))) { UnicodeToChar((uint8_t*)name, hv.bs, hlen); printf("name:%s\n", name); } break; case OBEX_HDR_TYPE: if( (type = malloc(hlen + 1))) { strcpy(type, (char *)hv.bs); } printf("%s() type:%s\n", __FUNCTION__, type); break; case 0xbe: // user-defined inverse push printf("%s() Found inverse push req\n", __FUNCTION__); printf("data:%02x\n", hv.bq1); break; case OBEX_HDR_APPARAM: printf("%s() Found apparam\n", __FUNCTION__); printf("name:%d (%02x %02x ...)\n", hlen, *hv.bs, *(hv.bs+1)); break; default: printf("%s() Skipped header %02x\n", __FUNCTION__, hi); } } //fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); if (is_type_fl(type)) { struct dirent *dirp; DIR *dp; struct stat statdir; struct stat statbuf; char *filename; struct rawdata_stream *xmldata; xmldata = INIT_RAWDATA_STREAM(512); if (NULL == xmldata) goto out; FL_XML_VERSION(xmldata); FL_XML_TYPE(xmldata); FL_XML_BODY_BEGIN(xmldata); stat(CUR_DIR, &statdir); dp = opendir(CUR_DIR); while(NULL != dp && NULL != (dirp = readdir(dp))) { if (0 == strcmp(dirp->d_name, ".") || 0 == strcmp(dirp->d_name, "..")) continue; FL_XML_BODY_ITEM_BEGIN(xmldata); //Adding 1 bytes due to containing '\0' filename = malloc(strlen(CUR_DIR) + strlen(dirp->d_name) + 1); strcpy(filename, CUR_DIR); strcat(filename, dirp->d_name); lstat(filename, &statbuf); if (0 == S_ISDIR(statbuf.st_mode)) //it is a file FL_XML_BODY_FILENAME(xmldata, dirp->d_name); else //it is a directory FL_XML_BODY_FOLDERNAME(xmldata, dirp->d_name); FL_XML_BODY_SIZE(xmldata, statbuf.st_size); FL_XML_BODY_PERM(xmldata, statbuf.st_mode, statdir.st_mode); FL_XML_BODY_MTIME(xmldata, statbuf.st_mtime); FL_XML_BODY_CTIME(xmldata, statbuf.st_ctime); FL_XML_BODY_ATIME(xmldata, statbuf.st_atime); FL_XML_BODY_ITEM_END(xmldata); //printf("---filename:%s\n", filename); //fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); free(filename); filename = NULL; //fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); } //fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); FL_XML_BODY_END(xmldata); closedir(dp); printf("xml doc:%s\n", xmldata->data); //composite the obex obejct OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); hv.bq4 = xmldata->size; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_LENGTH, hv, sizeof(uint32_t), 0); hv.bs = (uint8_t *)xmldata->data; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_BODY, hv, xmldata->size, 0); //fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); FREE_RAWDATA_STREAM(xmldata); //fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); } else if (name) { printf("%s() Got a request for %s\n", __FUNCTION__, name); buf = easy_readfile(name, &file_size); if(buf == NULL) { printf("Can't find file %s\n", name); OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_FOUND, OBEX_RSP_NOT_FOUND); return; } OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); hv.bq4 = file_size; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_LENGTH, hv, sizeof(uint32_t), 0); hv.bs = buf; OBEX_ObjectAddHeader(handle, object, OBEX_HDR_BODY, hv, file_size, 0); } else { printf("%s() Got a GET without a name-header!\n", __FUNCTION__); OBEX_ObjectSetRsp(object, OBEX_RSP_NOT_FOUND, OBEX_RSP_NOT_FOUND); return; } //fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); if (NULL != buf) { free(buf); } //fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); out: if (NULL != name) { free(name); } //fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); if (NULL != type) { free(type); } //fprintf(stderr, "%s:%d:%s\n", __FILE__, __LINE__, __FUNCTION__); return; } /* * Function safe_save_file () * * First remove path and add "/tmp/". Then save. * */ static int safe_save_file(char *name, const uint8_t *buf, int len) { char *s = NULL; char filename[255] = {0,}; int fd; int actual; printf("Filename = %s\n", name); s = strrchr(name, '/'); if (s == NULL) s = name; else s++; strncat(filename, s, 250); fd = open(filename, O_RDWR | O_CREAT | O_EXCL, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); if ( fd < 0) { perror( filename); return -1; } actual = write(fd, buf, len); close(fd); printf( "Wrote %s (%d bytes)\n", filename, actual); return actual; } /* * Function put_done() * * Parse what we got from a PUT * */ static void put_done(obex_t *handle, obex_object_t *object, int final) { obex_headerdata_t hv; uint8_t hi; uint32_t hlen; const uint8_t *body = NULL; int body_len = 0; static char *name = NULL; char fullname[WORK_PATH_MAX]; struct stat statbuf; //char *namebuf = NULL; fprintf(stderr, "put_done>>>\n"); while(OBEX_ObjectGetNextHeader(handle, object, &hi, &hv, &hlen)) { switch(hi) { case OBEX_HDR_BODY: body = hv.bs; body_len = hlen; fprintf(stderr, "hv.bs=%p, hlen=%d\n", hv.bs, hlen); break; case OBEX_HDR_NAME: if (NULL != name) { free(name); } if( (name = malloc(hlen / 2))) { UnicodeToChar((uint8_t *)name, hv.bs, hlen); fprintf(stderr, "put file name: %s\n", name); } break; case OBEX_HDR_LENGTH: printf("HEADER_LENGTH = %d\n", hv.bq4); break; case HDR_CREATOR: printf("CREATORID = %#x\n", hv.bq4); break; default: printf("%s () Skipped header %02x\n", __FUNCTION__ , hi); } } if(!body) { printf("Got a PUT without a body\n"); OBEX_ObjectSetRsp(object, OBEX_RSP_CONTINUE, OBEX_RSP_SUCCESS); } if(!name) { name = strdup("OBEX_PUT_Unknown_object"); printf("Got a PUT without a name. Setting name to %s\n", name); } if (body) { safe_save_file(name, body, body_len); } if(final && !body) { strcpy(fullname, CUR_DIR); strcat(fullname, name); if (!stat(fullname, &statbuf)) { perror("stat failed"); } if (S_ISDIR(statbuf.st_mode)) { printf("Removing dir %s\n", name); rmdir(fullname); } else { printf("Deleting file %s\n", name); unlink(fullname); } } if (final) { free(name); name = NULL; fprintf(stderr, "<<= strlen(progress)) i = 0; switch(obex_cmd) { case OBEX_CMD_PUT: fprintf(stderr, "obex_ev_progress: obex_cmd_put\n"); put_done(handle, obj, 0); break; default: break; } break; case OBEX_EV_ABORT: /* Request was aborted */ printf("%s() OBEX_EV_ABORT: mode=%02x, obex_cmd=%02x, obex_rsp=%02x\n", __func__, mode, obex_cmd, obex_rsp); break; case OBEX_EV_STREAMEMPTY: //(void) cli_fillstream(cli, object); break; case OBEX_EV_UNEXPECTED: /* Unexpected data, not fatal */ break; default: printf("%s() Unhandled event %d\n", __func__, event); break; } } static void start_server(int transport) { int use_sdp = 0; obex_t *handle = NULL; struct sockaddr_in saddr; if (NULL == getcwd(init_work_path, WORK_PATH_MAX) && ERANGE == errno) { fprintf(stderr, "Wah, work path is too long, exceed %d.\n", WORK_PATH_MAX); exit(0); } if (transport==OBEX_TRANS_BLUETOOTH && (0 > obexftp_sdp_register_push(channel) || 0 > obexftp_sdp_register_ftp(channel))) { //OBEX_Cleanup(handle); fprintf(stderr, "register to SDP Server failed.\n"); } else { use_sdp = 1; } reset: handle = OBEX_Init(transport, obex_event, 0); if (NULL == handle) { perror("failed to init obex."); exit(-1); } switch (transport) { case OBEX_TRANS_INET: saddr.sin_family = AF_INET; saddr.sin_port = htons(channel); #ifdef _WIN32 saddr.sin_addr.s_addr = inet_addr(device); #else (void) inet_aton(device, &saddr.sin_addr); #endif if (0 > TcpOBEX_ServerRegister(handle, (struct sockaddr *)&saddr, sizeof(saddr))) { perror("failed to register inet server"); exit(-1); } break; #ifdef HAVE_BLUETOOTH case OBEX_TRANS_BLUETOOTH: if (0 > BtOBEX_ServerRegister(handle, /*bdaddr_t *bt_src*/NULL, channel)) { perror("failed to register bluetooth server"); exit(-1); } break; #endif case OBEX_TRANS_IRDA: if (0 > IrOBEX_ServerRegister(handle, "")) { perror("failed to register IrDA server"); exit(-1); } break; case OBEX_TRANS_CUSTOM: /* A simple Ericsson protocol session perhaps? */ default: fprintf(stderr, "Transport type unknown\n"); exit(-1); } printf("Waiting for connection...\n"); while (!finished) { //printf("Handling connection...\n"); OBEX_HandleInput(handle, -1); } OBEX_Cleanup(handle); sleep(1); /* throttle */ if (obexftpd_reset) { fprintf(stderr, "obexftpd reset\n"); obexftpd_reset = 0; finished = 0; success = 0; goto reset; } if (use_sdp) { fprintf(stderr, "sdp unregister\n"); if (0 > obexftp_sdp_unregister_push() || 0 > obexftp_sdp_unregister_ftp()) { fprintf(stderr, "unregister from SDP Server failed.\n"); } } } int main(int argc, char *argv[]) { int c; while (1) { int option_index = 0; static struct option long_options[] = { {"irda", no_argument, NULL, 'i'}, {"bluetooth", optional_argument, NULL, 'b'}, {"tty", required_argument, NULL, 't'}, {"network", required_argument, NULL, 'n'}, {"chdir", required_argument, NULL, 'c'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {"help", no_argument, NULL, 'h'}, {"usage", no_argument, NULL, 'h'}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "-ib::t:n:c:vVh", long_options, &option_index); if (c == -1) break; switch (c) { case 'i': start_server(OBEX_TRANS_IRDA); break; case 'b': if (optarg) { channel = atoi(optarg); } start_server(OBEX_TRANS_BLUETOOTH); fprintf(stderr, "server end\n"); break; case 'n': parsehostport(optarg, &device, &channel); //channel = atoi(optarg); start_server(OBEX_TRANS_INET); fprintf(stderr, "server end\n"); break; case 't': printf("accepting on tty not implemented yet."); /* start_server(OBEX_TRANS_CUSTOM); optarg */ break; case 'c': chdir(optarg); break; case 'v': verbose++; break; case 'V': printf("ObexFTPd %s\n", VERSION); break; case 'h': printf("ObexFTPd %s\n", VERSION); printf("Usage: %s [-c ] [-v] [-i | -b | -t | -n ]\n" "Recieve files from/to Mobile Equipment.\n" "Copyright (c) 2003-2006 Christian W. Zuckschwerdt, Alan Zhang,\n" " Hendrik Sattler, Frode Isaksen\n" "\n" " -i, --irda accept IrDA connections\n" " -b, --bluetooth [] accept bluetooth connections\n" " -t, --tty accept connections from this tty\n" " -n, --network accept network connections\n" "\n" " -c, --chdir set a default basedir\n" " -v, --verbose verbose messages\n" "\n" " -V, --version print version info\n" " -h, --help, --usage this help text\n", argv[0]); exit(0); default: printf("Try `%s --help' for more information.\n", argv[0]); } } if (optind < argc) { fprintf(stderr, "non-option ARGV-elements: "); while (optind < argc) fprintf(stderr, "%s ", argv[optind++]); fprintf(stderr, "\n"); exit (-1); } exit (0); } obexftp-0.24.2-Source/apps/obexftp.c000644 001750 001750 00000054223 12656173676 020425 0ustar00hendrikhendrik000000 000000 /** \file apps/obexftp.c Command line client to transfer from/to Mobile Equipment via OBEX. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ /* for * - strcasestr() */ #define _GNU_SOURCE #include #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #define strcasestr strstr #define ETIMEDOUT WSAETIMEDOUT #define ECONNREFUSED WSAECONNREFUSED #define EHOSTDOWN WSAEHOSTDOWN #define EINPROGRESS WSAEINPROGRESS #endif /* _WIN32 */ #include #ifdef HAVE_SYS_TIMES_H #include #endif // perhaps this scheme would be better? // IRDA irda://[nick?] // CABLE tty://path // BLUETOOTH bt://[device[:channel]] // USB usb://[enum] // INET host://host[:port] #define OBEXFTP_CABLE "OBEXFTP_CABLE" #define OBEXFTP_BLUETOOTH "OBEXFTP_BLUETOOTH" #define OBEXFTP_USB "OBEXFTP_USB" #define OBEXFTP_INET "OBEXFTP_INET" #define OBEXFTP_CHANNEL "OBEXFTP_CHANNEL" /* current command, set by main, read from info_cb */ int c; static void info_cb(int event, const char *msg, int len, void *UNUSED(data)) { char progress[] = "\\|/-"; static unsigned int i = 0; switch (event) { case OBEXFTP_EV_ERRMSG: fprintf(stderr, "Error: %s\n", msg); break; case OBEXFTP_EV_ERR: // OBEX_EV_REQDONE: obex_rsp=43 (SE user reject) fprintf(stderr, "failed: %s\n", msg); break; case OBEXFTP_EV_OK: fprintf(stderr, "done\n"); break; case OBEXFTP_EV_CONNECTING: fprintf(stderr, "Connecting..."); break; case OBEXFTP_EV_DISCONNECTING: fprintf(stderr, "Disconnecting..."); break; case OBEXFTP_EV_SENDING: fprintf(stderr, "Sending \"%s\"... ", msg); break; case OBEXFTP_EV_RECEIVING: fprintf(stderr, "Receiving \"%s\"... ", msg); break; case OBEXFTP_EV_LISTENING: fprintf(stderr, "Waiting for incoming connection\n"); break; case OBEXFTP_EV_CONNECTIND: fprintf(stderr, "Incoming connection\n"); break; case OBEXFTP_EV_DISCONNECTIND: fprintf(stderr, "Disconnecting\n"); break; case OBEXFTP_EV_INFO: printf("Got info %u: \n", *(uint32_t*)msg); break; case OBEXFTP_EV_BODY: if (c == 'l' || c == 'X' || c == 'P') { if (msg == NULL) fprintf(stderr, "No body.\n"); else if (len == 0) fprintf(stderr, "Empty body.\n"); else write(STDOUT_FILENO, msg, len); } break; case OBEXFTP_EV_PROGRESS: fprintf(stderr, "%c%c", 0x08, progress[i++]); fflush(stdout); if (i >= strlen(progress)) i = 0; break; } } /* create global uuid buffers */ static const uint8_t *fbs_uuid = UUID_FBS; static const uint8_t *irmc_uuid = UUID_IRMC; static const uint8_t *s45_uuid = UUID_S45; static const uint8_t *pcsoftware_uuid = UUID_PCSOFTWARE; /* parse UUID string to real bytes */ static int parse_uuid(char *name, const uint8_t **uuid, int *uuid_len) { if (name == NULL || *name == '\0' || !strncasecmp(name, "none", 4) || !strncasecmp(name, "null", 4) || !strncasecmp(name, "push", 4) || !strncasecmp(name, "goep", 4)) { fprintf(stderr, "Suppressing FBS.\n"); if (uuid) *uuid = NULL; if (uuid_len) *uuid_len = 0; return 0; } if (!strncasecmp(name, "fbs", 3) || !strncasecmp(name, "ftp", 3)) { fprintf(stderr, "Using FBS uuid.\n"); if (uuid) *uuid = fbs_uuid; if (uuid_len) *uuid_len = sizeof(UUID_FBS); return sizeof(UUID_FBS); } if (!strncasecmp(name, "sync", 4) || !strncasecmp(name, "irmc", 4)) { fprintf(stderr, "Using SYNCH uuid.\n"); if (uuid) *uuid = irmc_uuid; if (uuid_len) *uuid_len = sizeof(UUID_IRMC); return sizeof(UUID_IRMC); } if (!strncasecmp(name, "s45", 3) || !strncasecmp(name, "sie", 3)) { fprintf(stderr, "Using S45 uuid.\n"); if (uuid) *uuid = s45_uuid; if (uuid_len) *uuid_len = sizeof(UUID_S45); return sizeof(UUID_S45); } if (!strncasecmp(name, "pcsoftware", 10) || !strncasecmp(name, "sharp", 5)) { fprintf(stderr, "Using PCSOFTWARE uuid.\n"); if (uuid) *uuid = pcsoftware_uuid; if (uuid_len) *uuid_len = sizeof(UUID_PCSOFTWARE); return sizeof(UUID_PCSOFTWARE); } return -1; } #ifdef HAVE_USB static void discover_usb() { char **devices; char **dev; int interfaces_number; devices = obexftp_discover(OBEX_TRANS_USB); interfaces_number = 0; for(dev = devices; *dev; dev++) interfaces_number++; printf("Found %d USB OBEX interfaces\n\n", interfaces_number); for(dev = devices; *dev; dev++) { fprintf(stderr, "%s\n", *dev); } printf("\nUse '-u interface_number' to connect\n"); } #endif static int find_bt(char *addr, char **res_bdaddr, int *res_channel) { char **devices; char **dev; *res_bdaddr = addr; if (!addr || strlen(addr) < (6*2+5) || addr[2]!=':') { fprintf(stderr, "Scanning for %s ...\n", addr); devices = obexftp_discover(OBEX_TRANS_BLUETOOTH); for(dev = devices; dev && *dev; dev++) { if (!addr || strcasestr(*dev, addr)) { fprintf(stderr, "Found: %s\n", *dev); *res_bdaddr = *dev; break; } fprintf(stderr, "Seen: %s\n", *dev); } } if (!*res_bdaddr) return -1; /* No (matching) BT device found */ // (*res_bdaddr)[17] = '\0'; if (*res_channel < 0) { fprintf(stderr, "Browsing %s ...\n", *res_bdaddr); *res_channel = obexftp_browse_bt_ftp(*res_bdaddr); } if (*res_channel < 0) return -1; /* No valid BT channel found */ return 0; } /*@only@*/ /*@null@*/ static obexftp_client_t *cli = NULL; static const char *src_dev = NULL; #ifdef HAVE_BLUETOOTH static int transport = OBEX_TRANS_BLUETOOTH; #else static int transport = OBEX_TRANS_IRDA; #endif /* HAVE_BLUETOOTH */ /*@only@*/ /*@null@*/ static char *device = NULL; static int channel = -1; static const uint8_t *use_uuid = UUID_FBS; static int use_uuid_len = sizeof(UUID_FBS); static int use_conn=1; static int use_path=1; static int timeout = 20; /* default accept/reject timeout of 20 seconds */ /* connect with given uuid. re-connect every time */ static int cli_connect_uuid(const uint8_t *uuid, int uuid_len) { int ret, retry; #ifdef HAVE_SYS_TIMES_H clock_t clock; struct tms tms; #endif if (cli == NULL) { /* Open */ cli = obexftp_open (transport, NULL, info_cb, NULL); if(cli == NULL) { fprintf(stderr, "Error opening obexftp-client\n"); exit(1); //return -1; } if (!use_conn) { cli->quirks &= ~OBEXFTP_CONN_HEADER; } if (!use_path) { cli->quirks &= ~OBEXFTP_SPLIT_SETPATH; } cli->accept_timeout=timeout; } /* complete bt address if necessary */ if (transport == OBEX_TRANS_BLUETOOTH) { find_bt(device, &device, &channel); // we should free() the find_bt result at some point } for (retry = 0; retry < 3; retry++) { /* Connect */ #ifdef HAVE_SYS_TIMES_H clock = times(&tms); #endif ret = obexftp_connect_src(cli, src_dev, device, channel, uuid, uuid_len); #ifdef HAVE_SYS_TIMES_H clock = (times(&tms) - clock) * 1000 / sysconf(_SC_CLK_TCK); fprintf(stderr, "Tried to connect for %ldms\n", (long)clock); #endif if (ret >= 0) return ret; switch (errno) { case ETIMEDOUT: perror("The device may have moved out of range"); break; /* retry */ case ECONNREFUSED: perror("The user may have rejected the transfer"); return -errno; case EHOSTDOWN: perror("The device may be out of range or turned off"); break; /* retry */ case EINPROGRESS: perror("Interupted/bad reception or the device moved out of range"); break; /* retry */ default: fprintf(stderr, "unknown error on connect\n"); break; } fprintf(stderr, "Still trying to connect\n"); } obexftp_close(cli); cli = NULL; return ret; } /* connect, possibly without fbs uuid. won't re-connect */ static int cli_connect() { if (cli != NULL) { return 0; } if (cli_connect_uuid(use_uuid, use_uuid_len) < 0) exit(1); return 0; } static void cli_disconnect() { if (cli != NULL) { /* Disconnect */ (void) obexftp_disconnect (cli); /* Close */ obexftp_close (cli); cli = NULL; } } static void probe_device_uuid(const uint8_t *uuid, int uuid_len) { int rsp[10]; if (cli_connect_uuid(uuid, uuid_len) < 0) { printf("couldn't connect.\n"); return; } printf("getting null object without type\n"); (void) obexftp_get_type(cli, NULL, NULL, NULL); rsp[0] = cli->obex_rsp; printf("response code %02x\n", cli->obex_rsp); printf("getting empty object without type\n"); (void) obexftp_get_type(cli, NULL, NULL, ""); rsp[1] = cli->obex_rsp; printf("response code %02x\n", cli->obex_rsp); printf("getting null object with x-obex/folder-listing type\n"); (void) obexftp_get_type(cli, XOBEX_LISTING, NULL, NULL); rsp[2] = cli->obex_rsp; printf("response code %02x\n", cli->obex_rsp); printf("getting empty object with x-obex/folder-listing type\n"); (void) obexftp_get_type(cli, XOBEX_LISTING, NULL, ""); rsp[3] = cli->obex_rsp; printf("response code %02x\n", cli->obex_rsp); printf("getting null object with x-obex/capability type\n"); (void) obexftp_get_type(cli, XOBEX_CAPABILITY, NULL, NULL); rsp[4] = cli->obex_rsp; printf("response code %02x\n", cli->obex_rsp); printf("getting empty object with x-obex/capability type\n"); (void) obexftp_get_type(cli, XOBEX_CAPABILITY, NULL, ""); rsp[5] = cli->obex_rsp; printf("response code %02x\n", cli->obex_rsp); printf("getting null object with x-obex/object-profile type\n"); (void) obexftp_get_type(cli, XOBEX_PROFILE, NULL, NULL); rsp[6] = cli->obex_rsp; printf("response code %02x\n", cli->obex_rsp); printf("getting empty object with x-obex/object-profile type\n"); (void) obexftp_get_type(cli, XOBEX_PROFILE, NULL, ""); rsp[7] = cli->obex_rsp; printf("response code %02x\n", cli->obex_rsp); printf("getting telecom/devinfo.txt object\n"); cli->quirks = 0; (void) obexftp_get_type(cli, NULL, NULL, "telecom/devinfo.txt"); rsp[8] = cli->obex_rsp; printf("response code %02x\n", cli->obex_rsp); printf("getting telecom/devinfo.txt object with setpath\n"); cli->quirks = (OBEXFTP_LEADING_SLASH | OBEXFTP_TRAILING_SLASH | OBEXFTP_SPLIT_SETPATH); (void) obexftp_get_type(cli, NULL, NULL, "telecom/devinfo.txt"); rsp[9] = cli->obex_rsp; printf("response code %02x\n", cli->obex_rsp); printf("=== response codes === %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", rsp[0], rsp[1], rsp[2], rsp[3], rsp[4], rsp[5], rsp[6], rsp[7], rsp[8], rsp[9]); //cli_disconnect(); if (cli != NULL) { (void) obexftp_disconnect (cli); } } /* try the whole probing with different uuids */ static void probe_device() { printf("\n=== Probing with FBS uuid.\n"); probe_device_uuid(UUID_FBS, sizeof(UUID_FBS)); printf("\n=== Probing with S45 uuid.\n"); probe_device_uuid(UUID_S45, sizeof(UUID_S45)); printf("\n=== Probing without uuid.\n"); probe_device_uuid(NULL, 0); printf("\nEnd of probe.\n"); exit (0); } int main(int argc, char *argv[]) { int verbose = 0; int most_recent_cmd = 0; char *output_file = NULL; char *move_src = NULL; int ret = 0; /* preset mode of operation depending on our name */ if (strstr(argv[0], "ls") != NULL) most_recent_cmd = 'l'; if (strstr(argv[0], "get") != NULL) most_recent_cmd = 'g'; if (strstr(argv[0], "put") != NULL) most_recent_cmd = 'p'; if (strstr(argv[0], "rm") != NULL) most_recent_cmd = 'k'; /* preset the port from environment */ if (getenv(OBEXFTP_CHANNEL) != NULL) { channel = atoi(getenv(OBEXFTP_CHANNEL)); } if (channel >= 0) { transport = OBEX_TRANS_USB; fprintf(stderr, "Presetting to USB: %d\n", channel); } if (getenv(OBEXFTP_CABLE) != NULL) { device = getenv(OBEXFTP_CABLE); transport = OBEX_TRANS_CUSTOM; fprintf(stderr, "Presetting to TTY: %s\n", device); } if (getenv(OBEXFTP_BLUETOOTH) != NULL) { device = getenv(OBEXFTP_BLUETOOTH); transport = OBEX_TRANS_BLUETOOTH; fprintf(stderr, "Presetting to BT: %s (%d)\n", device, channel); } if (getenv(OBEXFTP_INET) != NULL) { device = getenv(OBEXFTP_INET); transport = OBEX_TRANS_INET; fprintf(stderr, "Presetting to INET: %s\n", device); } while (1) { int option_index = 0; static struct option long_options[] = { {"irda", no_argument, NULL, 'i'}, #ifdef HAVE_BLUETOOTH {"bluetooth", optional_argument, NULL, 'b'}, {"channel", required_argument, NULL, 'B'}, {"hci", required_argument, NULL, 'd'}, #endif #ifdef HAVE_USB {"usb", optional_argument, NULL, 'u'}, #endif {"tty", required_argument, NULL, 't'}, {"network", required_argument, NULL, 'n'}, {"uuid", optional_argument, NULL, 'U'}, {"noconn", no_argument, NULL, 'H'}, {"nopath", no_argument, NULL, 'S'}, {"timeout", required_argument, NULL, 'T'}, {"list", optional_argument, NULL, 'l'}, {"chdir", required_argument, NULL, 'c'}, {"mkdir", required_argument, NULL, 'C'}, {"output", required_argument, NULL, 'o'}, {"get", required_argument, NULL, 'g'}, {"getdelete", required_argument, NULL, 'G'}, {"put", required_argument, NULL, 'p'}, {"delete", required_argument, NULL, 'k'}, {"capability", no_argument, NULL, 'X'}, {"probe", no_argument, NULL, 'Y'}, {"info", no_argument, NULL, 'x'}, {"move", required_argument, NULL, 'm'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {"help", no_argument, NULL, 'h'}, {"usage", no_argument, NULL, 'h'}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "-ib::B:d:u::t:n:U::HST:L::l::c:C:f:o:g:G:p:k:XYxm:VvhN:FP", long_options, &option_index); if (c == -1) break; if (c == 1) c = most_recent_cmd; switch (c) { case 'i': transport = OBEX_TRANS_IRDA; device = NULL; channel = 0; break; #ifdef HAVE_BLUETOOTH case 'b': transport = OBEX_TRANS_BLUETOOTH; /* handle severed optional option argument */ if (!optarg && argc > optind && argv[optind][0] != '-') { optarg = argv[optind]; optind++; } device = optarg; break; case 'B': channel = atoi(optarg); break; case 'd': src_dev = optarg; break; #endif /* HAVE_BLUETOOTH */ #ifdef HAVE_USB case 'u': #ifndef _WIN32 if (geteuid() != 0) fprintf(stderr, "If USB doesn't work setup permissions in udev or run as superuser.\n"); #endif transport = OBEX_TRANS_USB; device = NULL; /* handle severed optional option argument */ if (!optarg && argc > optind && argv[optind][0] != '-') { optarg = argv[optind]; optind++; channel = atoi(optarg); } else { discover_usb(); } break; #endif /* HAVE_USB */ case 't': transport = OBEX_TRANS_CUSTOM; device = optarg; channel = 0; if (strstr(optarg, "ir") != NULL) fprintf(stderr, "Do you really want to use IrDA via ttys?\n"); break; case 'N': fprintf(stderr,"Option -%c is deprecated, use -%c instead\n",'N','n'); case 'n': transport = OBEX_TRANS_INET; device = optarg; channel = 650; { char *p; if ((p=strchr(optarg, ':'))) { *p = '\0'; channel = atoi(++p); } } { int n; if (sscanf(optarg, "%d.%d.%d.%d", &n, &n, &n, &n) != 4) fprintf(stderr, "Please use dotted quad notation.\n"); } break; case 'F': fprintf(stderr,"Option -%c is deprecated, use -%c instead\n",'F','U'); optarg = "none"; case 'U': /* handle severed optional option argument */ if (!optarg && argc > optind && argv[optind][0] != '-') { optarg = argv[optind]; optind++; } if (parse_uuid(optarg, &use_uuid, &use_uuid_len) < 0) fprintf(stderr, "Unknown UUID %s\n", optarg); break; case 'H': use_conn=0; break; case 'S': use_path=0; break; case 'T': timeout = atoi(optarg); if (timeout < 0) { fprintf(stderr, "timeout can't be less than 0. Using default.\n"); timeout = 20; } break; case 'L': /* handle severed optional option argument */ if (!optarg && argc > optind && argv[optind][0] != '-') { optarg = argv[optind]; optind++; } if (cli_connect() >= 0) { /* List folder */ stat_entry_t *ent; void *dir = obexftp_opendir(cli, optarg); while ((ent = obexftp_readdir(dir)) != NULL) { stat_entry_t *st; st = obexftp_stat(cli, ent->name); if (!st) continue; printf("%d %s%s\n", st->size, ent->name, ent->mode&S_IFDIR?"/":""); } obexftp_closedir(dir); } most_recent_cmd = c; break; case 'l': /* handle severed optional option argument */ if (!optarg && argc > optind && argv[optind][0] != '-') { optarg = argv[optind]; optind++; } if (cli_connect() >= 0) { /* List folder */ ret = obexftp_list(cli, NULL, optarg); } most_recent_cmd = c; break; case 'c': if (cli_connect() >= 0) { /* Change dir */ ret = obexftp_setpath(cli, optarg, 0); } most_recent_cmd = c; break; case 'C': if (cli_connect() >= 0) { /* Change or Make dir */ ret = obexftp_setpath(cli, optarg, 1); } most_recent_cmd = c; break; case 'o': output_file = optarg; break; case 'g': case 'G': if (cli_connect() >= 0) { char *p; /* basename or output_file */ if ((p = strrchr(optarg, '/')) != NULL) p++; else p = optarg; if (output_file) p = output_file; /* Get file */ ret = obexftp_get(cli, p, optarg); if (ret > 0 && c == 'G') ret = obexftp_del(cli, optarg); output_file = NULL; } most_recent_cmd = c; break; case 'p': if (cli_connect() >= 0) { char *p; /* basename or output_file */ if ((p = strrchr(optarg, '/')) != NULL) p++; else p = optarg; if (output_file) p = output_file; /* Send file */ ret = obexftp_put_file(cli, optarg, p); output_file = NULL; } most_recent_cmd = c; break; case 'k': if (cli_connect() >= 0) { /* Delete file */ ret = obexftp_del(cli, optarg); } most_recent_cmd = c; break; case 'X': if (cli_connect() >= 0) { /* Get capabilities */ ret = obexftp_get_capability(cli, optarg, 0); } most_recent_cmd = 'h'; // not really break; case 'P': fprintf(stderr,"Option -%c is deprecated, use -%c instead\n",'P','Y'); case 'Y': if (cli == NULL) probe_device(); fprintf(stderr, "No other transfer options allowed with --probe\n"); break; case 'x': if (cli_connect() >= 0) { /* for S65 */ (void) obexftp_disconnect (cli); (void) obexftp_connect_uuid (cli, device, channel, UUID_S45, sizeof(UUID_S45)); /* Retrieve Infos */ (void) obexftp_info(cli, 0x01); (void) obexftp_info(cli, 0x02); } most_recent_cmd = 'h'; // not really break; case 'm': most_recent_cmd = c; if (move_src == NULL) { move_src = optarg; break; } if (cli_connect() >= 0) { /* Rename a file */ ret = obexftp_rename(cli, move_src, optarg); } move_src = NULL; break; case 'v': verbose++; break; case 'V': printf("ObexFTP %s\n", VERSION); most_recent_cmd = 'h'; // not really break; case 'h': printf("ObexFTP %s\n", VERSION); printf("Usage: %s [ -i " #ifdef HAVE_BLUETOOTH "| -b [-B ] [-d ]" #endif #ifdef HAVE_USB "| -u " #endif "| -t | -N ]\n" "[-c ...] [-C ] [-l []]\n" "[-g ...] [-p ...] [-k ...] [-x] [-m ...]\n" "Transfer files from/to Mobile Equipment.\n" "Copyright (c) 2002-2004 Christian W. Zuckschwerdt\n" "\n" " -i, --irda connect using IrDA transport (default)\n" #ifdef HAVE_BLUETOOTH " -b, --bluetooth [] use or search a bluetooth device\n" " -B, --channel use this bluetooth channel when connecting\n" " -d, --hci use source device with this address or number\n" #endif #ifdef HAVE_USB " -u, --usb [] connect to a usb interface or list interfaces\n" #endif " -t, --tty connect to this tty using a custom transport\n" " -n, --network connect to this host\n\n" " -U, --uuid use given uuid (none, FBS, IRMC, S45, SHARP)\n" " -H, --noconn suppress connection ids (no conn header)\n" " -S, --nopath dont use setpaths (use path as filename)\n" " -T, --timeout timeout transfer if no accept/reject received\n\n" " -c, --chdir chdir\n" " -C, --mkdir mkdir and chdir\n" " -l, --list [] list current/given folder\n" " -o, --output specify the target file name\n" " get and put always specify the remote name.\n" " -g, --get fetch files\n" " -G, --getdelete fetch and delete (move) files \n" " -p, --put send files\n" " -k, --delete delete files\n\n" " -X, --capability retrieve capability object\n" " -Y, --probe probe and report device characteristics\n" " -x, --info retrieve infos (Siemens)\n" " -m, --move move files (Siemens)\n\n" " -v, --verbose verbose messages\n" " -V, --version print version info\n" " -h, --help, --usage this help text\n" "\n", argv[0]); most_recent_cmd = 'h'; // not really break; default: printf("Try `%s --help' for more information.\n", argv[0]); } if (ret < 0) printf("The operation failed with return code %d\n", -ret); } if (most_recent_cmd == 0) fprintf(stderr, "Nothing to do. Use --help for help.\n"); if (optind < argc) { fprintf(stderr, "non-option ARGV-elements: "); while (optind < argc) fprintf(stderr, "%s ", argv[optind++]); fprintf(stderr, "\n"); } cli_disconnect (); exit (-ret); } obexftp-0.24.2-Source/bfb/000755 001750 001750 00000000000 12701545532 016353 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/bfb/irda_fcs.c000644 001750 001750 00000001044 12273436533 020274 0ustar00hendrikhendrik000000 000000 /* Taken with renamed variables/function from * "A Painless Guide to CRC Error Detection Algorithms", chapter 18. * * This code is in the public domain. */ #include "irda_fcs.h" /* For the values see IrPHY specification, chapter 5.3.1 */ #define FCS_INIT 0xFFFF #define FCS_XOROT 0xFFFF extern unsigned short crctable[256]; unsigned short irda_fcs (unsigned char *blk_adr, unsigned long blk_len) { unsigned short fcs = FCS_INIT; while (blk_len--) fcs = crctable[(fcs ^ *blk_adr++) & 0xFFL] ^ (fcs >> 8); return fcs ^ FCS_XOROT; } obexftp-0.24.2-Source/bfb/crctable.c000644 001750 001750 00000017714 12273436424 020313 0ustar00hendrikhendrik000000 000000 /******************************************************************************/ /* Start of crctable.c */ /******************************************************************************/ /* */ /* Author : Ross Williams (ross@guest.adelaide.edu.au.). */ /* Date : 3 June 1993. */ /* Version : 1.0. */ /* Status : Public domain. */ /* */ /* Description : This program writes a CRC lookup table (suitable for */ /* inclusion in a C program) to a designated output file. The program can be */ /* statically configured to produce any table covered by the Rocksoft^tm */ /* Model CRC Algorithm. For more information on the Rocksoft^tm Model CRC */ /* Algorithm, see the document titled "A Painless Guide to CRC Error */ /* Detection Algorithms" by Ross Williams (ross@guest.adelaide.edu.au.). This */ /* document is likely to be in "ftp.adelaide.edu.au/pub/rocksoft". */ /* */ /* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia. */ /* */ /******************************************************************************/ #include #include #include "crcmodel.h" /******************************************************************************/ /* TABLE PARAMETERS */ /* ================ */ /* The following parameters entirely determine the table to be generated. You */ /* should need to modify only the definitions in this section before running */ /* this program. */ /* */ /* TB_FILE is the name of the output file. */ /* TB_WIDTH is the table width in bytes (either 2 or 4). */ /* TB_POLY is the "polynomial", which must be TB_WIDTH bytes wide. */ /* TB_REVER indicates whether the table is to be reversed (reflected). */ /* */ /* Example: */ /* */ /* #define TB_FILE "crctable.out" */ /* #define TB_WIDTH 2 */ /* #define TB_POLY 0x8005L */ /* #define TB_REVER TRUE */ #define TB_FILE "irda_fcs_table.c" #define TB_WIDTH 2 #define TB_POLY ((1 << 12)|(1 << 5)|(1 << 0)) #define TB_REVER TRUE /******************************************************************************/ /* Miscellaneous definitions. */ #define LOCAL static FILE *outfile; #define WR(X) fprintf(outfile,(X)) #define WP(X,Y) fprintf(outfile,(X),(Y)) /******************************************************************************/ LOCAL void chk_err P_((char *)); LOCAL void chk_err (mess) /* If mess is non-empty, write it out and abort. Otherwise, check the error */ /* status of outfile and abort if an error has occurred. */ char *mess; { if (mess[0] != 0) { printf("%s\n",mess); exit(EXIT_FAILURE); } if (ferror(outfile)) { perror("chk_err"); exit(EXIT_FAILURE); } } /******************************************************************************/ LOCAL void chkparam P_((void)); LOCAL void chkparam () { if ((TB_WIDTH != 2) && (TB_WIDTH != 4)) chk_err("chkparam: Width parameter is illegal."); if ((TB_WIDTH == 2) && (TB_POLY & 0xFFFF0000L)) chk_err("chkparam: Poly parameter is too wide."); if ((TB_REVER != FALSE) && (TB_REVER != TRUE)) chk_err("chkparam: Reverse parameter is not boolean."); } /******************************************************************************/ LOCAL void gentable P_((void)); LOCAL void gentable () { WR("/*****************************************************************/\n"); WR("/* */\n"); WR("/* CRC LOOKUP TABLE */\n"); WR("/* ================ */\n"); WR("/* The following CRC lookup table was generated automagically */\n"); WR("/* by the Rocksoft^tm Model CRC Algorithm Table Generation */\n"); WR("/* Program V1.0 using the following model parameters: */\n"); WR("/* */\n"); WP("/* Width : %1lu bytes. */\n", (ulong) TB_WIDTH); if (TB_WIDTH == 2) WP("/* Poly : 0x%04lX */\n", (ulong) TB_POLY); else WP("/* Poly : 0x%08lXL */\n", (ulong) TB_POLY); if (TB_REVER) WR("/* Reverse : TRUE. */\n"); else WR("/* Reverse : FALSE. */\n"); WR("/* */\n"); WR("/* For more information on the Rocksoft^tm Model CRC Algorithm, */\n"); WR("/* see the document titled \"A Painless Guide to CRC Error */\n"); WR("/* Detection Algorithms\" by Ross Williams */\n"); WR("/* (ross@guest.adelaide.edu.au.). This document is likely to be */\n"); WR("/* in the FTP archive \"ftp.adelaide.edu.au/pub/rocksoft\". */\n"); WR("/* */\n"); WR("/*****************************************************************/\n"); WR("\n"); switch (TB_WIDTH) { case 2: WR("unsigned short crctable[256] =\n{\n"); break; case 4: WR("unsigned long crctable[256] =\n{\n"); break; default: chk_err("gentable: TB_WIDTH is invalid."); } chk_err(""); { int i; cm_t cm; char *form = (TB_WIDTH==2) ? "0x%04lX" : "0x%08lXL"; int perline = (TB_WIDTH==2) ? 8 : 4; cm.cm_width = TB_WIDTH*8; cm.cm_poly = TB_POLY; cm.cm_refin = TB_REVER; for (i=0; i<256; i++) { WR(" "); WP(form,(ulong) cm_tab(&cm,i)); if (i != 255) WR(","); if (((i+1) % perline) == 0) WR("\n"); chk_err(""); } WR("};\n"); WR("\n"); WR("/*****************************************************************/\n"); WR("/* End of CRC Lookup Table */\n"); WR("/*****************************************************************/\n"); chk_err(""); } } /******************************************************************************/ int main (int argc, char **argv) { printf("\n"); printf("Rocksoft^tm Model CRC Algorithm Table Generation Program V1.0\n"); printf("-------------------------------------------------------------\n"); printf("Output file is \"%s\".\n",TB_FILE); chkparam(); outfile = fopen(TB_FILE,"w"); chk_err(""); gentable(); if (fclose(outfile) != 0) chk_err("main: Couldn't close output file."); printf("\nSUCCESS: The table has been successfully written.\n"); return 0; } /******************************************************************************/ /* End of crctable.c */ /******************************************************************************/ obexftp-0.24.2-Source/bfb/CMakeLists.txt000644 001750 001750 00000001573 12311311306 021104 0ustar00hendrikhendrik000000 000000 set ( bfb_SOURCES bfb.c bfb_io.c irda_fcs.c ${CMAKE_CURRENT_BINARY_DIR}/irda_fcs_table.c ) set ( bfb_PUBLIC_HEADERS bfb.h bfb_io.h ) set ( bfb_HEADERS irda_fcs.h ${bfb_PUBLIC_HEADERS} ) add_executable (crctable crcmodel.h crcmodel.c crctable.c ) add_custom_command ( OUTPUT irda_fcs_table.c COMMAND crctable ) add_library ( bfb ${bfb_SOURCES} ${bfb_HEADERS} ) set_property ( TARGET bfb PROPERTY VERSION 0.0.6 ) set_property ( TARGET bfb PROPERTY SOVERSION 1 ) set_property ( TARGET bfb PROPERTY PUBLIC_HEADER ${bfb_PUBLIC_HEADERS} ) install ( TARGETS bfb RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT library LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/bfb COMPONENT devel ) obexftp-0.24.2-Source/bfb/bfb.c000644 001750 001750 00000027644 12656174303 017270 0ustar00hendrikhendrik000000 000000 /** \file bfb/bfb.c BFB transport encapsulation (used for Siemens mobile equipment). ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #include #include #include #include #include /* htons */ #ifdef _WIN32 #include #include /* for endianess */ #else #include #endif #include "irda_fcs.h" #include "bfb.h" #include "bfb_io.h" #include /* Provide convenience macros for handling structure * fields through their offsets. */ #define STRUCT_OFFSET(struct_type, member) \ ((uint64_t) ((char*) &((struct_type*) 0)->member)) #define STRUCT_MEMBER_P(struct_p, struct_offset) \ ((void *) ((char*) (struct_p) + (uint64_t) (struct_offset))) #define STRUCT_MEMBER(member_type, struct_p, struct_offset) \ (*(member_type*) STRUCT_MEMBER_P ((struct_p), (struct_offset))) /* mobile need little-endianess always */ /* Solaris: _LITTLE_ENDIAN / _BIG_ENDIAN */ /* Linux: */ #if (BYTE_ORDER == LITTLE_ENDIAN) || defined (_LITTLE_ENDIAN) #define htoms(A) (A) #define htoml(A) (A) #define mtohs(A) (A) #define mtohl(A) (A) #elif (BYTE_ORDER == BIG_ENDIAN) || defined (_BIG_ENDIAN) #define htoms(A) ((((uint16_t)(A) & 0xff00) >> 8) | \ (((uint16_t)(A) & 0x00ff) << 8)) #define htoml(A) ((((uint32_t)(A) & 0xff000000) >> 24) | \ (((uint32_t)(A) & 0x00ff0000) >> 8) | \ (((uint32_t)(A) & 0x0000ff00) << 8) | \ (((uint32_t)(A) & 0x000000ff) << 24)) #define mtohs htoms #define mtohl htoml #else #error "BYTE_ORDER needs to be either BIG_ENDIAN or LITTLE_ENDIAN." #endif /** Returns the whole buffer folded with xor. */ uint8_t bfb_checksum(uint8_t *data, int len) { int i; uint8_t chk = 0; for (i=0; i < len; i++) chk ^= data[i]; return chk; } /** Stuff data frame into serial cable encapsulation. buffer needs to be of at leaset len+7 size Type 0x01: "prepare" command. Type 0x02: first transmission in a row. Type 0x03: continued transmission. seq needs to be incremented afterwards. */ int bfb_stuff_data(uint8_t *buffer, uint8_t type, uint8_t *data, uint16_t len, uint8_t seq) { union { uint16_t value; uint8_t bytes[2]; } fcs; /* special case: "attention" packet */ if (type == 1) { buffer[0] = 0x01; buffer[1] = ~buffer[0]; return 2; } /* error */ if (type != 2 && type != 3) { buffer[0] = 0x00; /* just terminate the buffer */ return 0; } buffer[0] = type; buffer[1] = ~buffer[0]; buffer[2] = seq; fcs.value = htons(len); buffer[3] = fcs.bytes[0]; buffer[4] = fcs.bytes[1]; /* copy data */ memcpy(buffer+5, data, len); /* gen CRC */ fcs.value = irda_fcs(buffer+2, len+3); /* append CRC to packet */ /* fcs.value = htons(fcs.value); */ buffer[len+5] = fcs.bytes[0]; buffer[len+6] = fcs.bytes[1]; return len+7; } /** Send a cmd, subcmd packet, add chk (no parameters). */ int bfb_write_subcmd(fd_t fd, uint8_t type, uint8_t subtype) { uint8_t buffer[2]; buffer[0] = subtype; buffer[1] = bfb_checksum(buffer, 1); return bfb_write_packets(fd, type, buffer, 2); } /** Send a cmd, subcmd packet. */ int bfb_write_subcmd0(fd_t fd, uint8_t type, uint8_t subtype) { return bfb_write_packets(fd, type, &subtype, 1); } /** Send a cmd, subcmd, data packet. */ int bfb_write_subcmd8(fd_t fd, uint8_t type, uint8_t subtype, uint8_t p1) { uint8_t buffer[2]; buffer[0] = subtype; buffer[1] = p1; return bfb_write_packets(fd, type, buffer, 2); } /** Send a cmd, subcmd packet, add chk (one word parameter). */ int bfb_write_subcmd1(fd_t fd, uint8_t type, uint8_t subtype, uint16_t p1) { uint8_t buffer[4]; buffer[0] = subtype; p1 = htoms(p1); /* mobile need little-endianess always */ buffer[1] = STRUCT_MEMBER(uint8_t, &p1, 0); buffer[2] = STRUCT_MEMBER(uint8_t, &p1, 1); buffer[3] = bfb_checksum(buffer, 3); DEBUG(3, "buf: %x %x %x %x\n", buffer[0], buffer[1], buffer[2], buffer[3]); return bfb_write_packets(fd, type, buffer, 4); } /** Send a cmd, subcmd packet, add chk (two word parameter). */ int bfb_write_subcmd2(fd_t fd, uint8_t type, uint8_t subtype, uint16_t p1, uint16_t p2) { uint8_t buffer[6]; buffer[0] = subtype; p1 = htoms(p1); /* mobile need little-endianess always */ buffer[1] = STRUCT_MEMBER(uint8_t, &p1, 0); buffer[2] = STRUCT_MEMBER(uint8_t, &p1, 1); p2 = htoms(p2); /* mobile need little-endianess always */ buffer[3] = STRUCT_MEMBER(uint8_t, &p2, 0); buffer[4] = STRUCT_MEMBER(uint8_t, &p2, 1); buffer[5] = bfb_checksum(buffer, 5); DEBUG(3, "buf: %x %x %x %x %x %x\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5]); return bfb_write_packets(fd, type, buffer, 6); } /** Send a cmd, subcmd packet, add chk (three word parameter). */ int bfb_write_subcmd3(fd_t fd, uint8_t type, uint8_t subtype, uint16_t p1, uint16_t p2, uint16_t p3) { uint8_t buffer[8]; buffer[0] = subtype; p1 = htoms(p1); /* mobile need little-endianess always */ buffer[1] = STRUCT_MEMBER(uint8_t, &p1, 0); buffer[2] = STRUCT_MEMBER(uint8_t, &p1, 1); p2 = htoms(p2); /* mobile need little-endianess always */ buffer[3] = STRUCT_MEMBER(uint8_t, &p2, 0); buffer[4] = STRUCT_MEMBER(uint8_t, &p2, 1); p3 = htoms(p3); /* mobile need little-endianess always */ buffer[5] = STRUCT_MEMBER(uint8_t, &p3, 0); buffer[6] = STRUCT_MEMBER(uint8_t, &p3, 1); buffer[7] = bfb_checksum(buffer, 7); DEBUG(3, "buf: %x %x %x %x %x %x %x %x\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]); return bfb_write_packets(fd, type, buffer, 8); } /** Send a cmd, subcmd packet, add long, word parameter. */ int bfb_write_subcmd_lw(fd_t fd, uint8_t type, uint8_t subtype, uint32_t p1, uint16_t p2) { uint8_t buffer[8]; buffer[0] = subtype; p1 = htoml(p1); /* mobile need little-endianess always */ buffer[1] = STRUCT_MEMBER(uint8_t, &p1, 0); buffer[2] = STRUCT_MEMBER(uint8_t, &p1, 1); buffer[3] = STRUCT_MEMBER(uint8_t, &p1, 2); buffer[4] = STRUCT_MEMBER(uint8_t, &p1, 3); p2 = htoms(p2); /* mobile need little-endianess always */ buffer[5] = STRUCT_MEMBER(uint8_t, &p2, 0); buffer[6] = STRUCT_MEMBER(uint8_t, &p2, 1); buffer[7] = bfb_checksum(buffer, 7); DEBUG(3, "buf: %02x %02x %02x %02x %02x %02x %02x\n", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6]); return bfb_write_packets(fd, type, buffer, 7); /* no chk? */ } /** Send actual packets. Patch from Jorge Ventura to handle EAGAIN from write. */ int bfb_write_packets(fd_t fd, uint8_t type, uint8_t *buffer, int length) { bfb_frame_t *frame; int i; int l; int actual; #ifdef _WIN32 return_val_if_fail (fd != INVALID_HANDLE_VALUE, FALSE); #else return_val_if_fail (fd > 0, FALSE); #endif /* alloc frame buffer */ frame = malloc((length > MAX_PACKET_DATA ? MAX_PACKET_DATA : length) + sizeof (bfb_frame_t)); if (frame == NULL) return -1; for(i=0; i MAX_PACKET_DATA) l = MAX_PACKET_DATA; frame->type = type; frame->len = l; frame->chk = frame->type ^ frame->len; memcpy(frame->payload, &buffer[i], l); actual = bfb_io_write(fd, frame, l + sizeof (bfb_frame_t), 1); DEBUG(3, "%s() Wrote %d bytes (expected %lu)\n", __func__, actual, (unsigned long)(l + sizeof (bfb_frame_t))); if (actual < (int)(l + sizeof(bfb_frame_t))) { DEBUG(1, "%s() Write failed\n", __func__); free(frame); return -1; } } free(frame); return i / MAX_PACKET_DATA; } /** Stuff data into packet buffers and send all packets. */ int bfb_send_data(fd_t fd, uint8_t type, uint8_t *data, uint16_t length, uint8_t seq) { uint8_t *buffer; int actual; buffer = malloc(length + 7); if (buffer == NULL) return -1; actual = bfb_stuff_data(buffer, type, data, length, seq); DEBUG(3, "%s() Stuffed %d bytes\n", __func__, actual); actual = bfb_write_packets(fd, BFB_FRAME_DATA, buffer, actual); DEBUG(3, "%s() Wrote %d packets\n", __func__, actual); free(buffer); return actual; } /** Retrieve actual packets. */ /*@null@*/ bfb_frame_t *bfb_read_packets(uint8_t *buffer, int *length) { bfb_frame_t *frame; int l; DEBUG(3, "%s() \n", __func__); if (*length < 0) { DEBUG(1, "%s() Wrong length?\n", __func__); return NULL; } if (*length == 0) { DEBUG(1, "%s() No packet?\n", __func__); return NULL; } if (*length < (int) sizeof(bfb_frame_t)) { DEBUG(1, "%s() Short packet?\n", __func__); return NULL; } /* temp frame */ frame = (bfb_frame_t *)buffer; if ((frame->type ^ frame->len) != frame->chk) { DEBUG(1, "%s() Header error?\n", __func__); DEBUGBUFFER(buffer, *length); return NULL; } if (*length < frame->len + (int) sizeof(bfb_frame_t)) { DEBUG(2, "%s() Need more data?\n", __func__); return NULL; } /* copy frame from buffer */ l = sizeof(bfb_frame_t) + frame->len; frame = malloc(l); if (frame == NULL) return NULL; memcpy(frame, buffer, l); /* remove frame from buffer */ *length -= l; memmove(buffer, &buffer[l], *length); DEBUG(3, "%s() Packet 0x%02x (%d bytes)\n", __func__, frame->type, frame->len); return frame; } /** Append BFB frame to a data buffer. */ int bfb_assemble_data(bfb_data_t **data, int *size, int *len, bfb_frame_t *frame) { bfb_data_t *tmp; int l; DEBUG(3, "%s() \n", __func__); if (frame->type != BFB_FRAME_DATA) { DEBUG(1, "%s() Wrong frame type (0x%02x)?\n", __func__, frame->type); return -1; } /* temp data */ tmp = (bfb_data_t *)frame->payload; if ((*len == 0) && (tmp->cmd == BFB_DATA_ACK)) { DEBUG(3, "%s() Skipping ack\n", __func__); return 0; } /* copy frame from buffer */ DEBUG(3, "%s() data: %d + frame: %d\n", __func__, *len, frame->len); l = *len + frame->len; if (l > *size) { DEBUG(1, "%s() data buffer to small, realloc'ing\n", __func__); *data = realloc(*data, l); *size = l; } /* memcpy(ret, *data, *len); */ memcpy(&((uint8_t *)*data)[*len], frame->payload, frame->len); /* free(*data); */ *len = l; return 1; } /** Check if data buffer is complete and valid. */ int bfb_check_data(bfb_data_t *data, int len) { union { uint16_t value; uint8_t bytes[2]; } l; uint8_t inv_chk; DEBUG(3, "%s() \n", __func__); if (data == NULL) return -1; if (len < (int) sizeof(bfb_data_t)) return 0; DEBUG(3, "%s() cmd: 0x%02x, chk: 0x%02x, seq: %d\n", __func__, data->cmd, data->chk, data->seq); inv_chk = ~data->chk; if (data->cmd != inv_chk) { DEBUG(1, "%s() Broken data?\n", __func__); DEBUGBUFFER(data, len); } if ((data->cmd != BFB_DATA_FIRST) && (data->cmd != BFB_DATA_NEXT)) { DEBUG(1, "%s() Wrong data type (0x%02x)?\n", __func__, data->cmd); return -1; } l.bytes[0] = data->len0; l.bytes[1] = data->len1; l.value = htons(l.value); DEBUG(3, "%s() fragment size %d, payload %lu of indicated %d\n", __func__, len, (unsigned long)(len - sizeof(bfb_data_t)), l.value); if (len-(int)sizeof(bfb_data_t) < (int)(l.value) + /*crc*/ 2) return 0; /* check CRC */ l.value = irda_fcs((unsigned char *)data + 2, len - 4); if ((((uint8_t *)data)[len-2] != l.bytes[0]) || (((uint8_t *)data)[len-1] != l.bytes[1])) { DEBUG(1, "%s() CRC-ERROR %02x %02x vs %02x %02x\n", __func__, ((uint8_t *)data)[len-2], ((uint8_t *)data)[len-1], l.bytes[0], l.bytes[1]); } DEBUG(2, "%s() data ready!\n", __func__); return 1; } obexftp-0.24.2-Source/bfb/bfb.h000644 001750 001750 00000007136 12311311306 017247 0ustar00hendrikhendrik000000 000000 /** \file bfb/bfb.h BFB transport encapsulation (used for Siemens mobile equipment). ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef BFB_H #define BFB_H #include #ifdef __cplusplus extern "C" { #endif #ifndef fd_t_defined #ifdef _WIN32 #include typedef HANDLE fd_t; #define fd_t_defined #else typedef int fd_t; #define fd_t_defined #endif #endif #pragma pack(1) typedef struct { uint8_t type; uint8_t len; uint8_t chk; uint8_t payload[0]; /* ... up to 32 */ /* uint8_t xor; ? */ } bfb_frame_t; #pragma pack() #pragma pack(1) typedef struct { uint8_t cmd; uint8_t chk; uint8_t seq; uint8_t len0; uint8_t len1; uint8_t data[0]; /* ... up to 518 ? */ /* uint16_t crc; */ } bfb_data_t; #pragma pack() #define BFB_FRAME_CONNECT 0x02 /* ^B */ #define BFB_FRAME_INTERFACE 0x01 /* ^A */ #define BFB_FRAME_KEY 0x05 /* ^E */ #define BFB_FRAME_AT 0x06 /* ^F */ #define BFB_FRAME_EEPROM 0x14 /* ^N */ #define BFB_FRAME_DATA 0x16 /* ^P */ #define BFB_CONNECT_HELLO 0x14 /* ^N */ #define BFB_CONNECT_HELLO_ACK 0xaa #define BFB_KEY_PRESS 0x06 /* ^F */ #define MAX_PACKET_DATA 32 #define BFB_DATA_ACK 0x01 /* aka ok */ #define BFB_DATA_FIRST 0x02 /* first transmission in a row */ #define BFB_DATA_NEXT 0x03 /* continued transmission */ uint8_t bfb_checksum(uint8_t *data, int len); int bfb_write_subcmd(fd_t fd, uint8_t type, uint8_t subtype); int bfb_write_subcmd0(fd_t fd, uint8_t type, uint8_t subtype); int bfb_write_subcmd8(fd_t fd, uint8_t type, uint8_t subtype, uint8_t p1); int bfb_write_subcmd1(fd_t fd, uint8_t type, uint8_t subtype, uint16_t p1); int bfb_write_subcmd2(fd_t fd, uint8_t type, uint8_t subtype, uint16_t p1, uint16_t p2); int bfb_write_subcmd3(fd_t fd, uint8_t type, uint8_t subtype, uint16_t p1, uint16_t p2, uint16_t p3); int bfb_write_subcmd_lw(fd_t fd, uint8_t type, uint8_t subtype, uint32_t p1, uint16_t p2); int bfb_stuff_data(/*@out@*/ uint8_t *buffer, uint8_t type, uint8_t *data, uint16_t len, uint8_t seq); int bfb_write_packets(fd_t fd, uint8_t type, uint8_t *buffer, int length); #define bfb_write_at(fd, data) \ bfb_write_packets(fd, BFB_FRAME_AT, (uint8_t *)data, strlen(data)) #define bfb_write_key(fd, data) \ bfb_write_subcmd8(fd, BFB_FRAME_KEY, BFB_KEY_PRESS, data) int bfb_send_data(fd_t fd, uint8_t type, uint8_t *data, uint16_t length, uint8_t seq); #define bfb_send_ack(fd) \ bfb_send_data(fd, BFB_DATA_ACK, NULL, 0, 0) #define bfb_send_first(fd, data, length) \ bfb_send_data(fd, BFB_DATA_FIRST, data, length, 0) #define bfb_send_next(fd, data, length, seq) \ bfb_send_data(fd, BFB_DATA_NEXT, data, length, seq) /*@null@*/ bfb_frame_t * bfb_read_packets(uint8_t *buffer, int *length); int bfb_assemble_data(/*@null@*/ /*@out@*/ bfb_data_t **data, int *size, int *len, bfb_frame_t *frame); int bfb_check_data(bfb_data_t *data, int len); #ifdef __cplusplus } #endif #endif /* BFB_H */ obexftp-0.24.2-Source/bfb/bfb_io.c000644 001750 001750 00000010615 12656173012 017741 0ustar00hendrikhendrik000000 000000 /** \file bfb/bfb_io.c BFB transport encapsulation (for Siemens mobile equipment). ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #else #include #include #define INVALID_HANDLE_VALUE -1 #endif #include "bfb.h" #include "bfb_io.h" #include int bfb_io_write(fd_t fd, const void *buffer, int length, int timeout) { struct timeval time; fd_set fds; int rc; if (fd == INVALID_HANDLE_VALUE) { DEBUG(1, "%s() Error file handle invalid\n", __func__); return -1; } /* select setup */ FD_ZERO(&fds); FD_SET(fd, &fds); /* Set time limit. */ time.tv_sec = timeout; time.tv_usec = 0; rc = select(fd+1, NULL, &fds, NULL, &time); if ( rc > 0) { #ifdef _WIN32 DWORD bytes; DEBUG(3, "%s() WriteFile\n", __func__); if(!WriteFile(fd, buffer, length, &bytes, NULL)) DEBUG(1, "%s() Write error: %ld\n", __func__, bytes); return bytes; #else int bytes; bytes = write(fd, buffer, length); if (bytes < length) DEBUG(1, "%s() Error short write (%d / %d)\n", __func__, bytes, length); if (bytes < 0) DEBUG(1, "%s() Error writing to port\n", __func__); return bytes; #endif } else { /* ! rc > 0*/ DEBUG(1, "%s() Select failed\n", __func__); return 0; } } int bfb_io_read(fd_t fd, void *buffer, int length, int timeout) { #ifdef _WIN32 DWORD bytes; DEBUG(3, "%s() ReadFile\n", __func__); return_val_if_fail (fd != INVALID_HANDLE_VALUE, -1); if (!ReadFile(fd, buffer, length, &bytes, NULL)) { DEBUG(2, "%s() Read error: %ld\n", __func__, bytes); } return bytes; #else struct timeval time; fd_set fdset; int actual; return_val_if_fail (fd > 0, -1); time.tv_sec = timeout; time.tv_usec = 0; FD_ZERO(&fdset); FD_SET(fd, &fdset); if(select(fd+1, &fdset, NULL, NULL, &time)) { actual = read(fd, buffer, length); if (actual < 0) { DEBUG(2, "%s() Read error: %d\n", __func__, actual); } return actual; } else { DEBUG(1, "%s() No data (timeout: %d)\n", __func__, timeout); return 0; } #endif } int bfb_io_init(fd_t fd) { int actual; int tries=3; bfb_frame_t *frame = NULL; uint8_t rspbuf[200]; int rsplen; uint8_t init_magic = BFB_CONNECT_HELLO; uint8_t init_magic2 = BFB_CONNECT_HELLO_ACK; /* uint8_t speed115200[] = {0xc0,'1','1','5','2','0','0',0x13,0xd2,0x2b}; uint8_t sifs[] = {'a','t','^','s','i','f','s',0x13}; */ #ifdef _WIN32 return_val_if_fail (fd != INVALID_HANDLE_VALUE, FALSE); #else return_val_if_fail (fd > 0, FALSE); #endif while (!frame && tries-- > 0) { actual = bfb_write_packets (fd, BFB_FRAME_CONNECT, &init_magic, sizeof(init_magic)); DEBUG(2, "%s() Wrote %d packets\n", __func__, actual); if (actual < 1) { DEBUG(1, "BFB port error\n"); return FALSE; } rsplen = 0; while (!frame && actual > 0) { actual = bfb_io_read(fd, &rspbuf[rsplen], sizeof(rspbuf)-rsplen, 2); DEBUG(2, "%s() Read %d bytes\n", __func__, actual); if (actual < 0) { DEBUG(1, "BFB read error\n"); return FALSE; } if (actual == 0) { DEBUG(1, "BFB read timeout\n"); } rsplen += actual; frame = bfb_read_packets(rspbuf, &rsplen); DEBUG(2, "%s() Unstuffed, %d bytes remaining\n", __func__, rsplen); } } if (frame == NULL) { DEBUG(1, "BFB init error\n"); return FALSE; } DEBUG(2, "BFB init ok.\n"); if ((frame->len == 2) && (frame->payload[0] == init_magic) && (frame->payload[1] == init_magic2)) { free(frame); return TRUE; } DEBUG(1, "Error doing BFB init (%d, %x %x)\n", frame->len, frame->payload[0], frame->payload[1]); free(frame); return FALSE; } obexftp-0.24.2-Source/bfb/bfb_io.h000644 001750 001750 00000002233 12311311306 017727 0ustar00hendrikhendrik000000 000000 /** \file bfb/bfb_io.h BFB protocol IO layer. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef BFB_IO_H #define BFB_IO_H #include "bfb/bfb.h" #ifdef __cplusplus extern "C" { #endif /* Send an BFB init command an check for a valid answer frame */ int bfb_io_init(fd_t fd); int bfb_io_read(fd_t fd, void *buffer, int length, int timeout); int bfb_io_write(fd_t fd, const void *buffer, int length, int timeout); #ifdef __cplusplus } #endif #endif /* BFB_IO_H */ obexftp-0.24.2-Source/bfb/crcmodel.h000644 001750 001750 00000021001 12270033624 020301 0ustar00hendrikhendrik000000 000000 /******************************************************************************/ /* Start of crcmodel.h */ /******************************************************************************/ /* */ /* Author : Ross Williams (ross@guest.adelaide.edu.au.). */ /* Date : 3 June 1993. */ /* Status : Public domain. */ /* */ /* Description : This is the header (.h) file for the reference */ /* implementation of the Rocksoft^tm Model CRC Algorithm. For more */ /* information on the Rocksoft^tm Model CRC Algorithm, see the document */ /* titled "A Painless Guide to CRC Error Detection Algorithms" by Ross */ /* Williams (ross@guest.adelaide.edu.au.). This document is likely to be in */ /* "ftp.adelaide.edu.au/pub/rocksoft". */ /* */ /* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia. */ /* */ /******************************************************************************/ /* */ /* How to Use This Package */ /* ----------------------- */ /* Step 1: Declare a variable of type cm_t. Declare another variable */ /* (p_cm say) of type p_cm_t and initialize it to point to the first */ /* variable (e.g. p_cm_t p_cm = &cm_t). */ /* */ /* Step 2: Assign values to the parameter fields of the structure. */ /* If you don't know what to assign, see the document cited earlier. */ /* For example: */ /* p_cm->cm_width = 16; */ /* p_cm->cm_poly = 0x8005L; */ /* p_cm->cm_init = 0L; */ /* p_cm->cm_refin = TRUE; */ /* p_cm->cm_refot = TRUE; */ /* p_cm->cm_xorot = 0L; */ /* Note: Poly is specified without its top bit (18005 becomes 8005). */ /* Note: Width is one bit less than the raw poly width. */ /* */ /* Step 3: Initialize the instance with a call cm_ini(p_cm); */ /* */ /* Step 4: Process zero or more message bytes by placing zero or more */ /* successive calls to cm_nxt. Example: cm_nxt(p_cm,ch); */ /* */ /* Step 5: Extract the CRC value at any time by calling crc = cm_crc(p_cm); */ /* If the CRC is a 16-bit value, it will be in the bottom 16 bits. */ /* */ /******************************************************************************/ /* */ /* Design Notes */ /* ------------ */ /* PORTABILITY: This package has been coded very conservatively so that */ /* it will run on as many machines as possible. For example, all external */ /* identifiers have been restricted to 6 characters and all internal ones to */ /* 8 characters. The prefix cm (for Crc Model) is used as an attempt to avoid */ /* namespace collisions. This package is endian independent. */ /* */ /* EFFICIENCY: This package (and its interface) is not designed for */ /* speed. The purpose of this package is to act as a well-defined reference */ /* model for the specification of CRC algorithms. If you want speed, cook up */ /* a specific table-driven implementation as described in the document cited */ /* above. This package is designed for validation only; if you have found or */ /* implemented a CRC algorithm and wish to describe it as a set of parameters */ /* to the Rocksoft^tm Model CRC Algorithm, your CRC algorithm implementation */ /* should behave identically to this package under those parameters. */ /* */ /******************************************************************************/ /* The following #ifndef encloses this entire */ /* header file, rendering it indempotent. */ #ifndef CM_DONE #define CM_DONE /******************************************************************************/ /* The following definitions are extracted from my style header file which */ /* would be cumbersome to distribute with this package. The DONE_STYLE is the */ /* idempotence symbol used in my style header file. */ #ifndef DONE_STYLE typedef unsigned long ulong; typedef unsigned bool; typedef unsigned char * p_ubyte_; #ifndef TRUE #define FALSE 0 #define TRUE 1 #endif /* Change to the second definition if you don't have prototypes. */ #define P_(A) A /* #define P_(A) () */ /* Uncomment this definition if you don't have void. */ /* typedef int void; */ #endif /******************************************************************************/ /* CRC Model Abstract Type */ /* ----------------------- */ /* The following type stores the context of an executing instance of the */ /* model algorithm. Most of the fields are model parameters which must be */ /* set before the first initializing call to cm_ini. */ typedef struct { int cm_width; /* Parameter: Width in bits [8,32]. */ ulong cm_poly; /* Parameter: The algorithm's polynomial. */ ulong cm_init; /* Parameter: Initial register value. */ bool cm_refin; /* Parameter: Reflect input bytes? */ bool cm_refot; /* Parameter: Reflect output CRC? */ ulong cm_xorot; /* Parameter: XOR this to output CRC. */ ulong cm_reg; /* Context: Context during execution. */ } cm_t; typedef cm_t *p_cm_t; /******************************************************************************/ /* Functions That Implement The Model */ /* ---------------------------------- */ /* The following functions animate the cm_t abstraction. */ void cm_ini P_((p_cm_t p_cm)); /* Initializes the argument CRC model instance. */ /* All parameter fields must be set before calling this. */ void cm_nxt P_((p_cm_t p_cm,int ch)); /* Processes a single message byte [0,255]. */ void cm_blk P_((p_cm_t p_cm,p_ubyte_ blk_adr,ulong blk_len)); /* Processes a block of message bytes. */ ulong cm_crc P_((p_cm_t p_cm)); /* Returns the CRC value for the message bytes processed so far. */ /******************************************************************************/ /* Functions For Table Calculation */ /* ------------------------------- */ /* The following function can be used to calculate a CRC lookup table. */ /* It can also be used at run-time to create or check static tables. */ ulong cm_tab P_((p_cm_t p_cm,int index)); /* Returns the i'th entry for the lookup table for the specified algorithm. */ /* The function examines the fields cm_width, cm_poly, cm_refin, and the */ /* argument table index in the range [0,255] and returns the table entry in */ /* the bottom cm_width bytes of the return value. */ /******************************************************************************/ /* End of the header file idempotence #ifndef */ #endif /******************************************************************************/ /* End of crcmodel.h */ /******************************************************************************/ obexftp-0.24.2-Source/bfb/crcmodel.c000644 001750 001750 00000012136 12270034063 020303 0ustar00hendrikhendrik000000 000000 /******************************************************************************/ /* Start of crcmodel.c */ /******************************************************************************/ /* */ /* Author : Ross Williams (ross@guest.adelaide.edu.au.). */ /* Date : 3 June 1993. */ /* Status : Public domain. */ /* */ /* Description : This is the implementation (.c) file for the reference */ /* implementation of the Rocksoft^tm Model CRC Algorithm. For more */ /* information on the Rocksoft^tm Model CRC Algorithm, see the document */ /* titled "A Painless Guide to CRC Error Detection Algorithms" by Ross */ /* Williams (ross@guest.adelaide.edu.au.). This document is likely to be in */ /* "ftp.adelaide.edu.au/pub/rocksoft". */ /* */ /* Note: Rocksoft is a trademark of Rocksoft Pty Ltd, Adelaide, Australia. */ /* */ /******************************************************************************/ /* */ /* Implementation Notes */ /* -------------------- */ /* To avoid inconsistencies, the specification of each function is not echoed */ /* here. See the header file for a description of these functions. */ /* This package is light on checking because I want to keep it short and */ /* simple and portable (i.e. it would be too messy to distribute my entire */ /* C culture (e.g. assertions package) with this package. */ /* */ /******************************************************************************/ #include "crcmodel.h" /******************************************************************************/ /* The following definitions make the code more readable. */ #define BITMASK(X) (1L << (X)) #define MASK32 0xFFFFFFFFL #define LOCAL static /******************************************************************************/ LOCAL ulong reflect P_((ulong v,int b)); LOCAL ulong reflect (v,b) /* Returns the value v with the bottom b [0,32] bits reflected. */ /* Example: reflect(0x3e23L,3) == 0x3e26 */ ulong v; int b; { int i; ulong t = v; for (i=0; i>=1; } return v; } /******************************************************************************/ LOCAL ulong widmask P_((p_cm_t)); LOCAL ulong widmask (p_cm) /* Returns a longword whose value is (2^p_cm->cm_width)-1. */ /* The trick is to do this portably (e.g. without doing <<32). */ p_cm_t p_cm; { return (((1L<<(p_cm->cm_width-1))-1L)<<1)|1L; } /******************************************************************************/ void cm_ini (p_cm) p_cm_t p_cm; { p_cm->cm_reg = p_cm->cm_init; } /******************************************************************************/ void cm_nxt (p_cm,ch) p_cm_t p_cm; int ch; { int i; ulong uch = (ulong) ch; ulong topbit = BITMASK(p_cm->cm_width-1); if (p_cm->cm_refin) uch = reflect(uch,8); p_cm->cm_reg ^= (uch << (p_cm->cm_width-8)); for (i=0; i<8; i++) { if (p_cm->cm_reg & topbit) p_cm->cm_reg = (p_cm->cm_reg << 1) ^ p_cm->cm_poly; else p_cm->cm_reg <<= 1; p_cm->cm_reg &= widmask(p_cm); } } /******************************************************************************/ void cm_blk (p_cm,blk_adr,blk_len) p_cm_t p_cm; p_ubyte_ blk_adr; ulong blk_len; { while (blk_len--) cm_nxt(p_cm,*blk_adr++); } /******************************************************************************/ ulong cm_crc (p_cm) p_cm_t p_cm; { if (p_cm->cm_refot) return p_cm->cm_xorot ^ reflect(p_cm->cm_reg,p_cm->cm_width); else return p_cm->cm_xorot ^ p_cm->cm_reg; } /******************************************************************************/ ulong cm_tab (p_cm,index) p_cm_t p_cm; int index; { int i; ulong r; ulong topbit = BITMASK(p_cm->cm_width-1); ulong inbyte = (ulong) index; if (p_cm->cm_refin) inbyte = reflect(inbyte,8); r = inbyte << (p_cm->cm_width-8); for (i=0; i<8; i++) if (r & topbit) r = (r << 1) ^ p_cm->cm_poly; else r<<=1; if (p_cm->cm_refin) r = reflect(r,p_cm->cm_width); return r & widmask(p_cm); } /******************************************************************************/ /* End of crcmodel.c */ /******************************************************************************/ obexftp-0.24.2-Source/bfb/irda_fcs.h000644 001750 001750 00000000112 12270311243 020257 0ustar00hendrikhendrik000000 000000 unsigned short irda_fcs (unsigned char *blk_adr, unsigned long blk_len); obexftp-0.24.2-Source/doc/000755 001750 001750 00000000000 12701545532 016367 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/doc/obexftp.1.txt000644 001750 001750 00000010451 11351376660 020743 0ustar00hendrikhendrik000000 000000 = OBEXFTP(1) == NAME obexftp - Mobile Equipment file transfer tool == SYNOPSIS *obexftp* [_OPTION_] [_COMMANDS_] == DESCRIPTION *obexftp* is used to access files on mobile equipment, i.e. cell phones. With *obexftpd* you can transfer files between any computers using *IrDA*, *Bluetooth* and *TCP/IP*. This tool lets you access the *ObexFTP* library by the means of a command line interface. You might consider using the other means available. E.g. the *ObexFS* filesystem for Linux. == OPTIONS The ordering of options is important. Every command will use the most recent device set. Every file without command switch will apply to the command given most recent. See *EXAMPLES* === Transport Options *-i*, *--irda*:: Connect using the IrDA protocol. This is the default. *-b* _device_, *--bluetooth* _device_:: Connect to this bluetooth device. If the device is not given the first device found will be used. *-B* _number_, *--channel* _number_:: Use this bluetooth channel when connecting. The channel will be discoverd automatically if this option is not used. *-d* _no/address_, *--hci* _no/address_:: Use the bluetooth device referenced by number or address as source device for the connection. *-u* _intf no_, *--usb* _intf no_:: Connect to this usb interface or list all available usb interfaces. *-t* _device_, *--tty* _device_:: Connect to this tty device. *-n* _host_, *--network* _host_:: Connect to this network host. === Compatibility Options *-U* _uuid_, *--uuid* _uuid_:: Select the UUID to connect with. Recognized values are currently "none" needed by some Nokia mobile devices, "FBS" (default) for the normal file browsing service, "IRMC" for IRMC synchronisation and "S45" when connecting to a Siemens Mobile phone via cable or "SHARP" for PCSOFTWARE UUID with Sharp devices. *-H*, *--noconn*:: Suppress connection IDs (i.e. send no connection header to the mobile). *-S*, *--nopath*:: Don't use "setpath" commands (i.e. send the whole path as filename to the mobile). Can be used together with *--noconn* and *--uuid none* to send an OBEX-PUSH. === Setting The File Path *-c* _folder_, *--chdir* _folder_:: Set the mobiles current working directory. *-C* _folder_, *--mkdir* _folder_:: Set the mobiles current working directory. The folder will be created if it doesn't exist. *-l* _folder_, *--list* _folder_:: List a folder. === Sending And Retrieving Files *-o* _path_, *--output* _path_:: Specify the target file name, overriding the implicit local name from *--get* or the implicit remote name from *--put* *-g* _source_, *--get* _source_:: Retrieve files from mobile. *-G* _source_, *--getdelete* _source_:: Retrieve files from mobile and delete them on the mobile *-p* _source_, *--put* _source_:: Send files to the mobile. *-k* _source_, *--delete* _source_:: Delete files from the mobile. === Experimental Extras *-X*, *--capability*:: Retrieve the capability object from the mobile (if available). *-Y*, *--probe*:: Probe and report device characteristics *-x*, *--info*:: Retrieve misc infos from mobile. I.e. memory size and free memory. Siemens specific for now. *-m* _src_ _dest_, *--move* _src_ _dest_:: Move (rename) files on the mobile. Siemens specific for now. === Version Information And Help *-v*, *--verbose*:: Be verbose and give some additional infos. *-V*, *--version*:: Print version string and exit. *-h*, *--help*, *--usage*:: Print short usage instructions. == EXAMPLES To get the directory listing from the first irda device:: *obexftp -i -l* or just *obexftp -l* as IrDA is the default. To get the file bar from directory foo from the first bluetooth device:: *obexftp -b -c foo -g bar* To send the file bar to directory foo with device on first serial port:: *obexftp -t /dev/ttyS0 -c foo -p bar* It is possible to use RfComm (serial port over bluetooth):: *obexftp -t /dev/rfcomm0 -c foo -p bar* And also IrComm (serial port over IrDA):: *obexftp -t /dev/ircomm0 -c foo -p bar* To send the file bar using plain OBEX PUSH:: *obexftp --bluetooth --nopath --noconn --uuid none --put bar* == SEE ALSO obexftpd(1), openobex(3), obexftp(3), multicobex(3), libbfb(3). == BUGS Bugs ? Features ! == NOTES The software has been tested and reported working on at least Siemens, Ericsson, and Nokia phones. == AUTHOR Christian W. Zuckschwerdt obexftp-0.24.2-Source/doc/obexftpd.1.txt000644 001750 001750 00000003002 11351376660 021101 0ustar00hendrikhendrik000000 000000 = OBEXFTPD(1) == NAME obexftpd - Mobile Equipment file transfer server == SYNOPSIS *obexftpd* [_OPTIONS_] [_TRANSPORT_] == DESCRIPTION With *obexftpd* you can set up an obex server on any computers using *IrDA*, *Bluetooth* or *TCP/IP*. Use e.g. *obexftp* or the *ObexFS* to access the files on this server. == OPTIONS The ordering of options is important. The first transport option will start the server. Use basedir and verbose options prior to any transport. See *EXAMPLES* === Transport Options *-i*, *--irda*:: Acceopt connections using the IrDA protocol. *-b*, *--bluetooth*:: Accept connections via bluetooth. *-t* _device_, *--tty* _device_:: Accept connections from this tty device. NOT WORKING! *-n* _host_, *--network* _host_:: Accept connections from the network to this port. === Setting The File Path *-c* _folder_, *--chdir* _folder_:: Set the base directory for the server. === Version Information And Help *-v*, *--verbose*:: Be verbose and give some additional infos. *-V*, *--version*:: Print version string and exit. *-h*, *--help*, *--usage*:: Print short usage instructions. == EXAMPLES Start listening for bluetooth connections and use a safe basedir::: *obexftpd -c /tmp/inbox -b* == SEE ALSO obexftp(1), openobex(3), obexftp(3), multicobex(3), libbfb(3). == BUGS Bugs ? Features ! == NOTES The software has been tested and reported working on at least Siemens, Ericsson, and Nokia phones. == AUTHOR Christian W. Zuckschwerdt Alan Zhang obexftp-0.24.2-Source/doc/CMakeLists.txt000644 001750 001750 00000003503 12270554157 021134 0ustar00hendrikhendrik000000 000000 find_program ( ASCIIDOC_EXECUTABLE asciidoc ) find_program ( XMLTO_EXECUTABLE xmlto ) if ( ASCIIDOC_EXECUTABLE AND XMLTO_EXECUTABLE ) set ( PROGRAMS obexftp obexftpd ) foreach ( program ${PROGRAMS} ) set ( ASCIIDOC_INPUT ${CMAKE_CURRENT_SOURCE_DIR}/${program}.1.txt ) set ( ASCIIDOC_XML_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${program}.1.xml ) set ( ASCIIDOC_HTML_OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${program}.1.html ) add_custom_command ( OUTPUT ${ASCIIDOC_XML_OUTPUT} COMMAND ${ASCIIDOC_EXECUTABLE} ARGS --doctype=manpage --backend=docbook -o ${ASCIIDOC_XML_OUTPUT} ${ASCIIDOC_INPUT} DEPENDS ${ASCIIDOC_INPUT} VERBATIM ) add_custom_command ( OUTPUT ${ASCIIDOC_HTML_OUTPUT} COMMAND ${ASCIIDOC_EXECUTABLE} ARGS --doctype=manpage --backend=xhtml11 -o ${ASCIIDOC_HTML_OUTPUT} ${ASCIIDOC_INPUT} DEPENDS ${ASCIIDOC_INPUT} VERBATIM ) list ( APPEND html_help_files ${ASCIIDOC_HTML_OUTPUT} ) if ( UNIX ) add_custom_command ( OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${program}.1 COMMAND ${XMLTO_EXECUTABLE} ARGS -o ${CMAKE_CURRENT_BINARY_DIR} man ${ASCIIDOC_XML_OUTPUT} DEPENDS ${ASCIIDOC_XML_OUTPUT} VERBATIM ) list ( APPEND manpage_files ${CMAKE_CURRENT_BINARY_DIR}/${program}.1 ) endif ( UNIX ) endforeach ( program ) if ( UNIX ) add_custom_target ( doc ALL DEPENDS ${manpage_files} ) install ( FILES ${manpage_files} DESTINATION ${CMAKE_INSTALL_MANDIR}/man1 COMPONENT documentation OPTIONAL ) endif ( UNIX ) add_custom_target ( htmldoc DEPENDS ${html_help_files} ) install ( FILES ${html_help_files} DESTINATION ${CMAKE_INSTALL_DOCDIR}/html COMPONENT documentation OPTIONAL ) endif ( ASCIIDOC_EXECUTABLE AND XMLTO_EXECUTABLE ) obexftp-0.24.2-Source/examples/000755 001750 001750 00000000000 12701545532 017440 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/examples/README_obexftpbackup000755 001750 001750 00000002465 11351376660 023253 0ustar00hendrikhendrik000000 000000 ------------- obexftpbackup 2.0 ------------- A while ago I wrote an obexftpbackup script which worked fine on the basic SE T610 file structure. Since upgrading to obexftp 0.18 I've had to modify the error checking, but more significantly I've had to completely re-write it to handle the directory structure of the SE K750i. In its current form it will handle up to 8 levels of subdirectories and will accept file and directory names with spaces in them. There's also a sed line to handle filenames with apostrophes in them. To use it simply create a directory called ~/Documents/Obexftp-backups, switch your phone's bluetooth to visible for the first run, then run obexftpbackup. On subsequent runs the phone can be hidden. I've only found one bug so far, and that appears to be in obexftp itself when trying read the directory contents for the Pictures directory. I suspect this could be due to having over 100 jpegs in that folder. Enjoy! Ken. ------------- obexftpbackup 1.0 ------------- The sleeps appear to be necessary to give my Sony Ericsson T610 a chance. If you wish to retain all your previous downloads from the phone then don't use the -o option, and take care to rename your pictures from the default name otherwise Picture(1).jpg etc will omitted from your backup. Ken Booth obexftp-0.24.2-Source/examples/c_example.c000644 001750 001750 00000003250 11351376660 021545 0ustar00hendrikhendrik000000 000000 /* Minimal ObexFTP C client example Copyright (c) 2007 Christian W. Zuckschwerdt Compile with: gcc -Wall $(pkg-config --libs obexftp) -o c_example c_example.c */ #include #include #include /*!!!*/ int main(int argc, char *argv[]) { char *device; int channel; char *filename = NULL; obexftp_client_t *cli = NULL; /*!!!*/ int ret; /* Get device, channel and optional filename */ if (argc < 3) { fprintf(stderr, "Usage: %s []\n", argv[0]); exit(1); } device = argv[1]; channel = atoi(argv[2]); if (argc > 3) { filename = argv[3]; } /* Open connection */ cli = obexftp_open(OBEX_TRANS_BLUETOOTH, NULL, NULL, NULL); /*!!!*/ if (cli == NULL) { fprintf(stderr, "Error opening obexftp client\n"); exit(1); } /* Connect to device */ ret = obexftp_connect(cli, device, channel); /*!!!*/ if (ret < 0) { fprintf(stderr, "Error connecting to obexftp device\n"); obexftp_close(cli); cli = NULL; exit(1); } if (filename == NULL) { /* List folder */ ret = obexftp_list(cli, NULL, "/"); /*!!!*/ if (ret < 0) { fprintf(stderr, "Error getting a folder listing\n"); } else { printf("%s\n", cli->buf_data); /*!!!*/ } } else { /* Get file */ ret = obexftp_get(cli, NULL, filename); /*!!!*/ if (ret < 0) { fprintf(stderr, "Error getting a file\n"); } else { /* do something with cli->buf_data and cli->buf_size */ } } /* Disconnect */ ret = obexftp_disconnect(cli); /*!!!*/ if (ret < 0) { fprintf(stderr, "Error disconnecting the client\n"); } /* Close */ obexftp_close(cli); /*!!!*/ cli = NULL; exit(0); } obexftp-0.24.2-Source/examples/c_example_obex_push.c000755 001750 001750 00000003132 11351376660 023623 0ustar00hendrikhendrik000000 000000 /* OBEX PUSH ObexFTP C client example Copyright (c) 2007 Christian W. Zuckschwerdt Compile with: gcc -Wall $(pkg-config --libs obexftp) -o c_example_obex_push c_example_obex_push.c */ #include #include #include #include /*!!!*/ int main(int argc, char *argv[]) { char *device = NULL; int channel = -1; char *filepath, *filename; obexftp_client_t *cli = NULL; /*!!!*/ int ret; /* Get the filename, device and optional channel */ if (argc < 3) { fprintf(stderr, "Usage: %s []\n", argv[0]); exit(1); } filepath = argv[1]; device = argv[2]; if (argc > 3) channel = atoi(argv[3]); else channel = obexftp_browse_bt_push(device); /*!!!*/ /* Extract basename from file path */ filename = strrchr(filepath, '/'); if (!filename) filename = filepath; else filename++; /* Open connection */ cli = obexftp_open(OBEX_TRANS_BLUETOOTH, NULL, NULL, NULL); /*!!!*/ if (cli == NULL) { fprintf(stderr, "Error opening obexftp client\n"); exit(1); } /* Connect to device */ ret = obexftp_connect_push(cli, device, channel); /*!!!*/ if (ret < 0) { fprintf(stderr, "Error connecting to obexftp device\n"); obexftp_close(cli); cli = NULL; exit(1); } /* Push file */ ret = obexftp_put_file(cli, filepath, filename); /*!!!*/ if (ret < 0) { fprintf(stderr, "Error putting file\n"); } /* Disconnect */ ret = obexftp_disconnect(cli); /*!!!*/ if (ret < 0) { fprintf(stderr, "Error disconnecting the client\n"); } /* Close */ obexftp_close(cli); /*!!!*/ cli = NULL; exit(0); } obexftp-0.24.2-Source/examples/obexftpbackup000755 001750 001750 00000004415 11351376660 022233 0ustar00hendrikhendrik000000 000000 #!/bin/bash --norc #btchan="-B 15" retries=10 [ "X$1" == "X-version" ] && { echo "$0 version 2.0" exit 0 } overwrite=0 [ "X$1" == "X-o" ] && { overwrite=1 shift } [ $# -gt 1 ] && { echo "usage: $0 [-o] [dir]" echo "usage: $0 [-version]" exit 1 } topdir=$1 [ -z "$1" ] && topdir=~/Documents/Obexftp-backups [ ! -d $topdir ] && { echo "${0}: ${topdir}: No such directory" exit 1 } echo "Scanning for new phones" for btaddr in `hcitool scan | grep : | cut -f2` do sleep 1 subdir=`hcitool scan | grep --fixed-strings $btaddr | cut -f3` echo "Found phone $subdir" mkdir "$topdir/$subdir" 2>/dev/null echo $btaddr > "$topdir/$subdir/.Bluetooth-addr" done sleep 1 obexftpdir() { echo "Parsing \$1=\"$1\" \$2=\"$2\" \$3=\"$3\" \$4=\"$4\" \$5=\"$5\" \$6=\"$6\" \$7=\"$7\" \$8=\"$8\"" sleep 1 obexftp -b $btaddr $btchan ${1:+-c "$1"} ${2:+-c "$2"} ${3:+-c "$3"} ${4:+-c "$4"} ${5:+-c "$5"} ${6:+-c "$6"} ${7:+-c "$7"} ${8:+-c "$8"} -l 2>/dev/null | tr '<' '\012' | grep "file name" | cut -d\" -f2 | sed -e "s/\&apos\;/'/" | while read fil do sleep 1 echo "Checking file $fil" [ ! -z "`echo $fil | grep '\.dm$'`" ] && { echo "Cannot copy DRM protected files" touch "$fil" } [ $overwrite == "1" ] || [ ! -f "$fil" ] && { echo "reading $fil" retry=0 success=0 while [ $success -eq 0 -a $retry -lt $retries ] do success=`obexftp -b $btaddr $btchan ${1:+-c "$1"} ${2:+-c "$2"} ${3:+-c "$3"} ${4:+-c "$4"} ${5:+-c "$5"} ${6:+-c "$6"} ${7:+-c "$7"} ${8:+-c "$8"} -g "$fil" 2>&1 | grep -c '^Receiving.*'"$fil"'.*done$'` sleep 1 [ $success -eq 0 ] && echo "Retrying ..." retry=`expr $retry + 1` done echo "read $fil success $success" } done sleep 1 obexftp -b $btaddr $btchan ${1:+-c "$1"} ${2:+-c "$2"} ${3:+-c "$3"} ${4:+-c "$4"} ${5:+-c "$5"} ${6:+-c "$6"} ${7:+-c "$7"} -l 2>/dev/null | tr '<' '\012' | grep "folder name" | cut -d\" -f2 | while read sub do echo "Subdir is \"$sub\"" mkdir "$sub" 2>/dev/null cd "$sub" obexftpdir ${1:+"$1"} ${2:+"$2"} ${3:+"$3"} ${4:+"$4"} ${5:+"$5"} ${6:+"$6"} ${7:+"$7"} "$sub" cd .. done } cd $topdir ls | while read dir do echo Getting files for phone `basename "$dir"` btaddr=`cat "$dir/.Bluetooth-addr"` mkdir "$dir" 2>/dev/null cd "$dir" obexftpdir cd .. done exit 0 obexftp-0.24.2-Source/examples/perl_example.pl000755 001750 001750 00000001445 11351376660 022465 0ustar00hendrikhendrik000000 000000 #!/usr/bin/perl -w use strict; use OBEXFTP; my $obex = new OBEXFTP::client($OBEXFTP::BLUETOOTH); my $devs = $obex->discover(); die "No devices found" unless @$devs > 0; print "Found " . scalar @$devs . " devices\n"; my $dev = $devs->[0]; # or $$devs[0] my $channel = OBEXFTP::browsebt($dev, 0); # default is ftp print "Using device $dev on channel $channel\n"; sleep 2; my $ret = $obex->connect($dev, $channel); print "$ret\n"; $ret = $obex->list("/"); print "$ret\n"; sleep 2; $ret = $obex->list("/images"); print "$ret\n"; sleep 2; $ret = $obex->get("/images/some.jpg"); open OUT, ">downloaded.jpg" or die "Can't write test.out: $@"; binmode(OUT); print OUT $ret; close OUT; $ret = $obex->get("/data/README.txt"); print "$ret\n"; $ret = $obex->disconnect(); print "$ret\n"; $obex->DESTROY(); obexftp-0.24.2-Source/examples/picture-mover000755 001750 001750 00000000576 11351376660 022203 0ustar00hendrikhendrik000000 000000 #!/bin/sh # append your mobiles address to '-b' for slight speedup # optionally choose a channel with '-B' # change the '-c path' into something useful for your device # use '-G' instead of '-g' to move the pictures (copy & delete) pics=$(obexftp -b -c MMCard -c Pictures -l |grep 'file.*jpg' |cut -d '"' -f 2) echo Getting $pics sleep 3 obexftp -b -c MMCard -c Pictures -g $pics obexftp-0.24.2-Source/examples/python_example.py000755 001750 001750 00000000652 11351376660 023060 0ustar00hendrikhendrik000000 000000 #!/usr/bin/python import obexftp obex = obexftp.client(obexftp.BLUETOOTH) devs = obex.discover(); print devs; dev = devs[0] print "Using %s" % dev channel = obexftp.browsebt(dev,0) print "Channel %d" % channel print obex.connect(dev, channel) print obex.list("/") print obex.list("/images") data = obex.get("/images/some.jpg") file = open('downloaded.jpg', 'wb') file.write(data) print obex.disconnect() obex.delete obexftp-0.24.2-Source/examples/ruby_example.rb000755 001750 001750 00000000665 11351376660 022477 0ustar00hendrikhendrik000000 000000 #!/usr/bin/env ruby require 'obexftp' intfs = Obexftp.discover(Obexftp::USB) intfs.each { |i| puts i } # - or - obex = Obexftp::Client.new(Obexftp::BLUETOOTH) intfs = obex.discover intfs.each { |i| puts i } # - then - dev = intfs.first channel = Obexftp.browsebt(dev, 0) # default is ftp obex = Obexftp::Client.new(Obexftp::BLUETOOTH) # or reuse the above puts obex.connect(dev, channel) puts obex.list('/') puts obex.disconnect obexftp-0.24.2-Source/examples/ruby_list_devices.rb000755 001750 001750 00000000765 11351376660 023522 0ustar00hendrikhendrik000000 000000 #!/usr/bin/env ruby require 'obexftp' puts "Scanning USB..." intfs = Obexftp.discover(Obexftp::USB) intfs.each do |dev| puts "usb/#{dev}" end puts "Scanning BT..." intfs = Obexftp.discover(Obexftp::BLUETOOTH) intfs.each do |dev| channel = Obexftp.browsebt(dev, Obexftp::PUSH) puts "bt/[#{dev}]:#{channel} (push)" channel = Obexftp.browsebt(dev, Obexftp::FTP) puts "bt/[#{dev}]:#{channel} (ftp)" channel = Obexftp.browsebt(dev, Obexftp::SYNC) puts "bt/[#{dev}]:#{channel} (sync)" end obexftp-0.24.2-Source/examples/ruby_obex_push.rb000755 001750 001750 00000003163 11351376660 023034 0ustar00hendrikhendrik000000 000000 #!/usr/bin/env ruby =begin ruby_obex_push.rb - Ruby/GTK2 example of ObexFTP push client. Copyright (c) 2007 Christian W. Zuckschwerdt Original Ruby/GTK2 examples Copyright Ruby-GNOME2 Project Team This program is licenced under the same licence as Ruby-GNOME2. =end require 'gtk2' require 'obexftp' dialog = Gtk::FileChooserDialog.new("Send file via bluetooth", nil, Gtk::FileChooser::ACTION_OPEN, "gnome-vfs", [Gtk::Stock::COPY, Gtk::Dialog::RESPONSE_ACCEPT], [Gtk::Stock::CLOSE, Gtk::Dialog::RESPONSE_CANCEL] ) label = Gtk::Label.new("Select target device:") combo = Gtk::ComboBox.new hbox = Gtk::HBox.new hbox.add(label).add(combo).show_all dialog.extra_widget = hbox dialog.signal_connect("response") do |widget, response| case response when Gtk::Dialog::RESPONSE_ACCEPT filename = dialog.filename dev = combo.active_text channel = Obexftp.browsebt(dev, Obexftp::PUSH) obex = Obexftp::Client.new(Obexftp::BLUETOOTH) puts obex.connectpush(dev, channel) puts obex.put_file(filename) puts obex.disconnect else dialog.destroy Gtk.main_quit end end # Should use gtk.timeout_add and/or Thread.new for the scanning... puts "Scanning USB..." intfs = Obexftp.discover(Obexftp::USB) # intfs.each { |i| combo.append_text(i) } # enable this with >=ObexFTP-0.23 puts "Scanning BT..." intfs = Obexftp.discover(Obexftp::BLUETOOTH) intfs.each { |i| combo.append_text(i) } combo.active = 0 dialog.show_all Gtk.main obexftp-0.24.2-Source/examples/ruby_obexftp.rb000755 001750 001750 00000013037 11351376660 022510 0ustar00hendrikhendrik000000 000000 #!/usr/bin/env ruby # == Synopsis # # Transfer files from/to Mobile Equipment. # # == Usage # # ruby_obexftp.rb # transport: [ -i | -b [-B ] | -U | -t | -N ] # operations: [-c ...] [-C ] [-l []] # [-g ...] [-p ...] [-k ...] # # -i, --irda connect using IrDA transport (default) # -b, --bluetooth [] use or search a bluetooth device # [ -B, --channel ] use this bluetooth channel when connecting # -u, --usb [] connect to a usb interface or list interfaces # -t, --tty connect to this tty using a custom transport # -n, --network connect to this host # # -F, --ftp use FTP (default) # -P, --push use OPUSH # -S, --sync use IRMC # -c, --chdir chdir # -C, --mkdir mkdir and chdir # -l, --list [] list current/given folder # -o, --output specify the target file name # get and put always specify the remote name. # -g, --get fetch files # -G, --getdelete fetch and delete (move) files # -p, --put send files # -k, --delete delete files # # -X, --capability retrieve capability object # -v, --verbose verbose messages # -V, --version print version info # -h, --help, --usage this help text # # fmtstring:: # A +strftime+ format string controlling the # display of the date and time. If omitted, # use "%Y% M% d %H:%m" # # == Author # Christian W. Zuckschwerdt # # == Copyright # Copyright (c) 2006 Christian W. Zuckschwerdt # Licensed under the same terms as Ruby. require 'optparse' require 'rdoc/usage' require 'obexftp' @cli = nil @transport = Obexftp::BLUETOOTH @service = Obexftp::FTP @device = nil @channel = -1 # connect with given uuid. re-connect every time def cli_connect if @cli.nil? # Open @cli = Obexftp::Client.new(@transport) raise "Error opening obexftp-client" if @cli.nil? end @cli.callback Proc.new { |num, msg| puts "Callback no.#{num} '#{msg}'" if msg.length < 30 } # for (retry = 0; retry < 3; retry++) # Connect @cli.connect(@device, @channel) and return @cli # fprintf(stderr, "Still trying to connect\n") # end @cli.close @cli = nil end def cli_disconnect return if @cli.nil? @cli.disconnect # @cli.close @cli = nil end # preset mode of operation depending on our name # preset from environment OptionParser.new do |opts| verbose = false target_path = nil output_file = nil opts.on('-i', '--irda') do @transport = Obexftp::IRDA @device = nil @channel = 0 end opts.on('-b', '--bluetooth [ADDR]') do |arg| @transport = Obexftp::BLUETOOTH @device = arg if arg.nil? intfs = Obexftp.discover(@transport) intfs.each { |i| puts i } @device = intfs.first end @channel = Obexftp.browsebt(@device, @service) puts "Got channel #{@channel}" end opts.on('-B', '--channel N', Integer) do |arg| @channel = arg end opts.on('-u', '--usb [N]', Integer) do |arg| # "If USB doesn't work setup permissions in udev or run as superuser." @transport = Obexftp::USB @device = nil @channel = arg intfs = Obexftp.discover(@transport) end opts.on('-t', '--tty DEVICE') do |arg| @transport, @device, @channel = Obexftp::CABLE, arg, -1 # if (strstr(arg, "ir") != NULL) # fprintf(stderr, "Do you really want to use IrDA via ttys?\n"); end opts.on('-n', '--network HOST') do |arg| @transport = Obexftp::NETWORK @device = arg # dotted quad, hopefully @channel = 0 end opts.on('-F', '--ftp') do cli_disconnect @service = Obexftp::FTP end opts.on('-P', '--push') do cli_disconnect @service = Obexftp::PUSH end opts.on('-S', '--sync') do cli_disconnect @service = Obexftp::SYNC end opts.on('-l', '--list [PATH]') do |arg| puts cli_connect.list(arg) end opts.on('-c', '--chdir [PATH]') do |arg| cli_connect.chpath(arg) end opts.on('-C', '--mkdir PATH') do |arg| cli_connect.mkpath(arg) end opts.on('-o', '--output PATH') do |arg| output_file = arg end opts.on('-g', '--get PATH') do |arg| output_file ||= File.basename(arg) result = cli_connect.get(arg) raise "No such file" if result.nil? open(output_file, 'w') do |file| file.print(result) end output_file = nil end opts.on('-G', '--getdelete PATH') do |arg| output_file ||= File.basename(arg) cli = cli_connect result = cli.get(arg) raise "No such file" if result.nil? open(output_file, 'w') do |file| file.print(result) cli.del(arg) end output_file = nil end opts.on('-p', '--put PATH') do |arg| output_file ||= File.basename(arg) cli_connect.put_file(arg, output_file) output_file = nil end opts.on('-k', '--delete PATH') do |arg| cli_connect.delete(arg) end opts.on('-X', '--capabilities [PATH]') do |arg| cli_connect.get_capability(arg) end opts.on('-v', '--[no-]verbose', 'Run verbosely') do |arg| verbose = arg end opts.on('-V', '--version') do puts "ObexFTP #{VERSION}" end opts.on('-h', '--help') do RDoc::usage end opts.parse!(ARGV) # rescue RDoc::usage('usage') end cli_disconnect obexftp-0.24.2-Source/examples/tcl_example.tcl000644 001750 001750 00000000330 11351376660 022441 0ustar00hendrikhendrik000000 000000 #!/bin/sh # the next line restarts using tclsh \ exec tclsh "$0" "$@" load obexftp.so puts [discover $BLUETOOTH] client c $BLUETOOTH puts [c connect "00:11:22:33:44:55" 6] puts [c list "/"] c disconnect c -delete obexftp-0.24.2-Source/includes/000755 001750 001750 00000000000 12701545532 017430 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/includes/common.h000644 001750 001750 00000003075 12656174331 021102 0ustar00hendrikhendrik000000 000000 /** \file includes/common.h ObexFTP common macros and debugging. ObexFTP library - language bindings for OBEX file transfer. */ #ifndef _OBEXFTP_COMMON_H #define _OBEXFTP_COMMON_H #include #ifdef UNUSED #elif defined(__GNUC__) # define UNUSED(x) UNUSED_ ## x __attribute__((unused)) #elif defined(__LCLINT__) # define UNUSED(x) /*@unused@*/ x #else # define UNUSED(x) x #endif #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (!FALSE) #endif /* these are not asserts! dont define to nothing */ #define return_if_fail(expr) do { if (!(expr)) return; } while(0); #define return_val_if_fail(expr,val) do { if (!(expr)) return val; } while(0); #ifdef _WIN32 #define snprintf _snprintf #endif /* _WIN32 */ /* use 0 for production, 1 for verification, >2 for debug */ #ifndef OBEXFTP_DEBUG #define OBEXFTP_DEBUG 0 #endif #if defined (__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define DEBUG(n, ...) if (OBEXFTP_DEBUG >= (n)) fprintf(stderr, __VA_ARGS__) #elif defined (__GNUC__) #define DEBUG(n, format...) if (OBEXFTP_DEBUG >= (n)) fprintf (stderr, format) #else /* !__GNUC__ */ static void DEBUG (int n, const char *format, ...) { va_list args; if (OBEXFTP_DEBUG >= (n)) { va_start (args, format); fprintf (stderr, format, args); va_end (args); } } #endif /* !__GNUC__ */ #if OBEXFTP_DEBUG > 4 #define DEBUGBUFFER(b,l) do { \ int i; \ for (i=0; i < (l); i++) \ fprintf (stderr, "%02x ", ((uint8_t *)(b))[i]); \ fprintf (stderr, "\n"); \ } while (0) #else #define DEBUGBUFFER(b,l) do { } while (0) #endif #endif /* _OBEXFTP_COMMON_H */ obexftp-0.24.2-Source/multicobex/000755 001750 001750 00000000000 12701545532 017775 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/multicobex/multi_cobex.h000644 001750 001750 00000002637 11351376660 022474 0ustar00hendrikhendrik000000 000000 /** \file multicobex/multi_cobex.h Detect, initiate and run OBEX over custom serial port protocols (Siemens, Ericsson, New-Siemens, Motorola, Generic). ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef MULTICOBEX_H #define MULTICOBEX_H #include #ifdef __cplusplus extern "C" { #endif /* session handling */ obex_ctrans_t * cobex_ctrans (const char *tty); void cobex_free (obex_ctrans_t * ctrans); /* callbacks */ int cobex_connect (obex_t *self, void *data); int cobex_disconnect (obex_t *self, void *data); int cobex_write (obex_t *self, void *data, uint8_t *buffer, int length); int cobex_handleinput (obex_t *self, void *data, int timeout); #ifdef __cplusplus } #endif #endif /* MULTICOBEX_H */ obexftp-0.24.2-Source/multicobex/multi_cobex_private.h000644 001750 001750 00000003451 11351376660 024221 0ustar00hendrikhendrik000000 000000 /** \file multicobex/multi_cobex_private.h Detect, initiate and run OBEX over custom serial port protocols (Siemens, Ericsson, New-Siemens, Motorola, Generic). ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2005 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef MULTICOBEX_PRIVATE_H #define MULTICOBEX_PRIVATE_H #include #define SERPORT "/dev/ttyS0" #define RECVSIZE 500 /* Recieve up to this much from socket */ enum cobex_type { CT_BFB, /* use a bfb transport */ CT_ERICSSON, /* just custom init and teardown */ CT_SIEMENS, /* new siemens, like ericsson above */ CT_MOTOROLA, /* experimental motorola support */ CT_GENERIC /* should work on most phones */ }; typedef struct { enum cobex_type type; /* Type of connected mobile */ char *tty; #ifdef _WIN32 HANDLE fd; /* Socket descriptor */ #else int fd; /* Socket descriptor */ #endif uint8_t recv[RECVSIZE]; /* Buffer socket input */ int recv_len; uint8_t seq; bfb_data_t *data_buf; /* assembled obex frames */ int data_size; /* max buffer size */ int data_len; /* filled buffer length */ } cobex_t; #endif /* MULTICOBEX_PRIVATE_H */ obexftp-0.24.2-Source/multicobex/multi_cobex_io.c000644 001750 001750 00000040053 12656173041 023145 0ustar00hendrikhendrik000000 000000 /** \file bfb/bfb_io.c Detect, initiate and run OBEX over custom serial port protocols (Siemens, Ericsson, New-Siemens, Motorola, Generic). ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #define sleep(n) Sleep(n*1000) #else #include #include #endif #include "multi_cobex_io.h" #include "bfb/bfb.h" #include "bfb/bfb_io.h" #include /* Write out an IO buffer */ int cobex_io_write(fd_t fd, const void *buffer, int length) { struct timeval timeout; fd_set fds; if (fd == INVALID_HANDLE_VALUE) { DEBUG(1, "%s() Error file handle invalid\n", __func__); return -1; } /* select setup */ FD_ZERO(&fds); FD_SET(fd, &fds); /* Set time limit. */ timeout.tv_sec = 1; timeout.tv_usec = 0; if ( select(fd+1, NULL, &fds, NULL, &timeout) > 0) { #ifdef _WIN32 DWORD bytes; DEBUG(3, "%s() WriteFile\n", __func__); if(!WriteFile(fd, buffer, length, &bytes, NULL)) DEBUG(1, "%s() Write error: %ld\n", __func__, bytes); return bytes; #else int bytes; bytes = write(fd, buffer, length); if (bytes < length) DEBUG(1, "%s() Error short write (%d / %d)\n", __func__, bytes, length); if (bytes < 0) DEBUG(1, "%s() Error writing to port\n", __func__); return bytes; #endif } else { /* ! rc > 0*/ DEBUG(1, "%s() Select failed\n", __func__); return 0; } } /* Read an answer to an IO buffer of max length bytes */ int cobex_io_read(fd_t fd, void *buffer, int length, int timeout) { #ifdef _WIN32 DWORD bytes; DEBUG(3, "%s() ReadFile\n", __func__); return_val_if_fail (fd != INVALID_HANDLE_VALUE, -1); if (!ReadFile(fd, buffer, length, &bytes, NULL)) { DEBUG(2, "%s() Read error: %ld\n", __func__, bytes); } return bytes; #else struct timeval time; fd_set fdset; int actual; return_val_if_fail (fd > 0, -1); time.tv_sec = timeout; time.tv_usec = 0; FD_ZERO(&fdset); FD_SET(fd, &fdset); if (select(fd+1, &fdset, NULL, NULL, &time) > 0) { actual = read(fd, buffer, length); if (actual < 0) { DEBUG(2, "%s() Read error: %d\n", __func__, actual); } return actual; } else { DEBUG(1, "%s() No data (timeout: %d)\n", __func__, timeout); return 0; } #endif } /** Read (repeatedly) from fd until a timeout or an error is encountered. */ static int cobex_io_read_all(int fd, char *buffer, int length, int timeout) { int actual; int pos = 0; for (;;) { actual = cobex_io_read(fd, &buffer[pos], length - pos, timeout); if (actual < 0) return actual; if (actual == 0) return pos; pos += actual; } } /** Send an AT-command and expect an answer of one or more lines. \note Start your command with "AT" and terminate it with "\r" (CR). \note The expected lines are the the echo, one optional information response and a final result code of "OK" or "ERROR". */ static bool do_at_cmd(fd_t fd, const char *cmd, char *rspbuf, int rspbuflen) { #ifdef _WIN32 DWORD actual; #else int actual; #endif char *answer = NULL; int answer_size; char tmpbuf[100] = {0,}; unsigned int total = 0; int cmdlen; return_val_if_fail (cmd != NULL, -1); cmdlen = strlen(cmd); rspbuf[0] = 0; DEBUG(3, "%s() Sending %d: %s\n", __func__, cmdlen, cmd); /* Write command */ if (cobex_io_write(fd, cmd, cmdlen) < cmdlen) return false; actual = 1; while (actual > 0) { actual = cobex_io_read(fd, &tmpbuf[total], sizeof(tmpbuf) - total, 2); if (actual < 0) /* error checking */ return false; total += actual; tmpbuf[total] = '\0'; /* terminate the string, always */ DEBUG(3, "%s() tmpbuf=%d: %s\n", __func__, total, tmpbuf); /* Answer not found within 100 bytes. Cancel */ if (total >= sizeof(tmpbuf)) return false; /* Remove first line (echo), then search final result code */ for (answer = tmpbuf; answer && *answer ; ) { while ((*answer != '\r') && (*answer != '\n') && (*answer != '\0')) answer++; while ((*answer == '\r') || (*answer == '\n')) answer++; if (!strncmp(answer, "OK\r", 3) || !strncmp(answer, "ERROR\r", 6) || !strncmp(answer, "OK\n", 3) || !strncmp(answer, "ERROR\n", 6)) { actual = 0; /* we are done */ } } } /* try hard to discard remaing CR/LF */ if (total > 0 && tmpbuf[total-1] != '\n') actual = cobex_io_read(fd, &tmpbuf[total], sizeof(tmpbuf) - total, 2); /* Remove echo and trailing CRs */ answer = strchr(tmpbuf, '\r'); if (!answer) /* no echo found */ return false; while (*answer == '\r' || *answer == '\n') answer++; answer_size = 0; while (answer[answer_size] != '\0' && answer[answer_size] != '\r' && answer[answer_size] != '\n') answer_size++; DEBUG(3, "%s() Answer (size=%d): %s\n", __func__, answer_size, answer); if( (answer_size) >= rspbuflen ) return false; strncpy(rspbuf, answer, answer_size); rspbuf[answer_size] = '\0'; return true; } static void cobex_io_close_bfb(fd_t fd) { /* needed to leave transparent OBEX(3) mode * and enter RCCP(0) mode. * DCA-540 needs cable replug, probably problem * with the linux driver (linux-2.6.17.13) */ bfb_write_at(fd, "AT^SBFB=0\r"); sleep(1); cobex_io_write(fd, "+++", 3); sleep(1); cobex_io_write(fd,"\r", 1); } static void cobex_io_close_generic(fd_t fd, int force) { if(force) { /* Send a break to get out of OBEX-mode */ #ifdef _WIN32 if(SetCommBreak(fd) != TRUE) { #elif defined(TCSBRKP) if(ioctl(fd, TCSBRKP, 0) < 0) { #elif defined(TCSBRK) if(ioctl(fd, TCSBRK, 0) < 0) { #else if(tcsendbreak(fd, 0) < 0) { #endif DEBUG(1, "Unable to send break!\n"); } sleep(1); } } /* close the connection */ void cobex_io_close(fd_t fd, enum cobex_type typeinfo, int force) { DEBUG(3, "%s()\n", __func__); #ifdef _WIN32 return_if_fail (fd != INVALID_HANDLE_VALUE); #else return_if_fail (fd > 0); #endif switch(typeinfo) { case CT_BFB: cobex_io_close_bfb(fd); break; default: cobex_io_close_generic(fd, force); break; } #ifdef _WIN32 CloseHandle(fd); #else close(fd); #endif } static fd_t cobex_io_open_port(const char *ttyname) { fd_t ttyfd; #ifdef _WIN32 DCB dcb; COMMTIMEOUTS ctTimeOuts; return_val_if_fail (ttyname != NULL, INVALID_HANDLE_VALUE); DEBUG(3, "%s() CreateFile\n", __func__); ttyfd = CreateFile (ttyname, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (ttyfd == INVALID_HANDLE_VALUE) { DEBUG(1, "Error: CreateFile()\n"); return INVALID_HANDLE_VALUE; } if(!GetCommState(ttyfd, &dcb)) { DEBUG(1, "Error: GetCommState()\n"); } dcb.fBinary = TRUE; dcb.BaudRate = CBR_57600; dcb.fParity = FALSE; dcb.Parity = NOPARITY; dcb.ByteSize = 8; dcb.StopBits = ONESTOPBIT; dcb.fInX = FALSE; dcb.fOutX = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.fOutxCtsFlow = FALSE; dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fRtsControl = RTS_CONTROL_ENABLE; if(!SetCommState(ttyfd, &dcb)) DEBUG(1, "SetCommState failed\n"); ctTimeOuts.ReadIntervalTimeout = 250; ctTimeOuts.ReadTotalTimeoutMultiplier = 1; /* no good with big buffer */ ctTimeOuts.ReadTotalTimeoutConstant = 500; ctTimeOuts.WriteTotalTimeoutMultiplier = 1; ctTimeOuts.WriteTotalTimeoutConstant = 5000; if(!SetCommTimeouts(ttyfd, &ctTimeOuts)) { DEBUG(1, "Error: SetCommTimeouts()\n"); } Sleep(500); /* flush all pending input */ if(!PurgeComm(ttyfd, PURGE_RXABORT | PURGE_RXCLEAR)) { DEBUG(1, "Error: PurgeComm\n"); } #else struct termios oldtio, newtio; return_val_if_fail (ttyname != NULL, INVALID_HANDLE_VALUE); DEBUG(2, "%s() \n", __func__); if( (ttyfd = open(ttyname, O_RDWR | O_NONBLOCK | O_NOCTTY, 0)) < 0 ) { DEBUG(1, "Can' t open tty\n"); return INVALID_HANDLE_VALUE; } (void) tcgetattr(ttyfd, &oldtio); memset(&newtio, 0, sizeof(newtio)); newtio.c_cflag = B57600 | CS8 | CREAD; newtio.c_iflag = IGNPAR; newtio.c_oflag = 0; (void) tcflush(ttyfd, TCIFLUSH); (void) tcsetattr(ttyfd, TCSANOW, &newtio); #endif return ttyfd; } static bool cobex_io_init_bfb(fd_t ttyfd) { #ifndef _WIN32 struct termios newtio; (void) tcgetattr(ttyfd, &newtio); if (newtio.c_cflag != (B57600 | CS8 | CREAD)) { newtio.c_cflag = B57600 | CS8 | CREAD; (void) tcsetattr(ttyfd, TCSANOW, &newtio); } (void) tcflush(ttyfd, TCIFLUSH); #endif if (! bfb_io_init (ttyfd)) { /* well there may be some garbage -- just try again */ if (! bfb_io_init (ttyfd)) { DEBUG(1, "Couldn't init BFB mode.\n"); return false; } } return true; } static bool cobex_io_init_siemens2(fd_t ttyfd) { char rspbuf[200]; /* ^SBFB=3 only works when switching from RCCP(0) to OBEX(3) * but the phone may be in GIPSY(2) mode. * No need to implement BFC(1) mode if we only want to run OBEX. */ if(!do_at_cmd(ttyfd, "AT^SQWE?\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); return false; } if (strcasecmp("^SQWE: 0",rspbuf) != 0) { if(!do_at_cmd(ttyfd, "AT^SQWE=0\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); return false; } if(strcasecmp("OK", rspbuf) != 0) { DEBUG(1, "Error doing AT^SQWE=0 (%s)\n", rspbuf); return false; } sleep(1); } if(!do_at_cmd(ttyfd, "AT^SQWE=3\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); return false; } if(strcasecmp("OK", rspbuf) != 0) { DEBUG(1, "Error doing AT^SQWE=3 (%s)\n", rspbuf); return false; } sleep(1); /* synch a bit */ return true; } static bool cobex_io_init_siemens(fd_t ttyfd, enum cobex_type *typeinfo) { char rspbuf[200]; if(!do_at_cmd(ttyfd, "AT^SIFS\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); return false; } if(strcasecmp("^SIFS: WIRE", rspbuf) != 0 /* DCA-500, DCA-510 */ && strcasecmp("^SIFS: BLUE", rspbuf) != 0 && strcasecmp("^SIFS: IRDA", rspbuf) != 0 && strcasecmp("^SIFS: USB", rspbuf) != 0) { /* DCA-540 */ DEBUG(1, "Unknown connection doing AT^SIFS (%s), continuing anyway ...\n", rspbuf); } /* prefer connection without BFB */ if(!do_at_cmd(ttyfd, "AT^SBFB=?\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); return false; } if(!strncasecmp("^SBFB: (0-3", rspbuf, 11) != 0) { bool success; DEBUG(1, "New plain Siemens protocol. (%s)\n", rspbuf); success = cobex_io_init_siemens2(ttyfd); if (success) *typeinfo = CT_SIEMENS; return success; } else { bool success; DEBUG(1, "Old BFB Siemens protocol. (%s)\n", rspbuf); if(!do_at_cmd(ttyfd, "AT^SBFB=1\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); return false; } if(strcasecmp("OK", rspbuf) != 0) { DEBUG(1, "Error doing AT^SBFB=1 (%s)\n", rspbuf); return false; } sleep(1); /* synch a bit */ success = cobex_io_init_bfb(ttyfd); if (success) *typeinfo = CT_BFB; return success; } } static bool cobex_io_init_ericsson(fd_t ttyfd) { char rspbuf[200]; if(!do_at_cmd(ttyfd, "AT*EOBEX\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); return false; } if(strcasecmp("CONNECT", rspbuf) != 0) { DEBUG(1, "Error doing AT*EOBEX (%s)\n", rspbuf); return false; } return true; } static bool cobex_io_init_motorola(fd_t ttyfd) { char rspbuf[200]; if(!do_at_cmd(ttyfd, "AT+MODE=22\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); return false; } if(strcasecmp("CONNECT", rspbuf) != 0 || /* is this needed? */ strcasecmp("OK", rspbuf) != 0) { DEBUG(1, "Error doing AT+MODE=22 (%s)\n", rspbuf); return false; } return true; } static bool cobex_io_init_generic(fd_t ttyfd) { char rspbuf[200]; if(!do_at_cmd(ttyfd, "AT+CPROT=0\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); return false; } if(strcasecmp("CONNECT", rspbuf) != 0) { DEBUG(1, "Error doing AT+CPROT=0 (%s)\n", rspbuf); return false; } return true; } /* Init the phone and set it in BFB-mode */ /* Returns fd or INVALID_HANDLE_VALUE on failure */ fd_t cobex_io_open(const char *ttyname, enum cobex_type *typeinfo) { char rspbuf[200]; int actual; fd_t ttyfd = cobex_io_open_port(ttyname); const uint8_t transObexCheck[] = { 0xFF, 0x00, 0x08, 0xCB, 'A', 'T', 'Z', '\r' }; /* Can't just try that now, as it will break some phones. */ //if (bfb_io_init (ttyfd)) { // DEBUG(1, "Already in BFB mode.\n"); // goto bfbmode; //} /* check if we are in transparent OBEX or AT mode: */ /* send an ABORT (0xFF) with cleverly embedded AT command. */ /* look for valid OBEX frame (OK=0xA0, BADREQ=0xC0, or alike) */ DEBUG(1, "Checking for transparent OBEX mode\n"); actual = cobex_io_write(ttyfd, transObexCheck, sizeof(transObexCheck)); if (actual == 8) { int i; DEBUG(3, "Write ok, reading back\n"); actual = cobex_io_read_all(ttyfd, rspbuf, sizeof(rspbuf), 2); DEBUG(3, "Read %d bytes\n", actual); for (i = 0; i < actual; ++i) { DEBUG(3, "0x%02X %c\n", (uint8_t)rspbuf[i], isprint((int)rspbuf[i])? rspbuf[i]: ' '); } /* First check for an AT echo, or only for an OK response if echo is disabled by default */ if (actual >= 3 && (!strncmp(rspbuf, "ATZ\r", 4) || !strncmp(rspbuf, "\r\nOK\r\n", 4))) { DEBUG(1, "AT mode\n"); } else if (actual >= 3) { DEBUG(3, "Received %02X OBEX frame\n", (uint8_t)rspbuf[0]); DEBUG(1, "Transparent OBEX\n"); *typeinfo = CT_GENERIC; return ttyfd; } } if(!do_at_cmd(ttyfd, "ATZ\r", rspbuf, sizeof(rspbuf))) { #ifdef _WIN32 DEBUG(1, "Comm-error or already in BFB mode\n"); goto bfbmode; #else struct termios newtio; (void) tcgetattr(ttyfd, &newtio); if (newtio.c_cflag != (B19200 | CS8 | CREAD)) { newtio.c_cflag = B19200 | CS8 | CREAD; (void) tcsetattr(ttyfd, TCSANOW, &newtio); } (void) tcflush(ttyfd, TCIFLUSH); if(!do_at_cmd(ttyfd, "ATZ\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error or already in BFB mode\n"); goto bfbmode; } #endif } if(strcasecmp("OK", rspbuf) != 0) { DEBUG(1, "Error doing ATZ (%s)\n", rspbuf); goto err; } if(!do_at_cmd(ttyfd, "AT+GMI\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); goto err; } DEBUG(1, "AT+GMI: %s\n", rspbuf); if(strncasecmp("ERICSSON", rspbuf, 8) == 0 || strncasecmp("SONY ERICSSON", rspbuf, 13) == 0) { DEBUG(1, "Ericsson detected\n"); goto ericsson; } else if(strncasecmp("MOTOROLA", rspbuf, 8) == 0 || /* is this needed? */ strstr(rspbuf, "Motorola")) { DEBUG(1, "Motorola detected\n"); goto motorola; } else if(strncasecmp("SIEMENS", rspbuf, 7) == 0) { DEBUG(1, "Siemens detected\n"); goto siemens; } // Check for some other devices (mainly Gigasets show this behaviour) if(!do_at_cmd(ttyfd, "AT+CGMI\r", rspbuf, sizeof(rspbuf))) { DEBUG(1, "Comm-error\n"); goto err; } DEBUG(1, "AT+CGMI: %s\n", rspbuf); if(strncasecmp("SIEMENS", rspbuf, 7)) { DEBUG(1, "Siemens/Gigaset detected\n"); goto newsiemens; } DEBUG(1, "Unknown Device detected. Trying generic.\n"); goto generic; siemens: if (!cobex_io_init_siemens(ttyfd, typeinfo)) goto err; return ttyfd; bfbmode: if (!cobex_io_init_bfb(ttyfd)) goto err; *typeinfo = CT_BFB; return ttyfd; newsiemens: if (!cobex_io_init_siemens2(ttyfd)) goto err; *typeinfo = CT_SIEMENS; return ttyfd; ericsson: if (!cobex_io_init_ericsson(ttyfd)) goto err; *typeinfo = CT_ERICSSON; return ttyfd; motorola: if (!cobex_io_init_motorola(ttyfd)) goto err; *typeinfo = CT_MOTOROLA; return ttyfd; generic: if (!cobex_io_init_generic(ttyfd)) goto err; *typeinfo = CT_GENERIC; return ttyfd; err: cobex_io_close(ttyfd, CT_GENERIC, TRUE); return INVALID_HANDLE_VALUE; } obexftp-0.24.2-Source/multicobex/multi_cobex_io.h000644 001750 001750 00000003563 12311311306 023141 0ustar00hendrikhendrik000000 000000 /** \file multicobex/multi_cobex_io.h Detect, initiate and run OBEX over custom serial port protocols (Siemens, Ericsson, New-Siemens, Motorola, Generic). ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef MULTICOBEX_IO_H #define MULTICOBEX_IO_H #include #include "multi_cobex_private.h" #ifdef __cplusplus extern "C" { #endif #ifndef fd_t_defined #ifdef _WIN32 #include typedef HANDLE fd_t; #define fd_t_defined #else typedef int fd_t; #define fd_t_defined #endif #endif #if !defined(_WIN32) && !defined(INVALID_HANDLE_VALUE) #define INVALID_HANDLE_VALUE -1 #endif /* Write out a buffer */ int cobex_io_write(fd_t fd, const void *buffer, int length); /* Read in a answer */ int cobex_io_read(fd_t fd, void *buffer, int length, int timeout); /* Send an BFB init command an check for a valid answer frame */ int cobex_io_init(fd_t fd); /* close the connection */ void cobex_io_close(fd_t fd, enum cobex_type typeinfo, int force); /* Init the phone and set it in BFB-mode */ /* Returns fd or -1 on failure */ fd_t cobex_io_open(const char *ttyname, enum cobex_type *typeinfo); #ifdef __cplusplus } #endif #endif /* MULTICOBEX_IO_H */ obexftp-0.24.2-Source/multicobex/CMakeLists.txt000644 001750 001750 00000001611 12701255025 022527 0ustar00hendrikhendrik000000 000000 set ( multicobex_SOURCES multi_cobex.c multi_cobex_io.c ) set ( multicobex_PUBLIC_HEADERS multi_cobex.h ) set ( multicobex_HEADERS multi_cobex.h multi_cobex_io.h ${multicobex_PUBLIC_HEADERS} ) add_library ( multicobex ${multicobex_SOURCES} ${multicobex_HEADERS} ) set_property ( TARGET multicobex PROPERTY VERSION 1.0.2 ) set_property ( TARGET multicobex PROPERTY SOVERSION 1 ) set_property ( TARGET multicobex PROPERTY PUBLIC_HEADER ${multicobex_PUBLIC_HEADERS} ) target_link_libraries ( multicobex PRIVATE bfb ${OpenObex_LIBRARIES} ) install ( TARGETS multicobex RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT library LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/multicobex COMPONENT devel ) obexftp-0.24.2-Source/multicobex/multi_cobex.c000644 001750 001750 00000014213 12656173057 022464 0ustar00hendrikhendrik000000 000000 /** \file multicobex/multi_cobex.c Detect, initiate and run OBEX over custom serial port protocols (Siemens, Ericsson, New-Siemens, Motorola, Generic). ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #include #include #include #include #include #include #include #include #ifdef _WIN32 #include #define usleep(t) Sleep((t) < 500 ? 1 : ((t) + 500) / 1000); #else #include #include #endif #include #include "multi_cobex.h" #include "multi_cobex_private.h" #include "multi_cobex_io.h" #include "bfb/bfb.h" #include static void cobex_cleanup(cobex_t *c, int force) { return_if_fail (c != NULL); return_if_fail (c->fd != INVALID_HANDLE_VALUE); cobex_io_close(c->fd, c->type, force); c->fd = INVALID_HANDLE_VALUE; } /** Called from OBEX-lib to set up a connection. */ int cobex_connect(obex_t *self, void *data) { cobex_t *c; return_val_if_fail (self != NULL, -1); return_val_if_fail (data != NULL, -1); c = (cobex_t *) data; DEBUG(3, "%s() \n", __func__); c->fd = cobex_io_open(c->tty, &c->type); DEBUG(3, "%s() cobex_io_open returned %d, %d\n", __func__, c->fd, c->type); if(c->fd == INVALID_HANDLE_VALUE) return -1; return 1; } /** Called from OBEX-lib to tear down a connection. */ int cobex_disconnect(obex_t *self, void *data) { cobex_t *c = (cobex_t *)data; return_val_if_fail (self != NULL, -1); return_val_if_fail (data != NULL, -1); DEBUG(3, "%s() \n", __func__); cobex_cleanup(c, FALSE); return 1; } /** Called from OBEX-lib when data needs to be written. */ int cobex_write(obex_t *self, void *data, uint8_t *buffer, int length) { int written = 0; cobex_t *c = (cobex_t *)data; return_val_if_fail (self != NULL, -1); return_val_if_fail (data != NULL, -1); DEBUG(3, "%s() \n", __func__); DEBUG(3, "%s() Data %d bytes\n", __func__, length); if (c->type == CT_BFB) { if (c->seq == 0){ written = bfb_send_first(c->fd, buffer, length); DEBUG(2, "%s() Wrote %d first packets (%d bytes)\n", __func__, written, length); } else { written = bfb_send_next(c->fd, buffer, length, c->seq); DEBUG(2, "%s() Wrote %d packets (%d bytes)\n", __func__, written, length); } c->seq++; } else { int retries = 0; int fails = 0; for (retries = 0; written < length; retries++) { int chunk = write(c->fd, buffer+written, length-written); if (chunk <= 0) { if ( ++fails >= 10 ) { // to avoid infinite looping if something is really wrong DEBUG(1, "%s() Error writing to port (written %d bytes out of %d, in %d retries)\n", __func__, written, length, retries); return written; } usleep(1); // This mysteriously avoids a resource not available error on write() } else { written += chunk; fails = 0; // Reset error counter on successful write op } } if (retries > 0) DEBUG(2, "%s() Wrote %d bytes in %d retries\n", __func__, written, retries); } return written; } /** Called when input data is needed. */ int cobex_handleinput(obex_t *self, void *data, int timeout) { int actual; cobex_t *c = (cobex_t *)data; return_val_if_fail (self != NULL, -1); return_val_if_fail (data != NULL, -1); actual = cobex_io_read(c->fd, &(c->recv[c->recv_len]), sizeof(c->recv) - c->recv_len, timeout); /* Check if this is a timeout (0) or error (-1) */ if(actual <= 0) return actual; DEBUG(2, "%s() Read %d bytes (%d bytes already buffered)\n", __func__, actual, c->recv_len); if (c->type == CT_BFB) { if (c->data_buf == NULL || c->data_size == 0) { c->data_size = 1024; c->data_buf = malloc(c->data_size); } if (actual > 0) { bfb_frame_t *frame; c->recv_len += actual; DEBUGBUFFER(c->recv, c->recv_len); do { frame = bfb_read_packets(c->recv, &c->recv_len); if (frame == NULL) break; DEBUG(2, "%s() Parsed %x (%d bytes remaining)\n", __func__, frame->type, c->recv_len); (void)bfb_assemble_data(&c->data_buf, &c->data_size, &c->data_len, frame); if (bfb_check_data(c->data_buf, c->data_len) == 1) { actual = bfb_send_ack(c->fd); DEBUG(2, "%s() Wrote ack packet (%d)\n", __func__, actual); OBEX_CustomDataFeed(self, c->data_buf->data, c->data_len-7); c->data_len = 0; if (c->recv_len > 0) { DEBUG(2, "%s() Data remaining after feed, this can't be good.\n", __func__); DEBUGBUFFER(c->recv, c->recv_len); } return 1; } } while (1); } } else { if (actual > 0) { OBEX_CustomDataFeed(self, c->recv, actual); return 1; } } return actual; } /** Create a new multi cobex instance for a given TTY. \param tty the TTY to use. Defaults to the first serial TTY if NULL. */ obex_ctrans_t *cobex_ctrans (const char *tty) { obex_ctrans_t *ctrans; cobex_t *cobex; if(tty == NULL) tty = SERPORT; cobex = calloc(1, sizeof(*cobex)); cobex->tty = strdup(tty); ctrans = calloc(1, sizeof(*ctrans)); ctrans->connect = cobex_connect; ctrans->disconnect = cobex_disconnect; ctrans->write = cobex_write; ctrans->listen = NULL; ctrans->handleinput = cobex_handleinput; ctrans->customdata = cobex; return ctrans; } /** Free all data related to a multi cobex instance. */ void cobex_free (obex_ctrans_t *ctrans) { cobex_t *cobex; return_if_fail(ctrans != NULL); cobex = (cobex_t *)ctrans->customdata; return_if_fail(cobex != NULL); free(cobex->tty); cobex->tty = 0; free(cobex); cobex = 0; ctrans->customdata = 0; free (ctrans); } obexftp-0.24.2-Source/obexftp.pc.in000644 001750 001750 00000000371 11351376660 020227 0ustar00hendrikhendrik000000 000000 prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: ObexFTP Description: OBEX file transfer library Version: @VERSION@ Requires: @REQUIRES@ Libs: -L${libdir} -lobexftp -lmulticobex -lbfb Cflags: -I${includedir} obexftp-0.24.2-Source/obexftp/000755 001750 001750 00000000000 12701545532 017271 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/obexftp/cache.h000644 001750 001750 00000002366 11351376660 020520 0ustar00hendrikhendrik000000 000000 /** \file obexftp/cache.h ObexFTP client API caching layer. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef OBEXFTP_CACHE_H #define OBEXFTP_CACHE_H #ifdef __cplusplus extern "C" { #endif void cache_purge(cache_object_t **root, const char *path); void xfer_purge(obexftp_client_t *cli); int put_cache_object(obexftp_client_t *cli, /*@only@*/ char *name, /*@only@*/ char *object, int size); int get_cache_object(const obexftp_client_t *cli, const char *name, char **object, int *size); #ifdef __cplusplus } #endif #endif /* OBEXFTP_CACHE_H */ obexftp-0.24.2-Source/obexftp/obexftp.h000644 001750 001750 00000006067 11351376660 021126 0ustar00hendrikhendrik000000 000000 /** \file obexftp/obexftp.h Data structures and general functions for OBEX clients and servers. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef OBEXFTP_H #define OBEXFTP_H #ifdef __cplusplus extern "C" { #endif /** ObexFTP message callback prototype. */ typedef void (*obexftp_info_cb_t) (int event, const char *buf, int len, void *data); /** ObexFTP message callback events */ enum { OBEXFTP_EV_ERRMSG, /* not used / internal error */ OBEXFTP_EV_OK, OBEXFTP_EV_ERR, OBEXFTP_EV_CONNECTING, OBEXFTP_EV_DISCONNECTING, OBEXFTP_EV_SENDING, OBEXFTP_EV_LISTENING, OBEXFTP_EV_CONNECTIND, OBEXFTP_EV_DISCONNECTIND, OBEXFTP_EV_RECEIVING, OBEXFTP_EV_BODY, OBEXFTP_EV_INFO, OBEXFTP_EV_PROGRESS, /* approx. every 1KByte */ }; /** Number of bytes passed at one time to OBEX. */ #define STREAM_CHUNK 4096 /* bt svclass */ #define OBEX_SYNC_SERVICE 0x1104 #define OBEX_PUSH_SERVICE 0x1105 #define OBEX_FTP_SERVICE 0x1106 /* server and client helpers for bt */ char **obexftp_discover(int transport); char **obexftp_discover_bt_src(const char *src); /* HCI no. or address */ #define obexftp_discover_bt() \ obexftp_discover_bt_src(NULL) char *obexftp_bt_name_src(const char *addr, const char *src); #define obexftp_bt_name(addr) \ obexftp_bt_name_src(addr, NULL) int obexftp_browse_bt_src(const char *src, const char *addr, int svclass); #define obexftp_browse_bt(device, service) \ obexftp_browse_bt_src(NULL, device, service) #define obexftp_browse_bt_ftp(device) \ obexftp_browse_bt_src(NULL, device, OBEX_FTP_SERVICE) #define obexftp_browse_bt_push(device) \ obexftp_browse_bt_src(NULL, device, OBEX_PUSH_SERVICE) #define obexftp_browse_bt_sync(device) \ obexftp_browse_bt_src(NULL, device, OBEX_SYNC_SERVICE) int obexftp_sdp_register(int svclass, int channel); #define obexftp_sdp_register_ftp(channel) \ obexftp_sdp_register(OBEX_FTP_SERVICE, channel) #define obexftp_sdp_register_push(channel) \ obexftp_sdp_register(OBEX_PUSH_SERVICE, channel) #define obexftp_sdp_register_sync(channel) \ obexftp_sdp_register(OBEX_SYNC_SERVICE, channel) int obexftp_sdp_unregister(int svclass); #define obexftp_sdp_unregister_ftp() \ obexftp_sdp_unregister(OBEX_FTP_SERVICE) #define obexftp_sdp_unregister_push() \ obexftp_sdp_unregister(OBEX_PUSH_SERVICE) #define obexftp_sdp_unregister_sync() \ obexftp_sdp_unregister(OBEX_SYNC_SERVICE) #ifdef __cplusplus } #endif #endif /* OBEXFTP */ obexftp-0.24.2-Source/obexftp/obexftp_io.h000644 001750 001750 00000002156 11351376660 021610 0ustar00hendrikhendrik000000 000000 /** \file obexftp/obexftp_io.h ObexFTP IO abstraction. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef OBEXFTP_IO_H #define OBEXFTP_IO_H /*@null@*/ obex_object_t *build_object_from_file(obex_t *handle, uint32_t conn, const char *localname, const char *remotename); int open_safe(const char *path, const char *name); int checkdir(const char *path, const char *dir, int create, int allowabs); #endif /* OBEXFTP_IO_H */ obexftp-0.24.2-Source/obexftp/unicode.h000644 001750 001750 00000002233 11351376660 021074 0ustar00hendrikhendrik000000 000000 /** \file obexftp/unicode.h Unicode charset and encoding conversions. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef OBEXFTP_UNICODE_H #define OBEXFTP_UNICODE_H #include #ifdef __cplusplus extern "C" { #endif int CharToUnicode(uint8_t *uc, const uint8_t *c, int size); int UnicodeToChar(uint8_t *c, const uint8_t *uc, int size); int Utf8ToChar(uint8_t *c, const uint8_t *uc, int size); #ifdef __cplusplus } #endif #endif /* OBEXFTP_UNICODE_H */ obexftp-0.24.2-Source/obexftp/uuid.h000644 001750 001750 00000002533 11351376660 020417 0ustar00hendrikhendrik000000 000000 /** \file obexftp/uuid.h Definitions of well-known Universal Unique Identifiers (UUIDs). ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt */ #ifndef OBEXFTP_UUID_H #define OBEXFTP_UUID_H /** Folder Browsing service UUID. binary representation of F9EC7BC4-953C-11D2-984E-525400DC9E09 */ #define __UUID_FBS_bytes \ { 0xF9, 0xEC, 0x7B, 0xC4, \ 0x95, 0x3C, 0x11, 0xD2, 0x98, 0x4E, \ 0x52, 0x54, 0x00, 0xDC, 0x9E, 0x09 } #define UUID_FBS ((const uint8_t []) __UUID_FBS_bytes) /** UUID for Siemens S45 and maybe others too. binary representation of 6B01CB31-4106-11D4-9A77-0050DA3F471F */ #define __UUID_S45_bytes \ { 0x6B, 0x01, 0xCB, 0x31, \ 0x41, 0x06, 0x11, 0xD4, 0x9A, 0x77, \ 0x00, 0x50, 0xDA, 0x3F, 0x47, 0x1F } #define UUID_S45 ((const uint8_t []) __UUID_S45_bytes) /** UUID for Telecom/IrMC Synchronization Service (see IrOBEX spec). The character string "IRMC-SYNC". */ #define __UUID_IRMC_bytes \ { 'I', 'R', 'M', 'C', '-', 'S', 'Y', 'N', 'C' } #define UUID_IRMC ((const uint8_t []) __UUID_IRMC_bytes) /** UUID for Sharp mobiles. The character string "PCSOFTWARE". */ #define __UUID_PCSOFTWARE_bytes \ { 'P', 'C', 'S', 'O', 'F', 'T', 'W', 'A', 'R', 'E' } #define UUID_PCSOFTWARE ((const uint8_t []) __UUID_PCSOFTWARE_bytes) #endif /* OBEXFTP_UUID_H */ obexftp-0.24.2-Source/obexftp/bt_kit_test.c000644 001750 001750 00000004211 11776125712 021753 0ustar00hendrikhendrik000000 000000 /** \file obexftp/bt_kit_test.c Bluetooth, SDP, HCI kit for Linux, FreeBSD, NetBSD and Win32. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ /* gcc -Wall -I. -I../includes -DOBEXFTP_DEBUG=3 -DHAVE_BLUETOOTH -o bt_kit_test bt_kit.c bt_kit_test.c */ /* on win32 add: -lws2_32 */ #include #include #include int main(int argc, char *argv[]) { int ret, i; char **list, *device; char *hci = NULL; int svclass = BTKIT_FTP_SERVICE; if (argc > 1) { hci = argv[1]; } if (argc > 2) { svclass = atoi(argv[2]); } fprintf(stderr, "Initializing stack\n"); fflush(stderr); ret = btkit_init(); /* !!! */ if (ret != 0) { fprintf(stderr, "btkit_init failed (%d)\n", ret); fflush(stderr); } fprintf(stderr, "Discovering devices\n"); fflush(stderr); list = btkit_discover(hci); /* !!! */ if (list == NULL) { fprintf(stderr, "btkit_discover failed\n"); fflush(stderr); } else { for (i=0 ; list[i]; i++) { fprintf(stderr, "device %d: \"%s\"\n", i, list[i]); fflush(stderr); device = btkit_getname(hci, list[i]); /* !!! */ fprintf(stderr, "bt name %d: \"%s\"\n", i, device); fflush(stderr); ret = btkit_browse(hci, list[i], svclass); /* !!! */ fprintf(stderr, "service channel: %i\n", ret); fflush(stderr); } free(list); } fprintf(stderr, "Disposing stack\n"); fflush(stderr); ret = btkit_exit(); /* !!! */ if (ret != 0) { fprintf(stderr, "btkit_exit failed (%d)\n", ret); fflush(stderr); } return 0; } obexftp-0.24.2-Source/obexftp/object.h000644 001750 001750 00000004265 11776125712 020724 0ustar00hendrikhendrik000000 000000 /** \file obexftp/object.h Collection of functions to build common OBEX request objects. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef OBEXFTP_OBJECT_H #define OBEXFTP_OBJECT_H #include #include #ifdef __cplusplus extern "C" { #endif /** Telecom/IrMC Synchronization Service: Name Prefix. */ #define IRMC_NAME_PREFIX "telecom/" /** Telecom/IrMC Synchronization Service: Object Profile file-type. */ #define XOBEX_PROFILE "x-obex/object-profile" /** Telecom/IrMC Synchronization Service: Capability file-type. */ #define XOBEX_CAPABILITY "x-obex/capability" /** Folder Browsing Service: Folder Listing file-type. */ #define XOBEX_LISTING "x-obex/folder-listing" /** Siemens specific: app. param. for memory info. * parameter 0x01: mem installed, 0x02: free mem */ #define APPARAM_INFO_CODE '2' /*@null@*/ obex_object_t *obexftp_build_info (obex_t *obex, uint32_t conn, uint8_t opcode); /*@null@*/ obex_object_t *obexftp_build_get (obex_t *obex, uint32_t conn, const char *name, const char *type); /*@null@*/ obex_object_t *obexftp_build_rename (obex_t *obex, uint32_t conn, const char *from, const char *to); /*@null@*/ obex_object_t *obexftp_build_del (obex_t *obex, uint32_t conn, const char *name); /*@null@*/ obex_object_t *obexftp_build_setpath (obex_t *obex, uint32_t conn, const char *name, int create); /*@null@*/ obex_object_t *obexftp_build_put (obex_t *obex, uint32_t conn, const char *name, int size); #ifdef __cplusplus } #endif #endif /* OBEXFTP_OBJECT_H */ obexftp-0.24.2-Source/obexftp/bt_kit.c000644 001750 001750 00000062560 12656174435 020733 0ustar00hendrikhendrik000000 000000 /** \file obexftp/bt_kit.c Bluetooth, SDP, HCI kit for Linux, FreeBSD, NetBSD and Win32. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #include #include #include #ifdef _WIN32 #include #include #define WSA_VER_MAJOR 2 #define WSA_VER_MINOR 2 #else #include #include #include #endif /* _WIN32 */ #include "bt_kit.h" #include #ifdef HAVE_BLUETOOTH /** Nokia OBEX PC Suite Services. binary representation of 00005005-0000-1000-8000-0002ee000001 \note prefer this over FTP on Series 60 devices */ #define __SVC_UUID_PCSUITE_bytes \ { 0x00, 0x00, 0x50, 0x05, \ 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, \ 0x00, 0x02, 0xee, 0x00, 0x00, 0x01 } #define SVC_UUID_PCSUITE ((const uint8_t []) __SVC_UUID_PCSUITE_bytes) //Nokia SyncML Server UUID 128: 00005601-0000-1000-8000-0002ee000001 /* well known services 0x1000 to 0x12FF */ #define __SVC_UUID_BASE_bytes \ { 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, \ 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB } #define SVC_UUID_BASE ((const uint8_t []) __SVC_UUID_BASE_bytes) /* 0x0001: server; 0x0002: client; 0x0003: DM server; 0x0004: DM client */ #define __SVC_UUID_SYNCML_bytes \ { 0x00, 0x00, 0x00, 0x00, \ 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, \ 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 } #define SVC_UUID_SYNCML ((const uint8_t []) __SVC_UUID_SYNCML_bytes) /** Allocate and setup the network stack. \note Needed for win32 winsock compatibility. */ int btkit_init(void) { #ifdef _WIN32 WORD wVersionRequired = MAKEWORD(WSA_VER_MAJOR,WSA_VER_MINOR); WSADATA lpWSAData; if (WSAStartup(wVersionRequired, &lpWSAData) != 0) { DEBUG(2, "%s: WSAStartup failed (%d)\n", __func__, WSAGetLastError()); return -1; } if (LOBYTE(lpWSAData.wVersion) != WSA_VER_MAJOR || HIBYTE(lpWSAData.wVersion) != WSA_VER_MINOR) { DEBUG(2, "%s: WSA version mismatch\n", __func__); WSACleanup(); return -1; } #endif /* _WIN32 */ return 0; } /** Tear-down and free the network stack. \note Needed for win32 winsock compatibility. */ int btkit_exit(void) { #ifdef _WIN32 if (WSACleanup() != 0) { DEBUG(2, "%s: WSACleanup failed (%d)\n", __func__, WSAGetLastError()); return -1; } #endif /* _WIN32 */ return 0; } #ifdef _WIN32 //void baswap(bdaddr_t *dst, const bdaddr_t *src) //bdaddr_t *strtoba(const char *str) //char *batostr(const bdaddr_t *ba) /** Implementation of ba2str for winsock2. */ int ba2str(const bdaddr_t *btaddr, char *straddr) { /* WSAAddressToString() is not useful, it adds parentheses */ unsigned char *b = btaddr; return sprintf(straddr, "%2.2X:%2.2X:%2.2X:%2.2X:%2.2X:%2.2X", b[7], b[6], b[5], b[4], b[3], b[2]); } /** Implementation of str2ba for winsock2. */ int str2ba(const char *straddr, bdaddr_t *btaddr) { int i; unsigned int aaddr[6]; bdaddr_t tmpaddr = 0; if (sscanf(straddr, "%02x:%02x:%02x:%02x:%02x:%02x", &aaddr[0], &aaddr[1], &aaddr[2], &aaddr[3], &aaddr[4], &aaddr[5]) != 6) return 1; *btaddr = 0; for (i = 0; i < 6; i++) { tmpaddr = (bdaddr_t) (aaddr[i] & 0xff); *btaddr = ((*btaddr) << 8) + tmpaddr; } return 0; } char **btkit_discover(const char *src) { unsigned int ret; WSAQUERYSET querySet; char addressAsString[18]; char **res, **p; memset(&querySet, 0, sizeof(querySet)); querySet.dwSize = sizeof(querySet); querySet.dwNameSpace = NS_BTH; HANDLE hLookup; DWORD flags = LUP_CONTAINERS | LUP_FLUSHCACHE | LUP_RETURN_ADDR | LUP_RES_SERVICE; ret = WSALookupServiceBegin(&querySet, flags, &hLookup); if (ret != 0) { DEBUG(2, "%s: WSALookupServiceBegin failed (%d)\n", __func__, WSAGetLastError()); } p = res = calloc(15 + 1, sizeof(char *)); for (;;) { BYTE buffer[1000]; DWORD bufferLength = sizeof(buffer); WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer; ret = WSALookupServiceNext(hLookup, flags, &bufferLength, pResults); if (GetLastError() == WSA_E_NO_MORE) { break; } if (ret != 0) { DEBUG(2, "%s: WSALookupServiceNext failed (%d)\n", __func__, WSAGetLastError()); } ba2str(pResults->lpcsaBuffer->RemoteAddr.lpSockaddr, addressAsString); DEBUG(3, "%s: Found\t%s\n", __func__, addressAsString); *p++ = strdup(addressAsString); } ret = WSALookupServiceEnd(hLookup); if (ret != 0) { DEBUG(2, "%s: WSALookupServiceEnd failed (%d)\n", __func__, WSAGetLastError()); } return res; } char *btkit_getname(const char *src, const char *addr) { unsigned int ret; WSAQUERYSET querySet; char addressAsString[18]; char *res = NULL; memset(&querySet, 0, sizeof(querySet)); querySet.dwSize = sizeof(querySet); querySet.dwNameSpace = NS_BTH; HANDLE hLookup; DWORD flags = LUP_CONTAINERS | LUP_FLUSHCACHE | LUP_RETURN_ADDR | LUP_RES_SERVICE; ret = WSALookupServiceBegin(&querySet, flags, &hLookup); if (ret != 0) { DEBUG(2, "%s: WSALookupServiceBegin failed (%d)\n", __func__, WSAGetLastError()); } for (;;) { BYTE buffer[1000]; DWORD bufferLength = sizeof(buffer); WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer; ret = WSALookupServiceNext(hLookup, flags | LUP_RETURN_NAME, &bufferLength, pResults); if (GetLastError() == WSA_E_NO_MORE) { break; } if (ret != 0) { DEBUG(2, "%s: WSALookupServiceNext failed (%d)\n", __func__, WSAGetLastError()); } ba2str(pResults->lpcsaBuffer->RemoteAddr.lpSockaddr, addressAsString); if (!strcmp(addressAsString, addr)) { DEBUG(3, "%s: Found\t%s\n", __func__, pResults->lpszServiceInstanceName); res = pResults->lpszServiceInstanceName; break; } DEBUG(3, "%s: Skipping\t%s\n", __func__, pResults->lpszServiceInstanceName); } ret = WSALookupServiceEnd(hLookup); if (ret != 0) { DEBUG(2, "%s: WSALookupServiceEnd failed (%d)\n", __func__, WSAGetLastError()); } return res; } int btkit_browse(const char *src, const char *addr, int svclass) { unsigned int ret; int port = 0; WSAQUERYSET querySet; char addressAsString[20]; // "(XX:XX:XX:XX:XX:XX)" snprintf(addressAsString, 20, "(%s)", addr); if (!addr || strlen(addr) != 17) { DEBUG(1, "%s: bad address\n", __func__); return -1; } if ((svclass<0x0001 || svclass>0x0004) && (svclass<0x1000 || svclass>0x12FF)) { DEBUG(1, "%s: bad service class\n", __func__); return -1; } GUID baseServiceClassId = { 0x00000000, 0x0000, 0x1000, { 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB } }; // Bluetooth_Base_UUID baseServiceClassId.Data1 = svclass; GUID syncmlClassId = { 0x00000000, 0x0000, 0x1000, { 0x80, 0x00, 0x00, 0x02, 0xEE, 0x00, 0x00, 0x02 } }; // common UUID for SyncML Client/Server syncmlClassId.Data1 = svclass; memset(&querySet, 0, sizeof(querySet)); querySet.dwSize = sizeof(querySet); querySet.dwNameSpace = NS_BTH; if (svclass>=0x0001 && svclass<=0x0004) querySet.lpServiceClassId = &syncmlClassId; else querySet.lpServiceClassId = &baseServiceClassId; querySet.lpszContext = addressAsString; HANDLE hLookup; DWORD flags = LUP_NOCONTAINERS | LUP_FLUSHCACHE | LUP_RETURN_ADDR | LUP_RES_SERVICE | LUP_RETURN_NAME; ret = WSALookupServiceBegin(&querySet, flags, &hLookup); if (ret != 0) { DEBUG(2, "%s: WSALookupServiceBegin failed (%d)\n", __func__, WSAGetLastError()); return -1; } for (;;) { BYTE buffer[4000]; DWORD bufferLength = sizeof(buffer); WSAQUERYSET *pResults = (WSAQUERYSET*)&buffer; ret = WSALookupServiceNext(hLookup, flags, &bufferLength, pResults); if (GetLastError() == WSA_E_NO_MORE) { break; } if (ret != 0) { DEBUG(2, "%s: WSALookupServiceNext failed (%d)\n", __func__, WSAGetLastError()); break; } port = ((SOCKADDR_BTH*)pResults->lpcsaBuffer->RemoteAddr.lpSockaddr)->port; DEBUG(3, "%s: Found\t%s\t%li\n", __func__, pResults->lpszServiceInstanceName, port); } ret = WSALookupServiceEnd(hLookup); if (ret != 0) { DEBUG(2, "%s: WSALookupServiceEnd failed (%d)\n", __func__, WSAGetLastError()); return -1; } return port; } int btkit_register_obex(int UNUSED(svclass), int UNUSED(channel)) { DEBUG(1, "Implement this stub."); return -1; } int btkit_unregister_service(int UNUSED(svclass)) { DEBUG(1, "Implement this stub."); return -1; } #else /* _WIN32 */ #ifdef HAVE_SDP #if defined(__NetBSD__) || defined(__FreeBSD__) char **btkit_discover(const char *src) { struct bt_devinquiry *di; char **res; int num_rsp = 10; int length = 8; int i; DEBUG(2, "%s: Scanning ...\n", __func__); num_rsp = bt_devinquiry(src, length, num_rsp, &di); if(num_rsp < 0) { DEBUG(1, "%s: Inquiry failed\n", __func__); return NULL; } res = calloc(num_rsp + 1, sizeof(char *)); for(i = 0; i < num_rsp; i++) { res[i] = bt_malloc(18); /* size of text bdaddr */ bt_ntoa(&di->bdaddr, res[i]); DEBUG(2, "%s: Found\t%s\n", __func__, res[i]); } free(di); return res; } static int btkit_getname_cb(int UNUSED(s), const struct bt_devinfo *di, void *arg) { if ((di->enabled)) { strncpy(arg, di->devname, HCI_DEVNAME_SIZE); return 1; } return 0; } char *btkit_getname(const char *src, const char *addr) { hci_remote_name_req_cp cp; hci_remote_name_req_compl_ep ep; struct bt_devreq req; int s; return_val_if_fail(addr != NULL, NULL); if (!src) { if (bt_devenum(btkit_getname_cb, ep.name) == -1) { DEBUG(1, "%s: device enumeration failed\n", __func__); return NULL; } src = (const char *)ep.name; } s = bt_devopen(src, 0); if (s == -1) { DEBUG(1, "%s: HCI device open failed\n", __func__); return NULL; } memset(&cp, 0, sizeof(cp)); bt_aton(addr, &cp.bdaddr); memset(&req, 0, sizeof(req)); req.opcode = HCI_CMD_REMOTE_NAME_REQ; req.cparam = &cp; req.clen = sizeof(cp); req.event = HCI_EVENT_REMOTE_NAME_REQ_COMPL; req.rparam = &ep; req.rlen = sizeof(ep); if (bt_devreq(s, &req, 100) == -1) { DEBUG(1, "%s: remote name request failed\n", __func__); strcpy(ep.name, "No Name"); } close(s); return strndup(ep.name, sizeof(ep.name)); } static int btkit_browse_sdp(sdp_session_t ss, uuid_t *uuid) { uint8_t buf[19]; /* enough for uuid128 (ssp) and uint16 (ail) */ sdp_data_t seq, ssp, ail, rsp, rec, value, pdl; uintmax_t channel; uint16_t attr; seq.next = buf; seq.end = buf + sizeof(buf); /* build ServiceSearchPattern */ ssp.next = seq.next; sdp_put_uuid(&seq, uuid); ssp.end = seq.next; /* build AttributeIDList */ ail.next = seq.next; sdp_put_uint16(&seq, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST); ail.end = seq.next; if (!sdp_service_search_attribute(ss, &ssp, &ail, &rsp)) { DEBUG(1, "%s: SDP service search failed\n", __func__); return -1; } /* * we expect the response to contain a list of records * containing ProtocolDescriptorList. Return the first * one with a valid RFCOMM channel. */ while (sdp_get_seq(&rsp, &rec)) { if (!sdp_get_attr(&rec, &attr, &value) || attr != SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST) continue; /* drop any alt header */ sdp_get_alt(&value, &value); /* for each protocol stack */ while (sdp_get_seq(&value, &pdl)) { /* and for each protocol */ while (sdp_get_seq(&pdl, &seq)) { /* check for RFCOMM */ if (sdp_match_uuid16(&seq, SDP_UUID_PROTOCOL_RFCOMM) && sdp_get_uint(&seq, &channel) && channel >= RFCOMM_CHANNEL_MIN && channel <= RFCOMM_CHANNEL_MAX) return channel; } } } DEBUG(1, "%s: no channel found\n", __func__); return -1; } int btkit_browse(const char *src, const char *addr, int svclass) { bdaddr_t laddr, raddr; sdp_session_t ss; uuid_t uuid; int channel; return_val_if_fail(addr != NULL, -1); bt_aton(addr, &raddr); if (src) { if (!bt_devaddr(src, &laddr)) { DEBUG(1, "%s: invalid source address\n", __func__); return -1; } } else { bdaddr_copy(&laddr, BDADDR_ANY); } ss = sdp_open(&laddr, &raddr); if (ss == NULL) { DEBUG(1, "%s: Failed to connect to SDP server\n", __func__); return -1; } if (svclass >= 0x0001 && svclass <= 0x0004) { uuid_dec_be(SVC_UUID_SYNCML, &uuid); uuid.time_low = svclass; } else if (svclass >= 0x1000 && svclass <= 0x12FF) { uuid_dec_be(SVC_UUID_BASE, &uuid); uuid.time_low = svclass; } else { svclass = SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER; } DEBUG(1, "%s: svclass 0x%04x\n", __func__, svclass); channel = -1; /* Try PCSUITE first */ if (svclass == SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER) { DEBUG(1, "%s: trying PCSUITE first\n", __func__); uuid_dec_be(SVC_UUID_PCSUITE, &uuid); channel = btkit_browse_sdp(ss, &uuid); uuid_dec_be(SVC_UUID_BASE, &uuid); uuid.time_low = svclass; } if (channel == -1) channel = btkit_browse_sdp(ss, &uuid); sdp_close(ss); return channel; } static sdp_session_t ss; static uint32_t opush_handle; static uint32_t ftrn_handle; static uint32_t irmc_handle; int btkit_register_obex(int svclass, int channel) { uint8_t buffer[256]; sdp_data_t rec; uint32_t *hp; DEBUG(1, "%s: svclass 0x%04x channel %d\n", __func__, svclass, channel); /* Build SDP record */ rec.next = buffer; rec.end = buffer + sizeof(buffer); sdp_put_uint16(&rec, SDP_ATTR_SERVICE_RECORD_HANDLE); sdp_put_uint32(&rec, 0x00000000); sdp_put_uint16(&rec, SDP_ATTR_SERVICE_CLASS_ID_LIST); sdp_put_seq(&rec, 3); sdp_put_uuid16(&rec, (uint16_t)svclass); sdp_put_uint16(&rec, SDP_ATTR_PROTOCOL_DESCRIPTOR_LIST); sdp_put_seq(&rec, 17); sdp_put_seq(&rec, 3); sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_L2CAP); sdp_put_seq(&rec, 5); sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_RFCOMM); sdp_put_uint8(&rec, (uint8_t)channel); sdp_put_seq(&rec, 3); sdp_put_uuid16(&rec, SDP_UUID_PROTOCOL_OBEX); sdp_put_uint16(&rec, SDP_ATTR_BROWSE_GROUP_LIST); sdp_put_seq(&rec, 3); sdp_put_uuid16(&rec, SDP_SERVICE_CLASS_PUBLIC_BROWSE_GROUP); sdp_put_uint16(&rec, SDP_ATTR_LANGUAGE_BASE_ATTRIBUTE_ID_LIST); sdp_put_seq(&rec, 9); sdp_put_uint16(&rec, 0x656e); /* "en" */ sdp_put_uint16(&rec, 106); /* UTF-8 */ sdp_put_uint16(&rec, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID); sdp_put_uint16(&rec, SDP_ATTR_BLUETOOTH_PROFILE_DESCRIPTOR_LIST); sdp_put_seq(&rec, 8); sdp_put_seq(&rec, 6); sdp_put_uuid16(&rec, (uint16_t)svclass); sdp_put_uint16(&rec, 0x0100); /* v1.0 */ sdp_put_uint16(&rec, SDP_ATTR_PRIMARY_LANGUAGE_BASE_ID + SDP_ATTR_SERVICE_NAME_OFFSET); switch (svclass) { case SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH: sdp_put_str(&rec, "OBEX Object Push", -1); sdp_put_uint16(&rec, SDP_ATTR_SUPPORTED_FORMATS_LIST); sdp_put_seq(&rec, 2); sdp_put_uint8(&rec, 0xff); /* Any */ hp = &opush_handle; break; case SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER: sdp_put_str(&rec, "OBEX File Transfer", -1); hp = &ftrn_handle; break; case SDP_SERVICE_CLASS_IR_MC_SYNC: sdp_put_str(&rec, "IrMC Sync", -1); hp = &irmc_handle; break; default: DEBUG(1, "%s: unknown svclass\n", __func__); return -1; break; } rec.end = rec.next; rec.next = buffer; /* Register service with SDP server */ if (ss == NULL) { ss = sdp_open_local(NULL); if (ss == NULL) { DEBUG(1, "%s: failed to open SDP session\n", __func__); return -1; } DEBUG(2, "%s: opened SDP session\n", __func__); } if (!sdp_record_insert(ss, NULL, hp, &rec)) { DEBUG(1, "%s: failed to insert SDP record\n", __func__); sdp_data_print(&rec, 2); return -1; } return 0; } int btkit_unregister_service(int svclass) { uint32_t *hp; if (ss == NULL) { DEBUG(1, "%s: no session open\n", __func__); return -1; } switch (svclass) { case SDP_SERVICE_CLASS_OBEX_OBJECT_PUSH: hp = &opush_handle; break; case SDP_SERVICE_CLASS_OBEX_FILE_TRANSFER: hp = &ftrn_handle; break; case SDP_SERVICE_CLASS_IR_MC_SYNC: hp = &irmc_handle; break; default: DEBUG(1, "%s: unknown svclass\n", __func__); return -1; break; } if (!sdp_record_remove(ss, *hp)) { DEBUG(1, "%s: failed to remove SDP record\n", __func__); return -1; } *hp = 0; if (opush_handle == 0 && ftrn_handle == 0 && irmc_handle == 0) { DEBUG(2, "%s: closed SDP session\n", __func__); sdp_close(ss); ss = NULL; } return 0; } #else /* defined(__NetBSD__) || defined(__FreeBSD__) */ /** Discover all bluetooth devices in range. \param src optional source interface address (HCI or MAC) \return an array of device addresses */ char **btkit_discover(const char *src) { char **res; inquiry_info *info = NULL; bdaddr_t bdswap; int dev_id; int num_rsp = 10; int flags = 0; int length = 8; int dd, i; /* Get local bluetooth address */ if (src && strlen(src) == 17) dev_id = hci_devid(src); else if (src) dev_id = atoi(src); else dev_id = hci_get_route(NULL); DEBUG(2, "%s: Scanning ...\n", __func__); flags = IREQ_CACHE_FLUSH; /* only show devices currently in range */ num_rsp = hci_inquiry(dev_id, length, num_rsp, NULL, &info, flags); if(num_rsp < 0) { DEBUG(1, "%s: Inquiry failed", __func__); return NULL; } dd = hci_open_dev(dev_id); if (dd < 0) { DEBUG(1, "%s: HCI device open failed", __func__); free(info); return NULL; } res = calloc(num_rsp + 1, sizeof(char *)); for(i = 0; i < num_rsp; i++) { baswap(&bdswap, &(info+i)->bdaddr); res[i] = batostr(&bdswap); DEBUG(2, "%s: Found\t%s\n", __func__, res[i]); } hci_close_dev(dd); free(info); return res; } /** Get the name of a bluetooth device. \param src optional source interface address (HCI or MAC) \param addr the bluetooth address of the device to query \return the bluetooth name of the device */ char *btkit_getname(const char *src, const char *addr) { bdaddr_t bdaddr; int dev_id, dd; char name[248]; return_val_if_fail(addr != NULL, NULL); str2ba(addr, &bdaddr); /* Get local bluetooth address */ if (src && strlen(src) == 17) dev_id = hci_devid(src); else if (src) dev_id = atoi(src); else { dev_id = hci_get_route(&bdaddr); if (dev_id < 0) dev_id = hci_get_route(NULL); } dd = hci_open_dev(dev_id); if (dd < 0) { DEBUG(1, "%s: HCI device open failed", __func__); return NULL; } if(hci_read_remote_name(dd, &bdaddr, sizeof(name), name, 100000) < 0) { strcpy(name, "No Name"); } hci_close_dev(dd); return strdup(name); } static int browse_sdp_uuid(sdp_session_t *sess, uuid_t *uuid) { sdp_list_t *attrid, *search, *seq, *loop; uint32_t range = SDP_ATTR_PROTO_DESC_LIST; /* 0x0000ffff for SDP_ATTR_REQ_RANGE */ int channel = -1; attrid = sdp_list_append(0, &range); search = sdp_list_append(0, uuid); /* Get a linked list of services */ if(sdp_service_search_attr_req(sess, search, SDP_ATTR_REQ_INDIVIDUAL, attrid, &seq) < 0) { DEBUG(1, "%s: SDP service search failed", __func__); sdp_close(sess); return -1; } sdp_list_free(attrid, 0); sdp_list_free(search, 0); /* Loop through the list of services */ for(loop = seq; loop; loop = loop->next) { sdp_record_t *rec = (sdp_record_t *) loop->data; sdp_list_t *access = NULL; /* get the RFCOMM channel */ sdp_get_access_protos(rec, &access); if(access) { channel = sdp_get_proto_port(access, RFCOMM_UUID); } } sdp_list_free(seq, 0); return channel; } /** Browse a bluetooth device for a given service class. \param src optional source interface address (HCI or MAC) \param addr the bluetooth address of the device to query \return the channel on which the service runs */ int btkit_browse(const char *src, const char *addr, int svclass) { int res = -1; int dev_id; sdp_session_t *sess; uuid_t root_uuid; bdaddr_t bdaddr; bdaddr_t adapter; if (!addr || strlen(addr) != 17) return -1; str2ba(addr, &bdaddr); /* Get local bluetooth address */ if (src && strlen(src) == 17) dev_id = hci_devid(src); else if (src) dev_id = atoi(src); else { dev_id = hci_get_route(&bdaddr); if (dev_id < 0) dev_id = hci_get_route(NULL); } if (dev_id >= 0) hci_devba(dev_id, &adapter); else bacpy(&adapter, BDADDR_ANY); /* Connect to remote SDP server */ sess = sdp_connect(&adapter, &bdaddr, SDP_RETRY_IF_BUSY); if(!sess) { DEBUG(1, "%s: Failed to connect to SDP server", __func__); return -1; } // baswap(&bdswap, &bdaddr); // *res_bdaddr = batostr(&bdswap); // fprintf(stderr, "Browsing %s ...\n", *res_bdaddr); /* special case: SyncML */ if (svclass >= 0x0001 && svclass <= 0x0004) { unsigned short data1 = svclass; sdp_uuid128_create(&root_uuid, &SVC_UUID_SYNCML); memcpy(&root_uuid.value.uuid128.data[2], &data1, 2); res = browse_sdp_uuid(sess, &root_uuid); sdp_close(sess); return res; } /* determine the service class we're looking for */ if (svclass < 0x1000 || svclass > 0x12FF) { svclass = OBEX_FILETRANS_SVCLASS_ID; } /* prefer PCSUITE over FTP */ if (svclass == OBEX_FILETRANS_SVCLASS_ID) { sdp_uuid128_create(&root_uuid, &SVC_UUID_PCSUITE); res = browse_sdp_uuid(sess, &root_uuid); if (res > 0) { sdp_close(sess); return res; } } /* browse for the service class */ sdp_uuid16_create(&root_uuid, svclass); res = browse_sdp_uuid(sess, &root_uuid); sdp_close(sess); return res; } /** Search for OBEX FTP service. \return 1 if service is found and 0 otherwise */ static sdp_record_t *sdp_search_service(sdp_session_t *sess, uint16_t service) { sdp_list_t *attrid, *srch, *rsp = NULL; uint32_t range = 0x0000ffff; uuid_t svclass; int ret; attrid = sdp_list_append(0, &range); sdp_uuid16_create(&svclass, service); srch = sdp_list_append(NULL, &svclass); ret = sdp_service_search_attr_req(sess, srch, SDP_ATTR_REQ_RANGE, attrid, &rsp); sdp_list_free(attrid, 0); sdp_list_free(srch, 0); if (ret < 0) { DEBUG(1, "Failed to search the local SDP server."); return NULL; } if (sdp_list_len(rsp) == 0) { DEBUG(1, "No records found on the local SDP server."); return NULL; } return (sdp_record_t *) rsp->data; } /** Delete a service record from the local SDP server. */ int btkit_unregister_service(int svclass) { sdp_session_t *session; sdp_record_t *record; session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); if (!session) { DEBUG(1, "Failed to connect to the local SDP server."); return -1; } record = sdp_search_service(session, svclass); if (record && sdp_record_unregister(session, record)) DEBUG(1, "Service record unregistration failed."); sdp_close(session); return 0; } /** Add a service record to the local SDP server. */ int btkit_register_obex(int service, int channel) { sdp_session_t *session; sdp_record_t *record; sdp_list_t *svclass, *pfseq, *apseq, *root, *aproto; uuid_t root_uuid, l2cap, rfcomm, obex, obexftp; sdp_profile_desc_t profile; sdp_list_t *proto[3]; sdp_data_t *v; uint8_t channel_id = 1; /* should look for a free one */ int status; if (channel > 0) channel_id = channel; session = sdp_connect(BDADDR_ANY, BDADDR_LOCAL, 0); if (!session) { DEBUG(1, "Failed to connect to the local SDP server."); return -1; } record = sdp_record_alloc(); if (!record) { DEBUG(1, "Failed to allocate service record."); sdp_close(session); return -1; } /* Register to Public Browse Group */ sdp_uuid16_create(&root_uuid, PUBLIC_BROWSE_GROUP); root = sdp_list_append(NULL, &root_uuid); sdp_set_browse_groups(record, root); sdp_list_free(root, NULL); /* Protocol Descriptor List: L2CAP */ sdp_uuid16_create(&l2cap, L2CAP_UUID); proto[0] = sdp_list_append(NULL, &l2cap); apseq = sdp_list_append(NULL, proto[0]); /* Protocol Descriptor List: RFCOMM */ sdp_uuid16_create(&rfcomm, RFCOMM_UUID); proto[1] = sdp_list_append(NULL, &rfcomm); v = sdp_data_alloc(SDP_UINT8, &channel_id); proto[1] = sdp_list_append(proto[1], v); apseq = sdp_list_append(apseq, proto[1]); /* Protocol Descriptor List: OBEX */ sdp_uuid16_create(&obex, OBEX_UUID); proto[2] = sdp_list_append(NULL, &obex); apseq = sdp_list_append(apseq, proto[2]); aproto = sdp_list_append(NULL, apseq); sdp_set_access_protos(record, aproto); sdp_list_free(proto[0], NULL); sdp_list_free(proto[1], NULL); sdp_list_free(proto[2], NULL); sdp_list_free(apseq, NULL); sdp_list_free(aproto, NULL); sdp_data_free(v); /* Service Class ID List: */ sdp_uuid16_create(&obexftp, service); svclass = sdp_list_append(NULL, &obexftp); sdp_set_service_classes(record, svclass); /* Profile Descriptor List: */ /* profile id matches service id here */ sdp_uuid16_create(&profile.uuid, service); profile.version = 0x0100; pfseq = sdp_list_append(NULL, &profile); sdp_set_profile_descs(record, pfseq); sdp_set_info_attr(record, "OBEX File Transfer", NULL, NULL); status = sdp_device_record_register(session, BDADDR_ANY, record, SDP_RECORD_PERSIST); if (status < 0) { DEBUG(1, "SDP registration failed."); sdp_record_free(record); record = NULL; sdp_close(session); return -1; } sdp_close(session); return 0; } #endif /* BlueZ/Linux */ #else #warning "no bluetooth sdp support for this platform" char **btkit_discover(const char *UNUSED(src)) { return NULL; } char *btkit_getname(const char *UNUSED(src), const char *UNUSED(addr)) { return NULL; } int btkit_browse(const char *UNUSED(src), const char *UNUSED(addr), int UNUSED(svclass)) { return -1; } int btkit_register_obex(int UNUSED(svclass), int UNUSED(channel)) { DEBUG(1, "SDP not supported."); return -1; } int btkit_unregister_service(int UNUSED(svclass)) { return -1; } #endif /* HAVE_SDP */ #endif /* _WIN32 */ #else #warning "bluetooth not available" #endif /* HAVE_BLUETOOTH */ obexftp-0.24.2-Source/obexftp/obexftp_io.c000644 001750 001750 00000014261 12006042732 021567 0ustar00hendrikhendrik000000 000000 /** \file obexftp/obexftp_io.c ObexFTP IO abstraction implementation. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include "obexftp_io.h" #include "unicode.h" #include #ifdef _WIN32 #define S_IRGRP 0 #define S_IROTH 0 #define S_IXGRP 0 #define S_IXOTH 0 #endif #define DEFFILEMOD (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) /* 0644 */ #define DEFXFILEMOD (DEFFILEMOD | S_IXGRP | S_IXUSR | S_IXOTH) /* 0755 */ /* Get some file-info. (size and lastmod) */ /* lastmod needs to have at least 21 bytes */ static int get_fileinfo(const char *name, char *lastmod) { struct stat stats; struct tm *tm; if ((0 == stat(name, &stats)) && ((tm = gmtime(&stats.st_mtime)) != NULL)) { (void) snprintf(lastmod, 21, "%04d-%02d-%02dT%02d:%02d:%02dZ", tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); return (int) stats.st_size; } return -1; } /* Create an object from a file. Attach some info-headers to it */ obex_object_t *build_object_from_file(obex_t *obex, uint32_t conn, const char *localname, const char *remotename) { obex_object_t *object; obex_headerdata_t hv; uint8_t *ucname; int ucname_len, size; char lastmod[] = "11997700--0011--0011TT0000::0000::0000ZZ."; /* Get filesize and modification-time */ size = get_fileinfo(localname, lastmod); object = OBEX_ObjectNew(obex, OBEX_CMD_PUT); if(object == NULL) return NULL; if(conn != 0xffffffff) { hv.bq4 = conn; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_CONNECTION, hv, sizeof(uint32_t), OBEX_FL_FIT_ONE_PACKET); } ucname_len = strlen(remotename)*2 + 2; ucname = malloc(ucname_len); if(ucname == NULL) { (void) OBEX_ObjectDelete(obex, object); return NULL; } ucname_len = CharToUnicode(ucname, (uint8_t*)remotename, ucname_len); hv.bs = ucname; (void ) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_NAME, hv, ucname_len, 0); free(ucname); hv.bq4 = (const uint32_t) size; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_LENGTH, hv, sizeof(uint32_t), 0); #if 0 /* Win2k excpects this header to be in unicode. I suspect this in incorrect so this will have to wait until that's investigated */ hv.bs = (const uint8_t *) lastmod; OBEX_ObjectAddHeader(obex, object, OBEX_HDR_TIME, hv, strlen(lastmod)+1, 0); #endif hv.bs = (const uint8_t *) NULL; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_BODY, hv, 0, OBEX_FL_STREAM_START); DEBUG(3, "%s() Lastmod = %s\n", __func__, lastmod); return object; } /* Check for dangerous filenames. */ static int nameok(const char *name) { DEBUG(3, "%s() \n", __func__); return_val_if_fail (name != NULL, FALSE); /* No abs paths */ if(name[0] == '/') return FALSE; if(strlen(name) >= 3) { /* "../../vmlinuz" */ if(name[0] == '.' && name[1] == '.' && name[2] == '/') return FALSE; /* "dir/../../../vmlinuz" */ if(strstr(name, "/../") != NULL) return FALSE; } return TRUE; } /* Concatenate two pathnames. */ /* The first path may be NULL. */ /* The second path is always treated relative. */ static int pathncat(/*@unique@*/ char *dest, const char *path, const char *name, size_t n) { size_t len; if(name == NULL) return -EINVAL; while(*name == '/') name++; if((path == NULL) || (*path == '\0')) { strncpy(dest, name, n); dest[n - 1] = '\0'; } else { strncpy(dest, path, n); dest[n - 1] = '\0'; len = strlen(dest); if (len >= n - 1) return -ENOMEM; if (dest[len - 1] != '/') { dest[len] = '/'; dest[len + 1] = '\0'; } strncat(dest, name, n - strlen(dest) - 1); } return 0; } /* Open a file, but do some sanity-checking first. */ int open_safe(const char *path, const char *name) { char *diskname; size_t maxlen; int fd; DEBUG(3, "%s() \n", __func__); /* Check for dangerous filenames */ if(nameok(name) == FALSE) return -1; /* TODO! Rename file if already exist. */ maxlen = strlen(name) + 1; if (path) maxlen += strlen(path); diskname = malloc(maxlen); if(!diskname) return -1; (void) pathncat(diskname, path, name, maxlen); DEBUG(3, "%s() Creating file %s\n", __func__, diskname); fd = open(diskname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMOD); free(diskname); return fd; } /* Go to a directory. Create if not exists and create is true. */ int checkdir(const char *path, const char *dir, int create, int allowabs) { char *newpath; size_t maxlen; struct stat statbuf; int ret = -1; if(!allowabs) { if(nameok(dir) == FALSE) return -1; } if(!dir) return 1; maxlen = strlen(dir) + 1; if (path) maxlen += strlen(path); newpath = malloc(maxlen); if(!newpath) return -1; (void) pathncat(newpath, path, dir, maxlen); DEBUG(3, "%s() path = %s dir = %s, create = %d, allowabs = %d\n", __func__, path, dir, create, allowabs); if(stat(newpath, &statbuf) == 0) { /* If this directory aleady exist we are done */ if(S_ISDIR(statbuf.st_mode)) { DEBUG(3, "%s() Using existing dir\n", __func__); free(newpath); return 1; } else { /* A non-directory with this name already exist. */ DEBUG(3, "%s() A non-dir called %s already exist\n", __func__, newpath); free(newpath); return -1; } } if(create) { DEBUG(3, "%s() Will try to create %s\n", __func__, newpath); #ifdef _WIN32 ret = mkdir(newpath); #else ret = mkdir(newpath, DEFXFILEMOD); #endif } else { ret = -1; } free(newpath); return ret; } obexftp-0.24.2-Source/obexftp/client.c000644 001750 001750 00000102222 12656173100 020707 0ustar00hendrikhendrik000000 000000 /** \file obexftp/client.c ObexFTP client API implementation. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #include #include #include #include #include #include #include #include #include #ifdef _WIN32 #define O_BINARY (_O_BINARY) #define CREATE_MODE_FILE (S_IRUSR|S_IWUSR) #else #include #include #include #define O_BINARY (0) #define CREATE_MODE_FILE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) #endif /* _WIN32 */ #ifdef HAVE_BLUETOOTH #include "bt_kit.h" #else #define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT #endif /* HAVE_BLUETOOTH */ #include #include #include "obexftp.h" #include "client.h" #include "object.h" #include "obexftp_io.h" #include "uuid.h" #include "cache.h" #include #pragma pack(1) typedef struct { /* fixed to 6 bytes for now */ uint8_t code; uint8_t info_len; uint8_t info[4]; } apparam_t; #pragma pack() /** Empty callback used as default. */ static void dummy_info_cb(int UNUSED(event), const char *UNUSED(msg), int UNUSED(len), void *UNUSED(data)) { /* do nothing */ } /** Normalize the path argument. \note wont turn relative paths into (most likely wrong) absolute ones. wont expand "../" or "./". */ /* static char *normalize_file_path(const char *name) { char *p, *copy; return_val_if_fail(name != NULL, NULL); p = copy = malloc(strlen(name) + 1); / * cant be longer, can it? * / / * if (OBEXFTP_USE_LEADING_SLASH(quirks)) *p++ = '/'; while (*name == '/') name++; * / while (*name) { if (*name == '/') { *p++ = *name++; while (*name == '/') name++; } else { *p++ = *name++; } } *p = '\0'; return copy; } */ /** Normalize the path argument and split into pathname and basename. \note Wont turn relative paths into (most likely wrong) absolute ones. Wont expand "../" or "./". Will keep "telecom" prefix. \warning Do not use this function if there is no slash in the argument! */ static void split_file_path(const char *name, /*@only@*/ char **basepath, /*@only@*/ char **basename) { char *p; const char *tail; return_if_fail(name != NULL); for (tail = name; *tail == '/'; tail++); if (!strncmp(tail, "telecom/", 8)) { *basename = strdup(tail); /* keep whole path */ *basepath = strdup(""); /* cd top */ return; } tail = strrchr(name, '/'); if (tail) tail++; else tail = name; if (basename) *basename = strdup(tail); if (!basepath) return; p = *basepath = malloc(strlen(name) + 1); /* cant be longer, can it? */ /* if (OBEXFTP_USE_LEADING_SLASH(quirks)) *p++ = '/'; while (*name == '/') name++; */ while (*name && name < tail) { if (*name == '/') { *p++ = *name++; while (*name == '/') name++; } else { *p++ = *name++; } } /* if (p > *basepath && *(p-1) == '/') p--; if (OBEXFTP_USE_TRAILING_SLASH(quirks)) *p++ = '/'; */ *p = '\0'; } /** Add more data from memory to stream. */ static int cli_fillstream_from_memory(obexftp_client_t *cli, obex_object_t *object) { obex_headerdata_t hv; int actual = cli->out_size - cli->out_pos; if (actual > STREAM_CHUNK) actual = STREAM_CHUNK; DEBUG(3, "%s() Read %d bytes\n", __func__, actual); if(actual > 0) { /* Read was ok! */ hv.bs = (const uint8_t *) &cli->out_data[cli->out_pos]; (void) OBEX_ObjectAddHeader(cli->obexhandle, object, OBEX_HDR_BODY, hv, actual, OBEX_FL_STREAM_DATA); cli->out_pos += actual; } else if(actual == 0) { /* EOF */ cli->out_data = NULL; /* dont free, isnt ours */ hv.bs = (const uint8_t *) &cli->out_data[cli->out_pos]; (void) OBEX_ObjectAddHeader(cli->obexhandle, object, OBEX_HDR_BODY, hv, 0, OBEX_FL_STREAM_DATAEND); } else { /* Error */ cli->out_data = NULL; /* dont free, isnt ours */ hv.bs = (const uint8_t *) NULL; (void) OBEX_ObjectAddHeader(cli->obexhandle, object, OBEX_HDR_BODY, hv, 0, OBEX_FL_STREAM_DATA); } return actual; } /** Add more data from file to stream. */ static int cli_fillstream_from_file(obexftp_client_t *cli, obex_object_t *object) { obex_headerdata_t hv; int actual; DEBUG(3, "%s()\n", __func__); actual = read(cli->fd, cli->stream_chunk, STREAM_CHUNK); DEBUG(3, "%s() Read %d bytes\n", __func__, actual); if(actual > 0) { /* Read was ok! */ hv.bs = (const uint8_t *) cli->stream_chunk; (void) OBEX_ObjectAddHeader(cli->obexhandle, object, OBEX_HDR_BODY, hv, actual, OBEX_FL_STREAM_DATA); } else if(actual == 0) { /* EOF */ (void) close(cli->fd); cli->fd = -1; hv.bs = (const uint8_t *) cli->stream_chunk; (void) OBEX_ObjectAddHeader(cli->obexhandle, object, OBEX_HDR_BODY, hv, 0, OBEX_FL_STREAM_DATAEND); } else { /* Error */ (void) close(cli->fd); cli->fd = -1; hv.bs = (const uint8_t *) NULL; (void) OBEX_ObjectAddHeader(cli->obexhandle, object, OBEX_HDR_BODY, hv, 0, OBEX_FL_STREAM_DATA); } return actual; } /** Save body from object or return application parameters. */ static void client_done(obex_t *handle, obex_object_t *object, int UNUSED(obex_cmd), int UNUSED(obex_rsp)) { obex_headerdata_t hv; uint8_t hi; uint32_t hlen; const apparam_t *app = NULL; char *p; const uint8_t *body_data = NULL; uint32_t body_len = -1; /*@temp@*/ obexftp_client_t *cli; cli = OBEX_GetUserData(handle); DEBUG(3, "%s()\n", __func__); if (cli->fd > 0) (void) close(cli->fd); if (cli->buf_data) { DEBUG(1, "%s: Warning: buffer still active?\n", __func__); free(cli->buf_data); cli->buf_data = NULL; } while(OBEX_ObjectGetNextHeader(handle, object, &hi, &hv, &hlen)) { if(hi == OBEX_HDR_BODY) { DEBUG(3, "%s() Found body (length: %d)\n", __func__, hlen); if (cli->target_fn == NULL) { if (cli->buf_data) { DEBUG(1, "%s: Warning: purging non-empty buffer.\n", __func__); /* ok to free since we must have malloc' it right here */ free(cli->buf_data); } p = malloc(hlen + 1); if (p) { memcpy(p, hv.bs, hlen); p[hlen] = '\0'; cli->buf_size = hlen; cli->buf_data = p; } } body_len = hlen; body_data = hv.bs; cli->infocb(OBEXFTP_EV_BODY, (char *)hv.bs, hlen, cli->infocb_data); DEBUG(3, "%s() Done body\n", __func__); /* break; */ } else if(hi == OBEX_HDR_CONNECTION) { DEBUG(3, "%s() Found connection number: %d\n", __func__, hv.bq4); cli->connection_id = hv.bq4; } else if(hi == OBEX_HDR_WHO) { DEBUG(3, "%s() Sender identified\n", __func__); } else if(hi == OBEX_HDR_NAME) { DEBUG(3, "%s() Sender name\n", __func__); DEBUGBUFFER(hv.bs, hlen); } else if(hi == OBEX_HDR_APPARAM) { DEBUG(3, "%s() Found application parameters\n", __func__); if(hlen == sizeof(apparam_t)) { app = (const apparam_t *)hv.bs; /* order is network byte order (big-endian) */ cli->apparam_info = (app->info[0] << (3*8)) + (app->info[1] << (2*8)) + (app->info[2] << (1*8)) + (app->info[3] << (0*8)); cli->infocb(OBEXFTP_EV_INFO, (char*)&cli->apparam_info, 0, cli->infocb_data); } else DEBUG(3, "%s() Application parameters don't fit %d vs. %lu.\n", __func__, hlen, (unsigned long)sizeof(apparam_t)); break; } else { DEBUG(3, "%s() Skipped header %02x\n", __func__, hi); } } if(body_data) { if (body_len > 0) { if (cli->target_fn != NULL) { /* simple body writer */ int fd; //fd = open_safe("", cli-> target_fn); fd = open(cli-> target_fn, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, CREATE_MODE_FILE); if(fd > 0) { (void) write(fd, body_data, body_len); (void) close(fd); } else { DEBUG(3, "%s() Error writing body\n", __func__); } free (cli->target_fn); cli->target_fn = NULL; } else { DEBUG(3, "%s() Body not written\n", __func__); } } else { DEBUG(3, "%s() Skipping empty body\n", __func__); } } if(app) { DEBUG(3, "%s() Appcode %d, data (%d) %d\n", __func__, app->code, app->info_len, cli->apparam_info); } } /** Handle incoming event from OpenOBEX. */ static void cli_obex_event(obex_t *handle, obex_object_t *object, int UNUSED(mode), int event, int obex_cmd, int obex_rsp) { /*@temp@*/ obexftp_client_t *cli; cli = OBEX_GetUserData(handle); switch (event) { case OBEX_EV_PROGRESS: cli->infocb(OBEXFTP_EV_PROGRESS, "", 0, cli->infocb_data); break; case OBEX_EV_REQDONE: cli->finished = TRUE; if(obex_rsp == OBEX_RSP_SUCCESS) cli->success = TRUE; else { cli->success = FALSE; DEBUG(2, "%s() OBEX_EV_REQDONE: obex_rsp=%d%02d\n", __func__, obex_rsp >> 8, obex_rsp & 0xF); } cli->obex_rsp = obex_rsp; client_done(handle, object, obex_cmd, obex_rsp); break; case OBEX_EV_LINKERR: cli->finished = TRUE; cli->success = FALSE; DEBUG(2, "%s() OBEX_EV_LINKERR\n", __func__); break; case OBEX_EV_STREAMEMPTY: if (cli->out_data) (void) cli_fillstream_from_memory(cli, object); else (void) cli_fillstream_from_file(cli, object); break; default: DEBUG(1, "%s() Unknown event %d\n", __func__, event); break; } } /** Wait for the OBEX client to finish. */ static int obexftp_sync(obexftp_client_t *cli) { int ret; DEBUG(3, "%s()\n", __func__); /* cli->finished = FALSE; */ while(cli->finished == FALSE) { ret = OBEX_HandleInput(cli->obexhandle, cli->accept_timeout); DEBUG(3, "%s() OBEX_HandleInput = %d\n", __func__, ret); if (ret <= 0) { DEBUG(2, "%s() OBEX_HandleInput error: %d\n", __func__, errno); return -1; } } DEBUG(3, "%s() Done success=%d\n", __func__, cli->success); if(cli->success) return 1; else return - cli->obex_rsp; } /** Do an OBEX request synchronous. */ static int cli_sync_request(obexftp_client_t *cli, obex_object_t *object) { DEBUG(3, "%s()\n", __func__); if (cli->finished == FALSE) return -EBUSY; cli->finished = FALSE; (void) OBEX_Request(cli->obexhandle, object); return obexftp_sync (cli); } /** Create an obexftp client. \param transport the transport type that will be used \param ctrans optional custom transport (don't use) \param infocb optional info callback \param infocb_data optional info callback data \return a new allocated ObexFTP client instance, NULL on error */ obexftp_client_t *obexftp_open(int transport, /*const*/ obex_ctrans_t *ctrans, obexftp_info_cb_t infocb, void *infocb_data) { obexftp_client_t *cli; DEBUG(3, "%s()\n", __func__); cli = calloc (1, sizeof(obexftp_client_t)); if(cli == NULL) return NULL; cli->finished = TRUE; cli->accept_timeout = 20; /* 20 seconds accept/reject timeout, default value */ if (infocb) cli->infocb = infocb; else cli->infocb = dummy_info_cb; cli->infocb_data = infocb_data; cli->quirks = DEFAULT_OBEXFTP_QUIRKS; cli->cache_timeout = DEFAULT_CACHE_TIMEOUT; cli->cache_maxsize = DEFAULT_CACHE_MAXSIZE; cli->fd = -1; cli->obexhandle = OBEX_Init(transport, cli_obex_event, 0); if(cli->obexhandle == NULL) { free(cli); return NULL; } cli->transport = transport; if ( ctrans ) { DEBUG(2, "Custom OBEX transport requested!\n"); /* OBEX_RegisterCTransport is const to ctrans ... */ if(OBEX_RegisterCTransport(cli->obexhandle, ctrans) < 0) { DEBUG(1, "Custom transport callback-registration failed\n"); } cli->ctrans = ctrans; } OBEX_SetUserData(cli->obexhandle, cli); /* Buffer for body */ cli->stream_chunk = malloc(STREAM_CHUNK); if(cli->stream_chunk == NULL) { free(cli); return NULL; } return cli; } /** Close an obexftp client and free the resources. \param cli the obexftp_client_t to be shut done and free'd. It's save to pass NULL here. Closes the given obexftp client and frees the resources. It's recommended to set the client reference to NULL afterwards. */ void obexftp_close(obexftp_client_t *cli) { DEBUG(3, "%s()\n", __func__); return_if_fail(cli != NULL); OBEX_Cleanup(cli->obexhandle); if (cli->buf_data) { DEBUG(1, "%s: Warning: purging left-over buffer.\n", __func__); free(cli->buf_data); } cache_purge(&cli->cache, NULL); free(cli->stream_chunk); free(cli); } /** Do simple connect as client. \param cli an obexftp_client_t created by obexftp_open(). \param device the device address to connect to (transport specific) \param port the port/channel for the device address \param uuid UUID string for CONNECT (no default) \param uuid_len length of the UUID string (excluding terminating zero) \return the result of the CONNECT request, -1 on error \note Wrapper function for obexftp_connect_src() \warning Always use a UUID (except for OBEX PUSH) */ int obexftp_connect_uuid(obexftp_client_t *cli, const char *device, int port, const uint8_t uuid[], uint32_t uuid_len) { return obexftp_connect_src(cli, NULL, device, port, uuid, uuid_len); } int obexftp_connect_service(obexftp_client_t *cli, const char *src, const char *device, int port, int service) { const uint8_t *uuid = NULL; uint32_t uuid_len = 0; if (service == OBEX_FTP_SERVICE) { uuid = UUID_FBS; uuid_len = sizeof(UUID_FBS); } if (service == OBEX_SYNC_SERVICE) { uuid = UUID_IRMC; uuid_len = sizeof(UUID_IRMC); } // otherwiese default to OBEX_PUSH_SERVICE return obexftp_connect_src(cli, src, device, port, uuid, uuid_len); } /** Connect this ObexFTP client using a given source address by sending an OBEX CONNECT request. \param cli an obexftp_client_t created by obexftp_open(). \param src optional local source interface address (transport specific) \param device the device address to connect to (transport specific) \param port the port/channel for the device address \param uuid UUID string for CONNECT (no default) \param uuid_len length of the UUID string (excluding terminating zero) \return the result of the CONNECT request, -1 on error \note Always use a UUID (except for OBEX PUSH) */ int obexftp_connect_src(obexftp_client_t *cli, const char *src, const char *device, int port, const uint8_t uuid[], uint32_t uuid_len) { struct sockaddr_in peer; #ifdef HAVE_BLUETOOTH char *devicedup, *devicep; bdaddr_t bdaddr, src_addr; #endif #ifdef HAVE_USB int obex_intf_cnt; #endif obex_object_t *object; obex_headerdata_t hv; int ret = -1; /* no connection yet */ DEBUG(3, "%s()\n", __func__); return_val_if_fail(cli != NULL, -EINVAL); cli->infocb(OBEXFTP_EV_CONNECTING, "", 0, cli->infocb_data); switch (cli->transport) { case OBEX_TRANS_IRDA: ret = IrOBEX_TransportConnect(cli->obexhandle, "OBEX"); DEBUG(3, "%s() IR %d\n", __func__, ret); break; case OBEX_TRANS_INET: if (!device) { ret = -EINVAL; break; } #ifdef _WIN32 peer.sin_addr.s_addr = inet_addr(device); ret = (peer.sin_addr.s_addr == INADDR_NONE) ? 0 : 1; #else ret = inet_aton(device, &peer.sin_addr); #endif if (ret) { peer.sin_family = AF_INET; peer.sin_port = htons(port); /* overridden with OBEX_PORT 650 anyhow */ ret = TcpOBEX_TransportConnect(cli->obexhandle, (struct sockaddr *) &peer, sizeof(struct sockaddr_in)); DEBUG(3, "%s() TCP %d\n", __func__, ret); } else ret = -EINVAL; /* is there a better errno? */ break; case OBEX_TRANS_CUSTOM: /* don't change the custom transport once it is in place */ if (cli->ctrans == NULL) { cli->ctrans = cobex_ctrans (device); if(OBEX_RegisterCTransport(cli->obexhandle, cli->ctrans) < 0) { DEBUG(1, "Custom transport callback-registration failed\n"); } } ret = OBEX_TransportConnect(cli->obexhandle, NULL, 0); DEBUG(3, "%s() TC %d\n", __func__, ret); break; #ifdef HAVE_BLUETOOTH case OBEX_TRANS_BLUETOOTH: if (!src) { bacpy(&src_addr, BDADDR_ANY); } #if defined(_WIN32) /* nothing */ #elif defined(__NetBSD__) || defined(__FreeBSD__) else if (bt_devaddr(src, &src_addr)) { } #else else if (!strncmp(src, "hci", 3)) { hci_devba(atoi(src + 3), &src_addr); } else if (atoi(src) != 0) { hci_devba(atoi(src), &src_addr); } #endif else { str2ba(src, &src_addr); } if (!device) { ret = -EINVAL; break; } if (port < 1) { port = obexftp_browse_bt(device, OBEX_FTP_SERVICE); } /* transform some chars to colons */ devicedup = devicep = strdup(device); for (; *devicep; devicep++) { if (*devicep == '-') *devicep = ':'; if (*devicep == '_') *devicep = ':'; if (*devicep == '/') *devicep = ':'; } (void) str2ba(devicedup, &bdaddr); free(devicedup); ret = BtOBEX_TransportConnect(cli->obexhandle, &src_addr, &bdaddr, (uint8_t)port); DEBUG(3, "%s() BT %d\n", __func__, ret); break; #endif /* HAVE_BLUETOOTH */ #ifdef HAVE_USB case OBEX_TRANS_USB: obex_intf_cnt = OBEX_EnumerateInterfaces(cli->obexhandle); DEBUG(3, "%s() \n", __func__); if (obex_intf_cnt <= 0) { DEBUG(1, "%s() there are no valid USB interfaces\n", __func__); ret = -EINVAL; /* is there a better errno? */ } else if (port >= obex_intf_cnt) { DEBUG(1, "%s() %d is an invalid USB interface number\n", __func__, port); ret = -EINVAL; /* is there a better errno? */ } else { obex_interface_t *obex_intf; obex_intf = OBEX_GetInterfaceByIndex(cli->obexhandle, port); ret = OBEX_InterfaceConnect(cli->obexhandle, obex_intf); } DEBUG(3, "%s() USB %d\n", __func__, ret); break; #endif /* HAVE_USB */ default: ret = -ESOCKTNOSUPPORT; break; } if (ret < 0) { /* could be -EBUSY or -ESOCKTNOSUPPORT */ cli->infocb(OBEXFTP_EV_ERR, "connect", 0, cli->infocb_data); return ret; } #ifdef COMPAT_S45 // try S45 UUID first. object = OBEX_ObjectNew(cli->obexhandle, OBEX_CMD_CONNECT); hv.bs = UUID_S45; if(OBEX_ObjectAddHeader(cli->obexhandle, object, OBEX_HDR_TARGET, hv, sizeof(UUID_S45), OBEX_FL_FIT_ONE_PACKET) < 0) { DEBUG(1, "Error adding header\n"); OBEX_ObjectDelete(cli->obexhandle, object); return -1; } cli->connection_id = 0xffffffff; ret = cli_sync_request(cli, object); if(ret < 0) { cli->infocb(OBEXFTP_EV_ERR, "S45 UUID", 0, cli->infocb_data); #endif object = OBEX_ObjectNew(cli->obexhandle, OBEX_CMD_CONNECT); if (uuid) { hv.bs = uuid; if(OBEX_ObjectAddHeader(cli->obexhandle, object, OBEX_HDR_TARGET, hv, uuid_len, OBEX_FL_FIT_ONE_PACKET) < 0) { DEBUG(1, "Error adding header\n"); OBEX_ObjectDelete(cli->obexhandle, object); return -1; } } cli->connection_id = 0xffffffff; ret = cli_sync_request(cli, object); if (!OBEXFTP_USE_CONN_HEADER(cli->quirks)) cli->connection_id = 0xffffffff; #ifdef COMPAT_S45 } #endif if(ret < 0) cli->infocb(OBEXFTP_EV_ERR, "send UUID", 0, cli->infocb_data); else cli->infocb(OBEXFTP_EV_OK, "", 0, cli->infocb_data); return ret; } /** Disconnect this ObexFTP client by sending an OBEX DISCONNECT request. \param cli an obexftp_client_t created by obexftp_open(). \return the result of the DISCONNECT request */ int obexftp_disconnect(obexftp_client_t *cli) { obex_object_t *object; obex_headerdata_t hv; int ret; DEBUG(3, "%s()\n", __func__); return_val_if_fail(cli != NULL, -EINVAL); cli->infocb(OBEXFTP_EV_DISCONNECTING, "", 0, cli->infocb_data); object = OBEX_ObjectNew(cli->obexhandle, OBEX_CMD_DISCONNECT); if(cli->connection_id != 0xffffffff) { hv.bq4 = cli->connection_id; (void) OBEX_ObjectAddHeader(cli->obexhandle, object, OBEX_HDR_CONNECTION, hv, sizeof(uint32_t), OBEX_FL_FIT_ONE_PACKET); } ret = cli_sync_request(cli, object); if(ret < 0) cli->infocb(OBEXFTP_EV_ERR, "disconnect", 0, cli->infocb_data); else cli->infocb(OBEXFTP_EV_OK, "", 0, cli->infocb_data); /* don't -- obexftp_close will handle this with OBEX_Cleanup */ /* OBEX_TransportDisconnect(cli->obexhandle); */ return ret; } /** Send a custom Siemens OBEX app info opcode. \param cli an obexftp_client_t created by obexftp_open(). \param opcode the info opcode, 0x01 to inquire installed memory, 0x02 to get free memory \return the result of the app info request */ int obexftp_info(obexftp_client_t *cli, uint8_t opcode) { obex_object_t *object = NULL; int ret; return_val_if_fail(cli != NULL, -EINVAL); cli->infocb(OBEXFTP_EV_RECEIVING, "info", 0, cli->infocb_data); DEBUG(2, "%s() Retrieving info %d\n", __func__, opcode); object = obexftp_build_info (cli->obexhandle, cli->connection_id, opcode); if(object == NULL) return -1; ret = cli_sync_request(cli, object); if(ret < 0) { cli->infocb(OBEXFTP_EV_ERR, "info", 0, cli->infocb_data); } else cli->infocb(OBEXFTP_EV_OK, "info", 0, cli->infocb_data); return ret; } /** Send an OBEX GET with optional TYPE. Directories will be changed into first if split path quirk is set. \param cli an obexftp_client_t created by obexftp_open(). \param type OBEX TYPE of the request \param localname optional file to write \param remotename OBEX NAME to request \return the result of GET request \note \a localname and \a remotename may be null. */ int obexftp_get_type(obexftp_client_t *cli, const char *type, const char *localname, const char *remotename) { obex_object_t *object = NULL; int ret; return_val_if_fail(cli != NULL, -EINVAL); return_val_if_fail(remotename != NULL || type != NULL, -EINVAL); if (cli->buf_data) { DEBUG(1, "%s: Warning: buffer still active?\n", __func__); free(cli->buf_data); cli->buf_data = NULL; } cli->infocb(OBEXFTP_EV_RECEIVING, remotename, 0, cli->infocb_data); if (localname && *localname) cli->target_fn = strdup(localname); else cli->target_fn = NULL; if (OBEXFTP_USE_SPLIT_SETPATH(cli->quirks) && remotename && strchr(remotename, '/')) { char *basepath, *basename; split_file_path(remotename, &basepath, &basename); ret = obexftp_setpath(cli, basepath, 0); if(ret < 0) { cli->infocb(OBEXFTP_EV_ERR, basepath, 0, cli->infocb_data); return ret; } DEBUG(2, "%s() Getting %s -> %s (%s)\n", __func__, basename, localname, type); object = obexftp_build_get (cli->obexhandle, cli->connection_id, basename, type); free(basepath); free(basename); } else { DEBUG(2, "%s() Getting %s -> %s (%s)\n", __func__, remotename, localname, type); object = obexftp_build_get (cli->obexhandle, cli->connection_id, remotename, type); } if(object == NULL) return -1; ret = cli_sync_request(cli, object); if(ret < 0) cli->infocb(OBEXFTP_EV_ERR, remotename, 0, cli->infocb_data); else cli->infocb(OBEXFTP_EV_OK, remotename, 0, cli->infocb_data); return ret; } /** Send an custom Siemens OBEX rename request. \param cli an obexftp_client_t created by obexftp_open(). \param sourcename remote filename to be renamed \param targetname remote target filename \return the result of Siemens rename request */ int obexftp_rename(obexftp_client_t *cli, const char *sourcename, const char *targetname) { obex_object_t *object = NULL; int ret; return_val_if_fail(cli != NULL, -EINVAL); cli->infocb(OBEXFTP_EV_SENDING, sourcename, 0, cli->infocb_data); DEBUG(2, "%s() Moving %s -> %s\n", __func__, sourcename, targetname); object = obexftp_build_rename (cli->obexhandle, cli->connection_id, sourcename, targetname); if(object == NULL) return -1; cache_purge(&cli->cache, NULL); ret = cli_sync_request(cli, object); if(ret < 0) cli->infocb(OBEXFTP_EV_ERR, sourcename, 0, cli->infocb_data); else cli->infocb(OBEXFTP_EV_OK, sourcename, 0, cli->infocb_data); return ret; } /** Send an OBEX PUT with empty file name (delete). \param cli an obexftp_client_t created by obexftp_open(). \param name the remote filename/foldername to be removed. \return the result of the empty OBEX PUT request */ int obexftp_del(obexftp_client_t *cli, const char *name) { obex_object_t *object; int ret; return_val_if_fail(cli != NULL, -EINVAL); cli->infocb(OBEXFTP_EV_SENDING, name, 0, cli->infocb_data); /* split path and go there first */ if (OBEXFTP_USE_SPLIT_SETPATH(cli->quirks) && name && strchr(name, '/')) { char *basepath, *basename; split_file_path(name, &basepath, &basename); ret = obexftp_setpath(cli, basepath, 0); if(ret < 0) { cli->infocb(OBEXFTP_EV_ERR, basepath, 0, cli->infocb_data); return ret; } DEBUG(2, "%s() Deleting %s\n", __func__, basename); object = obexftp_build_del (cli->obexhandle, cli->connection_id, basename); free(basepath); free(basename); } else { DEBUG(2, "%s() Deleting %s\n", __func__, name); object = obexftp_build_del (cli->obexhandle, cli->connection_id, name); } if(object == NULL) return -1; cache_purge(&cli->cache, NULL); ret = cli_sync_request(cli, object); if(ret < 0) cli->infocb(OBEXFTP_EV_ERR, name, 0, cli->infocb_data); else cli->infocb(OBEXFTP_EV_OK, name, 0, cli->infocb_data); return ret; } /** Send OBEX SETPATH request (multiple requests if split path flag is set). \param cli an obexftp_client_t created by obexftp_open(). \param name path to change into \param create flag whether to create missing folders or fail \return the result of the OBEX SETPATH request(s). \note handles NULL, "", "/" and everything else correctly. */ int obexftp_setpath(obexftp_client_t *cli, const char *name, int create) { obex_object_t *object; int ret = 0; char *copy, *tail, *p; return_val_if_fail(cli != NULL, -EINVAL); DEBUG(2, "%s() Changing to %s\n", __func__, name); if (OBEXFTP_USE_SPLIT_SETPATH(cli->quirks) && name && *name && strchr(name, '/')) { tail = copy = strdup(name); for (p = strchr(tail, '/'); tail; ) { if (p) { *p = '\0'; p++; } cli->infocb(OBEXFTP_EV_SENDING, tail, 0, cli->infocb_data); DEBUG(2, "%s() Setpath \"%s\" (create:%d)\n", __func__, tail, create); /* try without the create flag */ object = obexftp_build_setpath (cli->obexhandle, cli->connection_id, tail, 0); ret = cli_sync_request(cli, object); if ((ret < 0) && create) { /* try again with create flag set maybe? */ object = obexftp_build_setpath (cli->obexhandle, cli->connection_id, tail, 1); ret = cli_sync_request(cli, object); } if (ret < 0) break; tail = p; if (p) p = strchr(p, '/'); /* prevent a trailing slash from messing all up with a cd top */ if (tail && *tail == '\0') break; } free (copy); } else { cli->infocb(OBEXFTP_EV_SENDING, name, 0, cli->infocb_data); DEBUG(2, "%s() Setpath \"%s\"\n", __func__, name); object = obexftp_build_setpath (cli->obexhandle, cli->connection_id, name, create); ret = cli_sync_request(cli, object); } if (create) cache_purge(&cli->cache, NULL); /* no way to know where we started */ if(ret < 0) cli->infocb(OBEXFTP_EV_ERR, name, 0, cli->infocb_data); else cli->infocb(OBEXFTP_EV_OK, name, 0, cli->infocb_data); return ret; } /** Send an OBEX PUT, optionally with (some) SETPATHs for a local file. \param cli an obexftp_client_t created by obexftp_open(). \param filename local file to send \param remotename remote name to write \return the result of the OBEX PUT (and SETPATH) request(s). \note Puts to filename's basename if remotename is NULL or ends with a slash. */ int obexftp_put_file(obexftp_client_t *cli, const char *filename, const char *remotename) { obex_object_t *object; int ret; return_val_if_fail(cli != NULL, -EINVAL); return_val_if_fail(filename != NULL, -EINVAL); if (cli->out_data) { DEBUG(1, "%s: Warning: buffer still active?\n", __func__); free(cli->buf_data); cli->buf_data = NULL; } cli->infocb(OBEXFTP_EV_SENDING, filename, 0, cli->infocb_data); // TODO: if remotename ends with a slash: add basename if (!remotename) { remotename = strrchr(filename, '/'); if (remotename) remotename++; else remotename = filename; } if (OBEXFTP_USE_SPLIT_SETPATH(cli->quirks) && remotename && strchr(remotename, '/')) { char *basepath, *basename; split_file_path(remotename, &basepath, &basename); ret = obexftp_setpath(cli, basepath, 0); if(ret < 0) { cli->infocb(OBEXFTP_EV_ERR, basepath, 0, cli->infocb_data); return ret; } DEBUG(2, "%s() Sending %s -> %s\n", __func__, filename, basename); object = build_object_from_file (cli->obexhandle, cli->connection_id, filename, basename); free(basepath); free(basename); } else { DEBUG(2, "%s() Sending %s -> %s\n", __func__, filename, remotename); object = build_object_from_file (cli->obexhandle, cli->connection_id, filename, remotename); } cli->fd = open(filename, O_RDONLY | O_BINARY, 0); if(cli->fd < 0) ret = -1; else { cli->out_data = NULL; /* dont free, isnt ours */ cache_purge(&cli->cache, NULL); ret = cli_sync_request(cli, object); } /* close(cli->fd); */ if(ret < 0) cli->infocb(OBEXFTP_EV_ERR, filename, 0, cli->infocb_data); else cli->infocb(OBEXFTP_EV_OK, filename, 0, cli->infocb_data); return ret; } /** Send memory data by OBEX PUT, optionally with (some) SETPATHs. \param cli an obexftp_client_t created by obexftp_open(). \param data data to send \param size length of the data \param remotename remote name to write \return the result of the OBEX PUT (and SETPATH) request(s). \note A remotename must be given always. */ int obexftp_put_data(obexftp_client_t *cli, const uint8_t *data, int size, const char *remotename) { obex_object_t *object; int ret; return_val_if_fail(cli != NULL, -EINVAL); return_val_if_fail(remotename != NULL, -EINVAL); if (cli->out_data) { DEBUG(1, "%s: Warning: buffer still active?\n", __func__); free(cli->buf_data); cli->buf_data = NULL; } cli->infocb(OBEXFTP_EV_SENDING, remotename, 0, cli->infocb_data); if (OBEXFTP_USE_SPLIT_SETPATH(cli->quirks) && remotename && strchr(remotename, '/')) { char *basepath, *basename; split_file_path(remotename, &basepath, &basename); ret = obexftp_setpath(cli, basepath, 0); if(ret < 0) { cli->infocb(OBEXFTP_EV_ERR, basepath, 0, cli->infocb_data); return ret; } DEBUG(2, "%s() Sending memdata -> %s\n", __func__, basename); object = obexftp_build_put (cli->obexhandle, cli->connection_id, basename, size); free(basepath); free(basename); } else { DEBUG(2, "%s() Sending memdata -> %s\n", __func__, remotename); object = obexftp_build_put (cli->obexhandle, cli->connection_id, remotename, size); } cli->out_data = data; /* memcpy would be safer */ cli->out_size = size; cli->out_pos = 0; cli->fd = -1; cache_purge(&cli->cache, NULL); ret = cli_sync_request(cli, object); if(ret < 0) cli->infocb(OBEXFTP_EV_ERR, remotename, 0, cli->infocb_data); else cli->infocb(OBEXFTP_EV_OK, remotename, 0, cli->infocb_data); return ret; } /** Simple device discovery wrappers. USB and BT only. */ static char **discover_usb() { char **res = NULL; #ifdef HAVE_USB obex_t *handle; int i, interfaces_number; if(! (handle = OBEX_Init(OBEX_TRANS_USB, cli_obex_event, 0))) { DEBUG(1, "%s() OBEX_Init failed\n", __func__); return NULL; } interfaces_number = OBEX_EnumerateInterfaces(handle); res = calloc(interfaces_number + 1, sizeof(char *)); for (i=0; i < interfaces_number; i++) { obex_interface_t *obex_intf; res[i] = malloc(201); obex_intf = OBEX_GetInterfaceByIndex(handle, i); snprintf(res[i], 200, "%d (Manufacturer: %s Product: %s Serial: %s Interface description: %s)", i, obex_intf->usb.manufacturer, obex_intf->usb.product, obex_intf->usb.serial, obex_intf->usb.control_interface); } /* OBEX_FreeInterfaces(handle); OpenOBEX 1.2 will crash */ OBEX_Cleanup(handle); #endif /* HAVE_USB */ return res; } char **obexftp_discover_bt_src(const char *src) { #ifdef HAVE_BLUETOOTH return btkit_discover(src); #else return NULL; #endif /* HAVE_BLUETOOTH */ } char *obexftp_bt_name_src(const char *addr, const char *src) { #ifdef HAVE_BLUETOOTH return btkit_getname(src, addr); #else return NULL; #endif /* HAVE_BLUETOOTH */ } int obexftp_browse_bt_src(const char *src, const char *addr, int svclass) { #ifdef HAVE_BLUETOOTH return btkit_browse(src, addr, svclass); #else return 0; #endif /* HAVE_BLUETOOTH */ } int obexftp_sdp_register(int svclass, int channel) { #ifdef HAVE_BLUETOOTH return btkit_register_obex(svclass, channel); #else return 0; #endif /* HAVE_BLUETOOTH */ } int obexftp_sdp_unregister(int svclass) { #ifdef HAVE_BLUETOOTH return btkit_unregister_service(svclass); #else return 0; #endif /* HAVE_BLUETOOTH */ } /** Device discovery wrapper for a named transport. \param transport a transport from the OBEX_TRANS_x enum. \return the discovery results as array of strings. \note USB and BT only for now. */ char **obexftp_discover(int transport) { switch (transport) { case OBEX_TRANS_BLUETOOTH: return obexftp_discover_bt(); case OBEX_TRANS_USB: return discover_usb(); default: DEBUG(1, "%s() Discovery not implemented: %d\n", __func__, transport); return NULL; } } obexftp-0.24.2-Source/obexftp/client.h000644 001750 001750 00000014522 12201733763 020724 0ustar00hendrikhendrik000000 000000 /** \file obexftp/client.h ObexFTP client API. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef OBEXFTP_CLIENT_H #define OBEXFTP_CLIENT_H #include #include #include #include #ifndef OBEX_TRANS_USB #define OBEX_TRANS_USB 6 #endif #include "obexftp.h" #include "object.h" #include "uuid.h" #ifdef __cplusplus extern "C" { #endif /* quirks */ #define OBEXFTP_LEADING_SLASH 0x01 /* used in get (and alike) */ #define OBEXFTP_TRAILING_SLASH 0x02 /* used in list */ #define OBEXFTP_SPLIT_SETPATH 0x04 /* some phones dont have a cwd */ #define OBEXFTP_CONN_HEADER 0x08 /* do we even need this? */ #define OBEXFTP_USE_LEADING_SLASH(x) ((x & OBEXFTP_LEADING_SLASH) != 0) #define OBEXFTP_USE_TRAILING_SLASH(x) ((x & OBEXFTP_TRAILING_SLASH) != 0) #define OBEXFTP_USE_SPLIT_SETPATH(x) ((x & OBEXFTP_SPLIT_SETPATH) != 0) #define OBEXFTP_USE_CONN_HEADER(x) ((x & OBEXFTP_CONN_HEADER) != 0) /* dont disable leading slashes unless you disable split setpath */ #define DEFAULT_OBEXFTP_QUIRKS \ (OBEXFTP_LEADING_SLASH | OBEXFTP_TRAILING_SLASH | OBEXFTP_SPLIT_SETPATH | OBEXFTP_CONN_HEADER) #define DEFAULT_CACHE_TIMEOUT 180 /* 3 minutes */ #define DEFAULT_CACHE_MAXSIZE 10240 /* 10k */ /* types */ typedef struct { char name[256]; mode_t mode; int size; time_t mtime; time_t atime; time_t ctime; } stat_entry_t; typedef struct cache_object cache_object_t; struct cache_object { cache_object_t *next; int refcnt; time_t timestamp; int size; /* or uint32_t */ char *name; char *content; /* or uint8_t */ stat_entry_t *stats; /* only if its a parsed directory */ }; typedef struct { /* state */ obex_t *obexhandle; uint32_t connection_id; /* set to 0xffffffff if unused */ obex_ctrans_t *ctrans; /* only valid with OBEX_TRANS_CUSTOM */ int transport; /* the transport for obexhandle */ int finished; int success; int obex_rsp; int mutex; /* should be using pthreads for this */ int quirks; /* client */ obexftp_info_cb_t infocb; void *infocb_data; /* transfer (put) */ int fd; /* used in put body */ uint8_t *stream_chunk; uint32_t out_size; uint32_t out_pos; const uint8_t *out_data; /* transfer (get) */ char *target_fn; /* used in get body */ uint32_t buf_size; /* not size but len... */ char *buf_data; uint32_t apparam_info; /* persistence */ cache_object_t *cache; int cache_timeout; int cache_maxsize; int accept_timeout; /* accept/reject timeout in seconds */ } obexftp_client_t; /* session */ /*@null@*/ obexftp_client_t *obexftp_open(int transport, /*@null@*/ /*const*/ obex_ctrans_t *ctrans, /*@null@*/ obexftp_info_cb_t infocb, /*@null@*/ void *infocb_data); void obexftp_close(/*@only@*/ /*@out@*/ /*@null@*/ obexftp_client_t *cli); int obexftp_connect_uuid(obexftp_client_t *cli, /*@null@*/ const char *device, /* for INET, BLUETOOTH */ int port, /* INET(?), BLUETOOTH, USB*/ /*@null@*/ const uint8_t uuid[], uint32_t uuid_len); int obexftp_connect_src(obexftp_client_t *cli, /*@null@*/ const char *src, /* HCI no. or address */ /*@null@*/ const char *device, /* for INET, BLUETOOTH */ int port, /* INET(?), BLUETOOTH, USB*/ /*@null@*/ const uint8_t uuid[], uint32_t uuid_len); int obexftp_connect_service(obexftp_client_t *cli, /*@null@*/ const char *src, /* HCI no. or address */ /*@null@*/ const char *device, /* for INET, BLUETOOTH */ int port, /* INET(?), BLUETOOTH, USB*/ int service); //int obexftp_connect_service(obexftp_client_t *cli, // /*@null@*/ const char *service, // /*@null@*/ const char *device, /* for INET, BLUETOOTH */ // int port, /* INET(?), BLUETOOTH, USB*/ ); #define obexftp_connect(cli, device, port) \ obexftp_connect_uuid(cli, device, port, UUID_FBS, sizeof(UUID_FBS)) #define obexftp_connect_ftp(cli, device, port) \ obexftp_connect_uuid(cli, device, port, UUID_FBS, sizeof(UUID_FBS)) #define obexftp_connect_push(cli, device, port) \ obexftp_connect_uuid(cli, device, port, NULL, 0) #define obexftp_connect_sync(cli, device, port) \ obexftp_connect_uuid(cli, device, port, UUID_IRMC, sizeof(UUID_IRMC)) int obexftp_disconnect(obexftp_client_t *cli); /* transfer */ int obexftp_setpath(obexftp_client_t *cli, /*@null@*/ const char *name, int create); #define obexftp_chpath(cli, name) \ obexftp_setpath(cli, name, 0) #define obexftp_mkpath(cli, name) \ obexftp_setpath(cli, name, 1) #define obexftp_cdup(cli) \ obexftp_setpath(cli, NULL, 0) #define obexftp_cdtop(cli) \ obexftp_setpath(cli, "", 0) int obexftp_get_type(obexftp_client_t *cli, const char *type, /*@null@*/ const char *localname, /*@null@*/ const char *remotename); #define obexftp_get(cli, localname, remotename) \ obexftp_get_type(cli, NULL, localname, remotename) #define obexftp_list(cli, localname, remotename) \ obexftp_get_type(cli, XOBEX_LISTING, localname, remotename) #define obexftp_get_capability(cli, localname, remotename) \ obexftp_get_type(cli, XOBEX_CAPABILITY, localname, remotename) int obexftp_put_file(obexftp_client_t *cli, const char *filename, const char *remotename); int obexftp_put_data(obexftp_client_t *cli, const uint8_t *data, int size, const char *remotename); int obexftp_del(obexftp_client_t *cli, const char *name); /* Siemens only */ int obexftp_info(obexftp_client_t *cli, uint8_t opcode); int obexftp_rename(obexftp_client_t *cli, const char *sourcename, const char *targetname); /* compatible directory handling */ void *obexftp_opendir(obexftp_client_t *cli, const char *name); int obexftp_closedir(void *dir); stat_entry_t *obexftp_readdir(void *dir); stat_entry_t *obexftp_stat(obexftp_client_t *cli, const char *name); #ifdef __cplusplus } #endif #endif /* OBEXFTP_CLIENT_H */ obexftp-0.24.2-Source/obexftp/bt_kit.h000644 001750 001750 00000007727 12656174456 020747 0ustar00hendrikhendrik000000 000000 /** \file obexftp/bt_kit.h Bluetooth, SDP, HCI kit for Linux, FreeBSD, NetBSD and Win32. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #ifndef BT_KIT_H #define BT_KIT_H #ifndef BTKITSYM #define BTKITSYM __attribute__ ((visibility ("hidden"))) #endif #ifdef __cplusplus extern "C" { #endif #ifdef HAVE_BLUETOOTH /* Service Class UUIDs for bt browse. */ /* Only Service Class UUID-16s are accepted (0x1000-0x12FF). Esp. not Protocol UUIDs. */ /* Also SYNCML UUID-16s (0x0001-0x0004) are translated to correct UUID-128s. */ #define BTKIT_SPP_SERVICE (0x1101) /* aka SerialPortServiceClassID_UUID16 */ #define BTKIT_SYNC_SERVICE (0x1104) /* aka IrMCSyncServiceClassID_UUID16 */ #define BTKIT_PUSH_SERVICE (0x1105) /* aka OBEXObjectPushServiceClassID_UUID16 */ #define BTKIT_FTP_SERVICE (0x1106) /* aka OBEXFileTransferServiceClassID_UUID16 */ #define BTKIT_SYNCML_SERVER (0x0001) /* aka SyncMLServer_UUID */ #define BTKIT_SYNCML_CLIENT (0x0002) /* aka SyncMLClient_UUID */ #define BTKIT_SYNCML_DM_SERVER (0x0003) /* aka SyncMLDMServer_UUID */ #define BTKIT_SYNCML_DM_CLIENT (0x0004) /* aka SyncMLDMClient_UUID */ //#ifndef _WIN32 //#include //#include //#include //#endif /* _WIN32 */ /* Windows with headers files from the Platform SDK */ #ifdef _WIN32 #include #include //#include //#include #define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT #define ETIMEDOUT WSAETIMEDOUT #define ECONNREFUSED WSAECONNREFUSED #define EHOSTDOWN WSAEHOSTDOWN #define EINPROGRESS WSAEINPROGRESS #define bdaddr_t BTH_ADDR #define sockaddr_rc _SOCKADDR_BTH #define rc_family addressFamily #define rc_bdaddr btAddr #define rc_channel port #define PF_BLUETOOTH PF_BTH #define AF_BLUETOOTH PF_BLUETOOTH #define BTPROTO_RFCOMM BTHPROTO_RFCOMM #define BDADDR_ANY (&(BTH_ADDR){BTH_ADDR_NULL}) #define bacpy(dst,src) memcpy((dst),(src),sizeof(BTH_ADDR)) #define bacmp(a,b) memcmp((a),(b),sizeof(BTH_ADDR)) BTKITSYM int ba2str(const bdaddr_t *btaddr, char *straddr); BTKITSYM int str2ba(const char *straddr, BTH_ADDR *btaddr); /* Various BSD systems */ #elif defined(__NetBSD__) || defined(__FreeBSD__) #define COMPAT_BLUEZ #include #ifdef HAVE_SDP #include #include #endif #ifndef BDADDR_ANY #define BDADDR_ANY NG_HCI_BDADDR_ANY #endif #ifndef RFCOMM_CHANNEL_MIN #define RFCOMM_CHANNEL_MIN 1 #endif #ifndef RFCOMM_CHANNEL_MAX #define RFCOMM_CHANNEL_MAX 30 #endif /* BlueZ, Linux 2.4.6 and up (incl. 2.6) */ #else #include #include #include #include #include #include #endif /* _WIN32 */ /* library setup/teardown functions (needed for win32) */ BTKITSYM int btkit_init(void); BTKITSYM int btkit_exit(void); /* additional functions */ BTKITSYM char **btkit_discover(const char *src); /* HCI no. or address */ BTKITSYM char *btkit_getname(const char *src, const char *addr); BTKITSYM int btkit_browse(const char *src, const char *addr, int svclass); BTKITSYM int btkit_register_obex(int svclass, int channel); BTKITSYM int btkit_unregister_service(int svclass); //KITSYM int btkit_open_rfcomm(char *src, char *dest, int channel); #endif /* HAVE_BLUETOOTH */ #ifdef __cplusplus } #endif #endif /* BT_KIT_H */ obexftp-0.24.2-Source/obexftp/cache.c000644 001750 001750 00000030703 12656173605 020512 0ustar00hendrikhendrik000000 000000 /** \file obexftp/cache.c ObexFTP client API caching layer. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ /* for * - strcasestr() */ #define _GNU_SOURCE #include #include #include #include #include /* __S_IFDIR, __S_IFREG */ #ifndef S_IFDIR #define S_IFDIR __S_IFDIR #endif #ifndef S_IFREG #define S_IFREG __S_IFREG #endif #include #include "obexftp.h" #include "client.h" #include "object.h" #include "unicode.h" #include "cache.h" #include /** Normalize the path argument, add/remove leading/trailing slash turns relative paths into (most likely wrong) absolute ones wont expand "../" or "./". */ static /*@only@*/ char *normalize_dir_path(int quirks, const char *name) { char *copy, *p; if (!name) name = ""; p = copy = malloc(strlen(name) + 2); /* at most add two slashes */ if (OBEXFTP_USE_LEADING_SLASH(quirks)) *p++ = '/'; while (*name == '/') name++; while (*name) { if (*name == '/') { *p++ = *name++; while (*name == '/') name++; } else { *p++ = *name++; } } if (p > copy && *(p-1) == '/') p--; if (OBEXFTP_USE_TRAILING_SLASH(quirks)) *p++ = '/'; *p = '\0'; return copy; } /** Purge all cache object at/below a given path. Methods that need to invalidate cache lines: - setpath (when create is on) - put - put_file - del - rename */ void cache_purge(cache_object_t **root, const char *path) { cache_object_t *cache, *tmp; char *name; char *pathonly; #define FREE_NODE(node) do { \ if (node->name) \ free(node->name); \ if (node->content) \ free(node->content); \ if (node->stats) \ free(node->stats); \ free(node); \ } while(0) if (!path || *path == '\0' || *path != '/') { /* purge all */ while (*root) { cache = *root; *root = cache->next; FREE_NODE(cache); } return; } pathonly = strdup(path); name = strrchr(pathonly, '/'); *name++ = '\0'; /* removing far too much, the siblings could stay cached... */ while (*root && !strncmp((*root)->name, pathonly, strlen(pathonly))) { cache = *root; *root = cache->next; FREE_NODE(cache); } for (cache = *root; cache->next; cache = cache->next) { if (!strncmp(cache->next->name, pathonly, strlen(pathonly))) { tmp = cache->next; cache->next = cache->next->next; FREE_NODE(tmp); } } free(pathonly); } /** Retrieve an object from the cache. */ int get_cache_object(const obexftp_client_t *cli, const char *name, char **object, int *size) { cache_object_t *cache; return_val_if_fail(cli != NULL, -1); /* search the cache */ for (cache = cli->cache; cache && strcmp(cache->name, name); cache = cache->next); if (cache) { DEBUG(2, "%s() Listing %s from cache\n", __func__, cache->name); if (object) *object = cache->content; if (size) *size = cache->size; return 0; } return -1; } /** Store an object in the cache. */ int put_cache_object(obexftp_client_t *cli, /*@only@*/ char *name, /*@only@*/ char *object, int size) { cache_object_t *cache; return_val_if_fail(cli != NULL, -1); /* prepend to cache */ cache = cli->cache; cli->cache = calloc(1, sizeof(cache_object_t)); cli->cache->next = cache; cli->cache->timestamp = time(NULL); cli->cache->size = size; cli->cache->name = name; cli->cache->content = object; return 0; } /** List a directory from cache, optionally loading it first. */ static char *obexftp_cache_list(obexftp_client_t *cli, const char *name) { char *path, *listing; return_val_if_fail(cli != NULL, NULL); cli->infocb(OBEXFTP_EV_RECEIVING, name, 0, cli->infocb_data); path = normalize_dir_path(cli->quirks, name); DEBUG(2, "%s() Listing %s (%s)\n", __func__, name, path); /* search the cache */ if (!get_cache_object(cli, path, &listing, NULL)) { DEBUG(2, "%s() Listing %s from cache\n", __func__, path); if (path) free(path); return listing; } if (path && !strcmp(path, "/telecom/")) { listing = strdup(""); put_cache_object(cli, path, listing, strlen(listing)); } if (obexftp_list(cli, NULL, path) < 0) return NULL; listing = strdup(cli->buf_data); put_cache_object(cli, path, listing, strlen(listing)); return listing; } /* simple xml parser */ /** Parse fixed format date string to time_t. */ static time_t atotime (const char *date) { struct tm tm; time_t retval = 0; if (6 == sscanf(date, "%4d%2d%2dT%2d%2d%2d", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec)) { tm.tm_year -= 1900; tm.tm_mon--; tm.tm_isdst = 0; retval = mktime(&tm); } return retval; } static mode_t get_perm(char *perm) { mode_t retval = 0; if(strcasestr(perm, "R")!=NULL) retval |= S_IRUSR | S_IRGRP; if(strcasestr(perm, "W")!=NULL) retval |= S_IWUSR | S_IRGRP; return retval; } static struct { char *esc; int size; char c; } xml_esc_seq[] = { { "&", 5, '&' }, { """, 6, '"' }, { "'", 6, '\'' }, { "<", 4, '<' }, { ">", 4, '>' }, }; static int xml_esc_seq_count = sizeof(xml_esc_seq) / sizeof(xml_esc_seq[0]); static void replace_xml_escape_sequences(char *xmltext) { int i; for (i = 0; i < xml_esc_seq_count; ++i) { char *esc_pos = strstr(xmltext, xml_esc_seq[i].esc); while (esc_pos) { size_t rem_len = strlen(esc_pos + xml_esc_seq[i].size); esc_pos[0] = xml_esc_seq[i].c; memmove(esc_pos + 1, esc_pos + xml_esc_seq[i].size, rem_len); esc_pos[rem_len + 1] = 0; //re-evaluate esc_pos = strstr(esc_pos + 1, xml_esc_seq[i].esc); } ; } } /** Parse an XML file to array of stat_entry_t's. Very limited - not multi-byte character save. It's actually "const char *xml" but can't be declared as such. \return a new allocated array of stat_entry_t's. */ static stat_entry_t *parse_directory(char *xml) { const char *line; const char *p, *h; char tagname[201]; char name[201]; // bad coder char perm[201]; char mod[201]; // - no biscuits! char acc[201]; char cre[201]; char size[201]; // int would be ok too. stat_entry_t *dir_start, *dir; int ret, n, i; uint8_t *xml_conv; if (!xml) return NULL; n = strlen(xml) + 1; xml_conv = malloc(n); if (xml_conv) { ret = Utf8ToChar(xml_conv, (uint8_t *)xml, n); if (ret > 0) { xml = (char *)xml_conv; } else { DEBUG(1, "UTF-8 conversion error\n"); } } DEBUG(4, "Converted cache xml: '%s'\n", xml); /* prepare a cache to hold this dir */ p = xml; for (i = 0; p && *p; p = strchr(++p, '>')) i++; DEBUG(2, "max %d cache lines\n", i); dir_start = dir = calloc(i, sizeof(stat_entry_t)); for (line = xml; *line != '\0'; ) { p = line; line = strchr(line, '>'); if (!line) break; line++; while (*p != '<') p++; tagname[0] = '\0'; sscanf (p, "<%200[^> \t\n\r] ", tagname); name[0] = '\0'; h = strstr(p, "name="); if (h) { sscanf (h, "name=\"%200[^\"]\"", name); replace_xml_escape_sequences(name); } perm[0] = '\0'; h = strstr(p, "user-perm="); if (h) sscanf(h, "user-perm=\"%200[^\"]\"", perm); else strcpy(perm, "RW"); //default permissions cre[0] = '\0'; h = strstr(p, "created="); if (h) sscanf (h, "created=\"%200[^\"]\"", cre); mod[0] = '\0'; h = strstr(p, "modified="); if (h) sscanf (h, "modified=\"%200[^\"]\"", mod); acc[0] = '\0'; h = strstr(p, "accessed="); if (h) sscanf(h, "accessed=\"%200[^\"]\"", acc); size[0] = '\0'; h = strstr(p, "size="); if (h) sscanf (h, "size=\"%200[^\"]\"", size); if (!strcmp("folder", tagname)) { dir->mode = S_IFDIR | get_perm(perm); if (get_perm(perm) & (S_IRUSR | S_IRGRP)) dir->mode |= S_IXUSR | S_IXGRP; strcpy(dir->name, name); DEBUG(2, "FOLDER: times for '%s'(ctime, mtime, atime): " "'%s', '%s', '%s'\n", name, cre, mod, acc); dir->ctime = atotime(cre); dir->mtime = atotime(mod); dir->atime = atotime(acc); dir->size = 0; dir++; } if (!strcmp("file", tagname)) { dir->mode = S_IFREG | get_perm(perm); strcpy(dir->name, name); DEBUG(2, "FILE: times for '%s'(ctime, mtime, atime): " "'%s', '%s', '%s'\n", name, cre, mod, acc); dir->ctime = atotime(cre); dir->mtime = atotime(mod); dir->atime = atotime(acc); i = 0; sscanf(size, "%i", &i); dir->size = i; /* int to off_t */ dir++; } // handle hidden folder! } dir->name[0] = '\0'; if (xml_conv) free (xml_conv); return dir_start; } /* directory handling */ typedef struct { stat_entry_t *cur; /* stat_entry_t *head; -- so we can free this? */ } dir_stream_t; /** Prepare a directory for reading. */ void *obexftp_opendir(obexftp_client_t *cli, const char *name) { cache_object_t *cache; dir_stream_t *stream; char *abs; /* fetch dir if needed */ (void) obexftp_cache_list(cli, name); /* search the cache */ abs = normalize_dir_path(cli->quirks, name); for (cache = cli->cache; cache && strcmp(cache->name, abs); cache = cache->next); free(abs); if (!cache) return NULL; DEBUG(2, "%s() dir prepared (%s)\n", __func__, cache->name); /* read dir */ if (!cache->stats) cache->stats = parse_directory(cache->content); DEBUG(2, "%s() got stats\n", __func__); stream = malloc(sizeof(dir_stream_t)); stream->cur = cache->stats; return (void *)stream; } /** Close a directory after reading. The stat entry is a cache object so we do nothing. */ int obexftp_closedir(void *dir) { if (!dir) return -1; free (dir); return 0; } /** Read the next entry from an open directory. */ stat_entry_t *obexftp_readdir(void *dir) { dir_stream_t *stream; stream = (dir_stream_t *)dir; if (!stream || !(stream->cur)) return NULL; if (!(*stream->cur->name)) return NULL; return stream->cur++; } /** Stat a directory entry. */ stat_entry_t *obexftp_stat(obexftp_client_t *cli, const char *name) { cache_object_t *cache; stat_entry_t *entry; char *path, *abs, *p; const char *basename; return_val_if_fail(name != NULL, NULL); path = strdup(name); p = strrchr(path, '/'); if (p) { *p++ = '\0'; basename = p; } else { *path = '\0'; basename = name; } DEBUG(2, "%s() stating '%s' / '%s'\n", __func__, path, basename); /* fetch dir if needed */ (void) obexftp_cache_list(cli, path); /* search the cache for the path */ abs = normalize_dir_path(cli->quirks, path); for (cache = cli->cache; cache && strcmp(cache->name, abs); cache = cache->next); free(abs); if (!cache) { free(path); return NULL; } DEBUG(2, "%s() found '%s'\n", __func__, cache->name); /* read dir */ if (!cache->stats) cache->stats = parse_directory(cache->content); DEBUG(2, "%s() got dir '%s'\n", __func__, path); /* then lookup the basename */ for (entry = cache->stats; entry && *entry->name && strcmp(entry->name, basename); entry++); free(path); if (!entry || !(*entry->name)) return NULL; DEBUG(2, "%s() got stats\n", __func__); return entry; /* dev_t st_dev; / * device * / ino_t st_ino; / * inode * / mode_t st_mode; / * protection * / nlink_t st_nlink; / * number of hard links * / uid_t st_uid; / * user ID of owner * / gid_t st_gid; / * group ID of owner * / dev_t st_rdev; / * device type (if inode device) * / off_t st_size; / * total size, in bytes * / blksize_t st_blksize; / * blocksize for filesystem I/O * / blkcnt_t st_blocks; / * number of blocks allocated * / time_t st_atime; / * time of last access * / time_t st_mtime; / * time of last modification * / time_t st_ctime; / * time of last status change * / */ } obexftp-0.24.2-Source/obexftp/object.c000644 001750 001750 00000022421 11776125712 020711 0ustar00hendrikhendrik000000 000000 /** \file obexftp/object.c Collection of functions to build common OBEX request objects. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2002-2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #include #include #include #include "unicode.h" #include "object.h" /** Build an INFO request object (Siemens only). \param obex reference to an OpenOBEX instance. \param conn optional connection id number \param opcode select if you want to read mem installed (0x01) or free mem (0x02) \return a new obex object if successful, NULL otherwise */ obex_object_t *obexftp_build_info (obex_t *obex, uint32_t conn, uint8_t opcode) { obex_object_t *object; obex_headerdata_t hv; uint8_t cmdstr[] = {APPARAM_INFO_CODE, 0x01, 0x00}; object = OBEX_ObjectNew(obex, OBEX_CMD_GET); if(object == NULL) return NULL; if(conn != 0xffffffff) { hv.bq4 = conn; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_CONNECTION, hv, sizeof(uint32_t), OBEX_FL_FIT_ONE_PACKET); } cmdstr[2] = opcode; hv.bs = (const uint8_t *) cmdstr; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_APPARAM, hv, sizeof(cmdstr), OBEX_FL_FIT_ONE_PACKET); return object; } /** Build a GET request object. \param obex reference to an OpenOBEX instance. \param conn optional connection id number \param name name of the requested file \param type type of the requested file \return a new obex object if successful, NULL otherwise \note \a name and \a type musn't both be NULL */ obex_object_t *obexftp_build_get (obex_t *obex, uint32_t conn, const char *name, const char *type) { obex_object_t *object; obex_headerdata_t hv; uint8_t *ucname; int ucname_len; object = OBEX_ObjectNew(obex, OBEX_CMD_GET); if(object == NULL) return NULL; if(conn != 0xffffffff) { hv.bq4 = conn; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_CONNECTION, hv, sizeof(uint32_t), OBEX_FL_FIT_ONE_PACKET); } if(type != NULL) { // type header is a null terminated ascii string hv.bs = (const uint8_t *) type; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_TYPE, hv, strlen(type)+1, OBEX_FL_FIT_ONE_PACKET); } if (name != NULL) { ucname_len = strlen(name)*2 + 2; ucname = malloc(ucname_len); if(ucname == NULL) { (void) OBEX_ObjectDelete(obex, object); return NULL; } ucname_len = CharToUnicode(ucname, (uint8_t*)name, ucname_len); hv.bs = (const uint8_t *) ucname; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_NAME, hv, ucname_len, OBEX_FL_FIT_ONE_PACKET); free(ucname); } return object; } /** Build a RENAME request object (Siemens only). \param obex reference to an OpenOBEX instance. \param conn optional connection id number \param from original name of the requested file \param to new name of the requested file \return a new obex object if successful, NULL otherwise \note neither filename may be NULL */ obex_object_t *obexftp_build_rename (obex_t *obex, uint32_t conn, const char *from, const char *to) { obex_object_t *object; obex_headerdata_t hv; uint8_t *appstr; uint8_t *appstr_p; int appstr_len; int ucname_len; char opname[] = {'m','o','v','e'}; if((from == NULL) || (to == NULL)) return NULL; object = OBEX_ObjectNew(obex, OBEX_CMD_PUT); if(object == NULL) return NULL; if(conn != 0xffffffff) { hv.bq4 = conn; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_CONNECTION, hv, sizeof(uint32_t), OBEX_FL_FIT_ONE_PACKET); } appstr_len = 1 + 1 + sizeof(opname) + strlen(from)*2 + 2 + strlen(to)*2 + 2 + 2; appstr = malloc(appstr_len); if(appstr == NULL) { (void) OBEX_ObjectDelete(obex, object); return NULL; } appstr_p = appstr; *appstr_p++ = 0x34; *appstr_p++ = sizeof(opname); memcpy(appstr_p, opname, sizeof(opname)); appstr_p += sizeof(opname); *appstr_p++ = 0x35; ucname_len = CharToUnicode(appstr_p + 1, (uint8_t*)from, strlen(from)*2 + 2); *appstr_p = ucname_len - 2; /* no trailing 0 */ appstr_p += ucname_len - 1; *appstr_p++ = 0x36; ucname_len = CharToUnicode(appstr_p + 1, (uint8_t*)to, strlen(to)*2 + 2); *appstr_p = ucname_len - 2; /* no trailing 0 */ hv.bs = (const uint8_t *) appstr; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_APPARAM, hv, appstr_len - 2, 0); free(appstr); return object; } /** Build a DELETE request object. \param obex reference to an OpenOBEX instance. \param conn optional connection id number \param name name of the file to be deleted \return a new obex object if successful, NULL otherwise \note \a name may not be NULL */ obex_object_t *obexftp_build_del (obex_t *obex, uint32_t conn, const char *name) { obex_object_t *object; obex_headerdata_t hv; uint8_t *ucname; int ucname_len; if(name == NULL) return NULL; object = OBEX_ObjectNew(obex, OBEX_CMD_PUT); if(object == NULL) return NULL; if(conn != 0xffffffff) { hv.bq4 = conn; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_CONNECTION, hv, sizeof(uint32_t), OBEX_FL_FIT_ONE_PACKET); } ucname_len = strlen(name)*2 + 2; ucname = malloc(ucname_len); if(ucname == NULL) { (void) OBEX_ObjectDelete(obex, object); return NULL; } ucname_len = CharToUnicode(ucname, (uint8_t*)name, ucname_len); hv.bs = (const uint8_t *) ucname; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_NAME, hv, ucname_len, OBEX_FL_FIT_ONE_PACKET); free(ucname); return object; } /** Build a SETPATH request object. \param obex reference to an OpenOBEX instance. \param conn optional connection id number \param name name of the file to be deleted \param create create the folder if neccessary \return a new obex object if successful, NULL otherwise \note if \a name is NULL ascend one directory if \a name is empty change to top/default directory */ obex_object_t *obexftp_build_setpath (obex_t *obex, uint32_t conn, const char *name, int create) { obex_object_t *object; obex_headerdata_t hv; // "Backup Level" and "Don't Create" flag in first byte // second byte is reserved and needs to be 0 uint8_t setpath_nohdr_data[2] = {0, 0}; uint8_t *ucname; int ucname_len; object = OBEX_ObjectNew(obex, OBEX_CMD_SETPATH); if(object == NULL) return NULL; if(conn != 0xffffffff) { hv.bq4 = conn; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_CONNECTION, hv, sizeof(uint32_t), OBEX_FL_FIT_ONE_PACKET); } if (create == 0) { // set the 'Don't Create' bit setpath_nohdr_data[0] |= 2; } if (name) { ucname_len = strlen(name)*2 + 2; ucname = malloc(ucname_len); if (ucname == NULL) { (void) OBEX_ObjectDelete(obex, object); return NULL; } ucname_len = CharToUnicode(ucname, (uint8_t*)name, ucname_len); /* apparently the empty name header is meant to be really empty... */ if (ucname_len == 2) ucname_len = 0; hv.bs = (const uint8_t *) ucname; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_NAME, hv, ucname_len, 0); free(ucname); } else { setpath_nohdr_data[0] = 1; /* or |= perhaps? */ } (void) OBEX_ObjectSetNonHdrData(object, setpath_nohdr_data, 2); return object; } /** Build a PUT request object. \param obex reference to an OpenOBEX instance. \param conn optional connection id number \param name name of the target file \param size size hint for the target file \return a new obex object if successful, NULL otherwise \note use build_object_from_file() instead */ obex_object_t *obexftp_build_put (obex_t *obex, uint32_t conn, const char *name, const int size) { obex_object_t *object; obex_headerdata_t hv; uint8_t *ucname; int ucname_len; object = OBEX_ObjectNew(obex, OBEX_CMD_PUT); if(object == NULL) return NULL; if(conn != 0xffffffff) { hv.bq4 = conn; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_CONNECTION, hv, sizeof(uint32_t), OBEX_FL_FIT_ONE_PACKET); } ucname_len = strlen(name)*2 + 2; ucname = malloc(ucname_len); if(ucname == NULL) { (void) OBEX_ObjectDelete(obex, object); return NULL; } ucname_len = CharToUnicode(ucname, (uint8_t*)name, ucname_len); hv.bs = (const uint8_t *) ucname; (void ) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_NAME, hv, ucname_len, 0); free(ucname); hv.bq4 = (uint32_t) size; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_LENGTH, hv, sizeof(uint32_t), 0); hv.bs = (const uint8_t *) NULL; (void) OBEX_ObjectAddHeader(obex, object, OBEX_HDR_BODY, hv, 0, OBEX_FL_STREAM_START); return object; } obexftp-0.24.2-Source/obexftp/unicode.c000644 001750 001750 00000016311 12656174532 021074 0ustar00hendrikhendrik000000 000000 /** \file obexftp/unicode.c Unicode charset and encoding conversions. ObexFTP library - language bindings for OBEX file transfer. Copyright (c) 2007 Christian W. Zuckschwerdt ObexFTP is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with ObexFTP. If not, see . */ #include #include #include #ifdef _WIN32 /* no need for iconv */ #include /* pulls in Winnls.h */ #else #ifdef HAVE_ICONV #include #include #ifndef ICONV_CONST #define ICONV_CONST #endif #ifdef HAVE_LANGINFO_H #include #define locale_charset nl_langinfo(CODESET) #else #define locale_charset "" #endif /* HAVE_LANGINFO_H */ #endif /* HAVE_ICONV */ #endif /* _WIN32 */ #include "unicode.h" #include /** Convert a string to UTF-16BE, tries to guess charset and encoding. As a lib we can't be sure what the input charset and encoding is. Try to read the input as UTF-8, this will also work for plain ASCII (7bit). On errors fall back to the environment locale, which again could be UTF-8. As last resort try to copy verbatim, i.e. as ISO-8859-1. \note This is a quick hack until OpenOBEX is iconv-ready. */ int CharToUnicode(uint8_t *uc, const uint8_t *c, int size) { #ifdef _WIN32 /* no need for iconv */ int ret, i; char tmp; return_val_if_fail(uc != NULL, -1); return_val_if_fail(c != NULL, -1); /* ANSI to UTF-16LE */ ret = MultiByteToWideChar(CP_ACP, 0, c, -1, (LPWSTR)uc, size); /* turn the eggs the right way around now */ for (i=0; i < ret; i++) { tmp = uc[2*i]; uc[2*i] = uc[2*i+1]; uc[2*i+1] = tmp; } return ret * 2; /* 0 on error */ #else /* _WIN32 */ #ifdef HAVE_ICONV iconv_t utf16; size_t ni, no, nrc; /* avoid type-punned dereferecing (breaks strict aliasing) */ ICONV_CONST char *cc = (ICONV_CONST char *)c; char *ucc = (char *)uc; return_val_if_fail(uc != NULL, -1); return_val_if_fail(c != NULL, -1); /* try UTF-8 to UTF-16BE */ ni = strlen(cc) + 1; no = size; utf16 = iconv_open("UTF-16BE", "UTF-8"); nrc = iconv(utf16, &cc, &ni, &ucc, &no); (void)iconv_close(utf16); if (nrc == (size_t)(-1)) { DEBUG(3, "Iconv from UTF-8 conversion error: '%s'\n", cc); } else { return size-no; } /* try current locale charset to UTF-16BE */ setlocale(LC_CTYPE, ""); DEBUG(2, "Iconv from locale \"%s\"\n", locale_charset); cc = (ICONV_CONST char *)c; ucc = (char *)uc; ni = strlen(cc) + 1; no = size; utf16 = iconv_open("UTF-16BE", locale_charset); nrc = iconv(utf16, &cc, &ni, &ucc, &no); (void)iconv_close(utf16); if (nrc == (size_t)(-1)) { DEBUG(3, "Iconv from locale conversion error: '%s'\n", cc); } else { return size-no; } /* fallback to ISO-8859-1 to UTF-16BE (every byte is valid here) */ cc = (ICONV_CONST char *)c; ucc = (char *)uc; ni = strlen(cc) + 1; no = size; utf16 = iconv_open("UTF-16BE", "ISO-8859-1"); nrc = iconv(utf16, &cc, &ni, &ucc, &no); (void)iconv_close(utf16); if (nrc == (size_t)(-1)) { DEBUG(2, "Iconv internal conversion error: '%s'\n", cc); return -1; } return size-no; #else /* HAVE_ICONV */ int len, n; if (uc == NULL || c == NULL) return -1; len = n = strlen((char *) c); if (n*2+2 > size) return -1; uc[n*2+1] = 0; uc[n*2] = 0; while (n--) { uc[n*2+1] = c[n]; uc[n*2] = 0; } return (len * 2) + 2; #endif /* HAVE_ICONV */ #endif /* _WIN32 */ } /** Convert a string from UTF-16BE to locale charset. Plain ASCII (7bit) and basic ISO-8859-1 will always work. This conversion supports UTF-8 and single byte locales. \note This is a quick hack until OpenOBEX is iconv-ready. */ int UnicodeToChar(uint8_t *c, const uint8_t *uc, int size) { #ifdef _WIN32 /* no need for iconv */ int ret, n, i; uint8_t *le; return_val_if_fail(uc != NULL, -1); return_val_if_fail(c != NULL, -1); /* turn the eggs around, pointy side up */ for (n=0; uc[2*n] != 0 || uc[2*n+1] != 0; n++); le = malloc(2*n+2); for (i=0; i <= n; i++) { le[2*i] = uc[2*i+1]; le[2*i+1] = uc[2*i]; } /* UTF-16LE to ANSI */ ret = WideCharToMultiByte(CP_ACP, 0, le, -1, c, size, NULL, NULL); free(le); return ret; /* 0 on error */ #else /* _WIN32 */ #ifdef HAVE_ICONV iconv_t utf16; size_t ni, no, nrc; /* avoid type-punned dereferecing (breaks strict aliasing) */ char *cc = (char *)c; ICONV_CONST char *ucc = (ICONV_CONST char *)uc; return_val_if_fail(uc != NULL, -1); return_val_if_fail(c != NULL, -1); /* UTF-16BE to current locale charset */ setlocale(LC_CTYPE, ""); DEBUG(3, "Iconv to locale \"%s\"\n", locale_charset); for (ni=0; ucc[2*ni] != 0 || ucc[2*ni+1] != 0; ni++); ni = 2*ni+2; no = size; utf16 = iconv_open(locale_charset, "UTF-16BE"); nrc = iconv(utf16, &ucc, &ni, &cc, &no); (void)iconv_close(utf16); if (nrc == (size_t)(-1)) { DEBUG(2, "Iconv from locale conversion error: '%s'\n", cc); } return size-no; #else /* HAVE_ICONV */ int n; if (uc == NULL || c == NULL) return -1; /* Make sure buffer is big enough! */ for (n = 0; uc[n*2+1] != 0; n++); if (n >= size) return -1; for (n = 0; uc[n*2+1] != 0; n++) c[n] = uc[n*2+1]; c[n] = 0; return 0; #endif /* HAVE_ICONV */ #endif /* _WIN32 */ } /** Convert a (xml) string from UTF-8 to locale charset. Plain ASCII (7bit) and basic ISO-8859-1 will always work. This conversion supports UTF-8 and single byte locales. \note This is a quick hack until OpenOBEX is iconv-ready. */ int Utf8ToChar(uint8_t *c, const uint8_t *uc, int size) { #ifdef _WIN32 /* no need for iconv */ int ret, n, i; uint8_t *le; return_val_if_fail(uc != NULL, -1); return_val_if_fail(c != NULL, -1); n = strlen(uc)*2+2; le = malloc(n); /* UTF-8 to UTF-16LE */ ret = MultiByteToWideChar(CP_UTF8, 0, uc, -1, (LPWSTR)le, n); /* UTF-16LE to ANSI */ ret = WideCharToMultiByte(CP_ACP, 0, le, -1, c, size, NULL, NULL); free(le); return ret; /* 0 on error */ #else /* _WIN32 */ #ifdef HAVE_ICONV iconv_t utf8; size_t ni, no, nrc; /* avoid type-punned dereferecing (breaks strict aliasing) */ char *cc = (char *)c; ICONV_CONST char *ucc = (ICONV_CONST char *)uc; return_val_if_fail(uc != NULL, -1); return_val_if_fail(c != NULL, -1); setlocale(LC_CTYPE, ""); DEBUG(2, "Iconv to \"%s\"\n", locale_charset); ni = strlen(ucc); no = size; utf8 = iconv_open(locale_charset, "UTF-8"); nrc = iconv(utf8, &ucc, &ni, &cc, &no); (void)iconv_close(utf8); if (nrc != (size_t)(-1)) { DEBUG(2, "Iconv from locale conversion error: '%s'\n", cc); } return size-no; #else /* HAVE_ICONV */ int n, i; n = strlen(uc); strncpy(c, uc, size); c[size] = '\0'; return n; #endif /* HAVE_ICONV */ #endif /* _WIN32 */ } obexftp-0.24.2-Source/obexftp/CMakeLists.txt000644 001750 001750 00000002460 12701256741 022034 0ustar00hendrikhendrik000000 000000 set ( obexftp_SOURCES object.c client.c obexftp_io.c cache.c unicode.c bt_kit.c ) set ( obexftp_PUBLIC_HEADERS obexftp.h client.h uuid.h object.h ) set ( obexftp_HEADERS object.h obexftp_io.h cache.h unicode.h bt_kit.h ${obexftp_PUBLIC_HEADERS} ) find_package ( Iconv REQUIRED ) add_definitions ( -DHAVE_ICONV ) if ( ICONV_USES_CONST ) add_definitions ( -DICONV_CONST=const ) endif ( ICONV_USES_CONST ) find_file ( HAVE_LANGINFO_H NAMES langinfo.h ) if ( HAVE_LANGINFO_H ) add_definitions ( -DHAVE_LANGINFO_H ) endif ( HAVE_LANGINFO_H ) # always set this add_definitions ( -DHAVE_USB ) add_library ( obexftp ${obexftp_SOURCES} ${obexftp_HEADERS} ) set_property ( TARGET obexftp PROPERTY VERSION 0.3.0 ) set_property ( TARGET obexftp PROPERTY SOVERSION 0 ) set_property ( TARGET obexftp PROPERTY PUBLIC_HEADER ${obexftp_PUBLIC_HEADERS} ) target_link_libraries ( obexftp PRIVATE multicobex ${Bluetooth_LIBRARIES} ${OpenObex_LIBRARIES} ) install ( TARGETS obexftp RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT library LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/obexftp COMPONENT devel ) obexftp-0.24.2-Source/swig/000755 001750 001750 00000000000 12701545532 016573 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/swig/perl/000755 001750 001750 00000000000 12701545532 017535 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/swig/perl/Makefile.PL.in000644 001750 001750 00000001524 11351376660 022122 0ustar00hendrikhendrik000000 000000 #!/usr/bin/perl -w use ExtUtils::MakeMaker ; WriteMakefile( 'ABSTRACT' => q[Perl interface to OBEX filesytem] , 'AUTHOR' => q[Christian W. Zuckschwerdt ] , # 'VERSION' => q[@VERSION@], # Avoid compilation problem for Fedora Core 1 'DEFINE' => q[-DSKIP_SEARCH_H @DEFS@], 'INC' => q[-I@top_srcdir@ @CPPFLAGS@], # Default value for LDDLFLAGS is $Config{lddlflags}="-shared -L/usr/local/lib" # but we want rpath to be @libdir@ or @exec_prefix@/lib 'LDDLFLAGS' => q[-shared -Wl,-rpath=@prefix@/lib], 'LIBS' => q[-L@top_builddir@/obexftp/.libs -lobexftp -L@top_builddir@/multicobex/.libs -lmulticobex -L@top_builddir@/bfb/.libs -lbfb @OPENOBEX_LIBS@], 'OBJECT' => 'perl_wrap.o', # $(OBJ_EXT) 'NAME' => 'OBEXFTP', 'FIRST_MAKEFILE' => 'Makefile.perl', ) ; obexftp-0.24.2-Source/swig/perl/CMakeLists.txt000644 001750 001750 00000003460 12201753535 022277 0ustar00hendrikhendrik000000 000000 find_package ( PerlLibs REQUIRED ) #foreach ( lib SITESEARCH SITELIB VENDORARCH VENDORLIB ARCHLIB PRIVLIB ) # message ( "PERL_${lib}: ${PERL_${lib}}" ) #endforeach ( lib ) add_definitions ( ${PERL_EXTRA_C_FLAGS} ) include_directories ( ${PERL_ARCHLIB}/CORE ) foreach ( src ${obexftp_SWIG_SOURCES} ) list ( APPEND obexftp-perl_SWIG_SOURCES ../${src} ) endforeach ( src ) set ( CMAKE_SWIG_FLAGS -module OBEXFTP ) set ( SWIG_PYTHON_EXTRA_FILE_EXTENSION "pm" ) set_source_files_properties ( ${obexftp-python_SWIG_SOURCES} PROPERTIES SWIG_MODULE_NAME OBEXFTP ) swig_add_module ( obexftp-perl perl ${obexftp-perl_SWIG_SOURCES} ) set_target_properties ( ${SWIG_MODULE_obexftp-perl_REAL_NAME} PROPERTIES OUTPUT_NAME OBEXFTP PREFIX "" NO_SONAME TRUE ) swig_link_libraries ( obexftp-perl obexftp ) # # Get the install directory for ruby modules and strip the ruby install prefix # so that we can use our own prefix. # execute_process ( COMMAND ${PERL_EXECUTABLE} -V:installprefix OUTPUT_VARIABLE PERL_PREFIX ) string ( REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_PREFIX ${PERL_PREFIX} ) file ( TO_CMAKE_PATH "${PERL_PREFIX}" PERL_PREFIX ) execute_process ( COMMAND ${PERL_EXECUTABLE} -V:installvendorarch OUTPUT_VARIABLE PERL_FULL_VENDOR_ARCH_DIR ) string ( REGEX REPLACE "install[a-z]+='([^']+)'.*" "\\1" PERL_FULL_VENDOR_ARCH_DIR ${PERL_FULL_VENDOR_ARCH_DIR} ) file ( TO_CMAKE_PATH "${PERL_FULL_VENDOR_ARCH_DIR}" PERL_FULL_VENDOR_ARCH_DIR ) string ( REGEX REPLACE "^${PERL_PREFIX}/" "" PERL_VENDOR_ARCH_DIR "${PERL_FULL_VENDOR_ARCH_DIR}" ) install ( TARGETS ${SWIG_MODULE_obexftp-perl_REAL_NAME} LIBRARY DESTINATION ${PERL_VENDOR_ARCH_DIR}/auto/OBEXFTP COMPONENT library ) install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/OBEXFTP.pm DESTINATION ${PERL_VENDOR_ARCH_DIR} COMPONENT library ) obexftp-0.24.2-Source/swig/python/000755 001750 001750 00000000000 12701545532 020114 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/swig/python/setup.py.in000644 001750 001750 00000001626 11351376660 022244 0ustar00hendrikhendrik000000 000000 from distutils.core import setup, Extension import string setup(name = 'obexftp', version = '@VERSION@', author = 'Christian Zuckschwerdt', author_email = 'zany@triq.net', url = 'http://www.openobex.org/', description = 'ObexFTP python bindings', download_url = 'http://triq.net/obexftp/', package_dir = {'obexftp': '@srcdir@'}, packages = [ 'obexftp' ], ext_package = 'obexftp', ext_modules = [Extension('_obexftp', ['python_wrap.c'], include_dirs=['@top_srcdir@'], extra_link_args = string.split('-L@top_builddir@/obexftp/.libs -lobexftp -L@top_builddir@/multicobex/.libs -lmulticobex -L@top_builddir@/bfb/.libs -lbfb @OPENOBEX_LIBS@'), # static: extra_link_args = string.split('@top_builddir@/obexftp/.libs/libobexftp.a @top_builddir@/multicobex/.libs/libmulticobex.a @top_builddir@/bfb/.libs/libbfb.a @OPENOBEX_LIBS@'), )], ) obexftp-0.24.2-Source/swig/python/CMakeLists.txt000644 001750 001750 00000003512 12201753535 022654 0ustar00hendrikhendrik000000 000000 find_package ( PythonLibs REQUIRED ) find_package ( PythonInterp REQUIRED ) if ( PYTHON_VERSION_STRING AND PYTHONLIBS_VERSION_STRING ) if ( NOT PYTHON_VERSION_STRING VERSION_EQUAL PYTHONLIBS_VERSION_STRING ) message ( FATAL_ERROR "Version mismatch between python interpreter and libraries" ) endif ( NOT PYTHON_VERSION_STRING VERSION_EQUAL PYTHONLIBS_VERSION_STRING ) endif ( PYTHON_VERSION_STRING AND PYTHONLIBS_VERSION_STRING ) include_directories ( ${PYTHON_INCLUDE_DIRS} ) foreach ( src ${obexftp_SWIG_SOURCES} ) list ( APPEND obexftp-python_SWIG_SOURCES ../${src} ) endforeach ( src ) set ( CMAKE_SWIG_FLAGS -module obexftp ) set_source_files_properties ( ${obexftp-python_SWIG_SOURCES} PROPERTIES SWIG_MODULE_NAME obexftp ) swig_add_module ( obexftp-python python ${obexftp-python_SWIG_SOURCES} ) set_target_properties ( ${SWIG_MODULE_obexftp-python_REAL_NAME} PROPERTIES OUTPUT_NAME _obexftp NO_SONAME TRUE ) swig_link_libraries ( obexftp-python obexftp ) # # Get the install directory for ruby modules and strip the ruby install prefix # so that we can use our own prefix. # execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "import site, sys; sys.stdout.write(site.PREFIXES[-1])" OUTPUT_VARIABLE PYTHON_PREFIX ) file ( TO_CMAKE_PATH "${PYTHON_PREFIX}" PYTHON_PREFIX ) execute_process ( COMMAND ${PYTHON_EXECUTABLE} -c "import site, sys; sys.stdout.write(site.getsitepackages()[-1])" OUTPUT_VARIABLE PYTHON_SITE_DIR ) file ( TO_CMAKE_PATH "${PYTHON_SITE_DIR}" PYTHON_SITE_DIR ) string ( REGEX REPLACE "^${PYTHON_PREFIX}/" "" PYTHON_SITE_DIR "${PYTHON_SITE_DIR}" ) install ( TARGETS ${SWIG_MODULE_obexftp-python_REAL_NAME} LIBRARY DESTINATION ${PYTHON_SITE_DIR} COMPONENT library ) install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/obexftp.py DESTINATION ${PYTHON_SITE_DIR} COMPONENT library ) obexftp-0.24.2-Source/swig/ruby/000755 001750 001750 00000000000 12701545532 017554 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/swig/ruby/extconf.rb000644 001750 001750 00000002020 11351376660 021545 0ustar00hendrikhendrik000000 000000 #!/usr/bin/env ruby require 'mkmf' # hack 1: ruby black magic to write a Makefile.new instead of a Makefile alias open_orig open def open(path, mode=nil, perm=nil) path = 'Makefile.new' if path == 'Makefile' if block_given? open_orig(path, mode, perm) { |io| yield(io) } else open_orig(path, mode, perm) end end if ENV['PREFIX'] prefix = CONFIG['prefix'] %w[ prefix sitedir datadir infodir mandir oldincludedir ].each do |key| CONFIG[key] = CONFIG[key].sub(/#{prefix}/, ENV['PREFIX']) end end dir_config('obexftp') if have_library('openobex', 'OBEX_Init') and find_library('bfb', 'bfb_io_open', '../../bfb/.libs') and find_library('multicobex', 'cobex_ctrans', '../../multicobex/.libs') and find_library('obexftp', 'obexftp_open', '../../obexftp/.libs') create_makefile('obexftp') # hack 2: strip all rpath references open('Makefile.ruby', 'w') do |out| IO.foreach('Makefile.new') do |line| out.puts line.gsub(/-Wl,-R'[^']*'/, '') end end else puts 'obex libs not found' end obexftp-0.24.2-Source/swig/ruby/CMakeLists.txt000644 001750 001750 00000002567 12201753535 022325 0ustar00hendrikhendrik000000 000000 find_package ( Ruby REQUIRED ) include_directories ( ${RUBY_INCLUDE_DIRS} ) foreach ( src ${obexftp_SWIG_SOURCES} ) list ( APPEND obexftp-ruby_SWIG_SOURCES ../${src} ) endforeach ( src ) set ( CMAKE_SWIG_FLAGS -module obexftp ) set_source_files_properties ( ${obexftp-ruby_SWIG_SOURCES} PROPERTIES SWIG_MODULE_NAME obexftp ) swig_add_module ( obexftp-ruby ruby ${obexftp-ruby_SWIG_SOURCES} ) set_target_properties ( ${SWIG_MODULE_obexftp-ruby_REAL_NAME} PROPERTIES OUTPUT_NAME obexftp PREFIX "" NO_SONAME TRUE ) swig_link_libraries ( obexftp-ruby obexftp ) # # Get the install directory for ruby modules and strip the ruby install prefix # so that we can use our own prefix. # execute_process ( COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "print RbConfig::CONFIG['prefix']" OUTPUT_VARIABLE RUBY_PREFIX ) file ( TO_CMAKE_PATH "${RUBY_PREFIX}" RUBY_PREFIX ) execute_process ( COMMAND ${RUBY_EXECUTABLE} -r rbconfig -e "print RbConfig::CONFIG['vendorarchdir']" OUTPUT_VARIABLE RUBY_FULL_VENDOR_ARCH_DIR ) file ( TO_CMAKE_PATH "${RUBY_FULL_VENDOR_ARCH_DIR}" RUBY_FULL_VENDOR_ARCH_DIR ) string ( REGEX REPLACE "^${RUBY_PREFIX}/" "" RUBY_VENDOR_ARCH_DIR "${RUBY_FULL_VENDOR_ARCH_DIR}" ) install ( TARGETS ${SWIG_MODULE_obexftp-ruby_REAL_NAME} LIBRARY DESTINATION ${RUBY_VENDOR_ARCH_DIR} COMPONENT library ) obexftp-0.24.2-Source/swig/tcl/000755 001750 001750 00000000000 12701545532 017355 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/swig/tcl/CMakeLists.txt000644 001750 001750 00000001401 12201753535 022110 0ustar00hendrikhendrik000000 000000 find_package ( TCL ) if ( TCL_FOUND ) include_directories ( ${TCL_INCLUDE_PATH} ) foreach ( src ${obexftp_SWIG_SOURCES} ) list ( APPEND obexftp-tcl_SWIG_SOURCES ../${src} ) endforeach ( src ) set ( CMAKE_SWIG_FLAGS -module obexftp ) set_source_files_properties ( ${obexftp-tcl_SWIG_SOURCES} PROPERTIES SWIG_MODULE_NAME obexftp ) swig_add_module ( obexftp-tcl tcl ${obexftp-tcl_SWIG_SOURCES} ) set_target_properties ( ${SWIG_MODULE_obexftp-tcl_REAL_NAME} PROPERTIES OUTPUT_NAME obexftp PREFIX "" NO_SONAME TRUE ) swig_link_libraries ( obexftp-tcl obexftp ) install ( TARGETS ${SWIG_MODULE_obexftp-tcl_REAL_NAME} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT library ) endif ( TCL_FOUND ) obexftp-0.24.2-Source/swig/charmap.i000644 001750 001750 00000006054 12025255423 020361 0ustar00hendrikhendrik000000 000000 /* * swig/charmap.i: ObexFTP client library SWIG interface * * Copyright (c) 2006 Christian W. Zuckschwerdt * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ /* handle strings that maybe NULL */ #if defined SWIGPERL /* perl5.swg uses PL_sv_undef. */ #elif defined SWIGPYTHON /* python.swg uses "". Change to Py_None maybe? */ #elif defined SWIGRUBY %typemap(in) char * "$1 = ($input != Qnil) ? StringValuePtr($input) : NULL;"; %typemap(freearg) char * ""; /* Fix for >=swig-1.3.28 */ %typemap(out) char * "$result = $1 ? rb_str_new2($1) : Qnil;"; #elif defined SWIGTCL /* tcl8.swg is naive about this. Does it work? */ #else #warning "no char * in-typemap for this language" #endif /* handle non-sz strings */ %typemap(out) char * { #if defined SWIGPERL $result = newSVpvn(arg1->buf_data, arg1->buf_size); argvi++; #elif defined SWIGPYTHON $result = PyString_FromStringAndSize(arg1->buf_data, arg1->buf_size); #elif defined SWIGRUBY $result = arg1->buf_data ? rb_str_new(arg1->buf_data, arg1->buf_size) : Qnil; #elif defined SWIGTCL Tcl_SetObjResult(interp,Tcl_NewStringObj((char *)arg1->buf_data,arg1->buf_size)); #else #warning "no char * out-typemap for this language" #endif }; /* handle arrays of strings */ %typemap(out) char ** { #if defined SWIGPERL char **p; AV *myav = newAV(); for (p = $1; p && *p; p++) av_push(myav, newSVpv(*p, 0)); $result = newRV_noinc((SV*)myav); sv_2mortal($result); argvi++; #elif defined SWIGPYTHON char **p; $result = PyList_New(0); for (p = $1; p && *p; p++) PyList_Append($result, PyString_FromString(*p)); #elif defined SWIGRUBY char **p; $result = rb_ary_new(); for (p = $1; p && *p; p++) rb_ary_push($result, rb_str_new2(*p)); #elif defined SWIGTCL char **p; /* $result = Tcl_NewListObj(0, NULL); // not needed? */ for (p = $1; p && *p; p++) Tcl_ListObjAppendElement(interp, $result, Tcl_NewStringObj(*p, strlen(*p))); #else #warning "no char ** out-typemap for this language" #endif } %typemap(in) (char *data, size_t size) { /* Danger Wil Robinson */ #if defined SWIGPERL $1 = SvPV($input,$2); #elif defined SWIGPYTHON $1 = PyString_AsString($input); $2 = PyString_Size($input); #elif defined SWIGRUBY $1 = RSTRING_PTR($input); $2 = (int) RSTRING_LEN($input); #elif defined SWIGTCL $1 = Tcl_GetStringFromObj($input,(int*)&$2); #else #warning "no char *, size_t in-typemap for this language" #endif }; obexftp-0.24.2-Source/swig/CMakeLists.txt000644 001750 001750 00000001430 12003314206 021314 0ustar00hendrikhendrik000000 000000 find_package ( SWIG ) if ( SWIG_FOUND ) include ( ${SWIG_USE_FILE} ) include_directories ( ${CMAKE_CURRENT_SOURCE_DIR} ) set ( obexftp_SWIG_SOURCES client.i ) option ( ENABLE_PERL "Build the obexftp PERL module (using swig)" ON ) if ( ENABLE_PERL) add_subdirectory ( perl ) endif ( ENABLE_PERL ) option ( ENABLE_PYTHON "Build the obexftp Python module (using swig)" ON ) if ( ENABLE_PYTHON) add_subdirectory ( python ) endif ( ENABLE_PYTHON ) option ( ENABLE_RUBY "Build the obexftp Ruby module (using swig)" ON ) if ( ENABLE_RUBY) add_subdirectory ( ruby ) endif ( ENABLE_RUBY ) option ( ENABLE_TCL "Build the obexftp Tcl module (using swig)" OFF ) if ( ENABLE_TCL) add_subdirectory ( tcl ) endif ( ENABLE_TCL ) endif ( SWIG_FOUND ) obexftp-0.24.2-Source/swig/client.i000644 001750 001750 00000011166 12201733763 020230 0ustar00hendrikhendrik000000 000000 /* * obexftp/client.i: ObexFTP client library SWIG interface * * Copyright (c) 2005 Christian W. Zuckschwerdt * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ /* perl croaks if this is lowercase. override for every other binding. */ %module OBEXFTP %{ #include #include %} %include "charmap.i" %constant int IRDA = OBEX_TRANS_IRDA; %constant int INET = OBEX_TRANS_INET; %constant int CABLE = OBEX_TRANS_CUSTOM; %constant int BLUETOOTH = OBEX_TRANS_BLUETOOTH; %constant int USB = OBEX_TRANS_USB; %constant int SYNC = OBEX_SYNC_SERVICE; %constant int PUSH = OBEX_PUSH_SERVICE; %constant int FTP = OBEX_FTP_SERVICE; %rename(discover) obexftp_discover; char **obexftp_discover(int transport); %rename(browsebt) obexftp_browse_bt; int obexftp_browse_bt(char *addr, int service); #if defined SWIGPERL #elif defined SWIGPYTHON %typemap(in) (obexftp_info_cb_t infocb, void *user_data) { if (!PyCallable_Check($input)) { /* should raise an exception here */ $1 = NULL; $2 = NULL; } else { Py_XINCREF($input); $1 = proxy_info_cb; $2 = $input; } }; %{ static void proxy_info_cb (int evt, const char *buf, int len, void *data) { PyObject *proc = (PyObject *)data; /* PyObject *msg = PyString_FromStringAndSize(buf, len); */ PyObject_CallFunction(proc, "is", evt, buf); } %} #elif defined SWIGRUBY %typemap(in) (obexftp_info_cb_t infocb, void *user_data) { $1 = proxy_info_cb; SWIG_ConvertPtr($input, &$2, NULL, 0); }; %{ static void proxy_info_cb (int event, const char *buf, int len, void *data) { VALUE proc = SWIG_NewPointerObj(data, NULL, 0); VALUE msg = buf ? rb_str_new(buf, len) : Qnil; rb_funcall(proc, rb_intern("call"), 2, INT2NUM(event), msg); } %} #elif defined SWIGTCL #else #warning "no callbacks for this language" #endif /* Which binding wants this capitalized too? */ %rename(client) obexftp_client_t; #ifdef SWIGRUBY %rename(Client) obexftp_client_t; #endif typedef struct { } obexftp_client_t; %extend obexftp_client_t { obexftp_client_t(int transport) { return obexftp_open(transport, NULL, NULL, NULL); } ~obexftp_client_t() { obexftp_close(self); } void callback(obexftp_info_cb_t infocb, void *user_data) { self->infocb = infocb; self->infocb_data = user_data; } char **discover() { return obexftp_discover(self->transport); } int connect(char *device, int port, char *src=NULL) { return obexftp_connect_src(self, src, device, port, UUID_FBS, sizeof(UUID_FBS)); } int connectpush(char *device, int port, char *src=NULL) { self->quirks &= ~OBEXFTP_SPLIT_SETPATH; return obexftp_connect_src(self, src, device, port, NULL, 0); } int connectsync(char *device, int port, char *src=NULL) { self->quirks &= ~OBEXFTP_SPLIT_SETPATH; return obexftp_connect_src(self, src, device, port, UUID_IRMC, sizeof(UUID_IRMC)); } int disconnect() { return obexftp_disconnect(self); } int chpath(char *name) { return obexftp_setpath(self, name, 0); } int mkpath(char *name) { return obexftp_setpath(self, name, 1); } int cdup() { return obexftp_setpath(self, NULL, 0); } int cdtop() { return obexftp_setpath(self, "", 0); } char *get(char *path) { (void) obexftp_get_type(self, NULL, NULL, path); return (char *)self->buf_data; } char *list(char *path=NULL) { (void) obexftp_get_type(self, XOBEX_LISTING, NULL, path); return (char *)self->buf_data; } char *get_capability(char *path=NULL) { (void) obexftp_get_type(self, XOBEX_CAPABILITY, NULL, path); return (char *)self->buf_data; } int get_file(char *path, char *localname) { return obexftp_get_type(self, NULL, localname, path); } int put_file(char *filename, char *remotename=NULL) { return obexftp_put_file(self, filename, remotename); } int put_data(char *data, size_t size, char *remotename=NULL) { return obexftp_put_data(self, data, size, remotename); } int delete(char *name) { return obexftp_del(self, name); } } obexftp-0.24.2-Source/CMakeModules/000755 001750 001750 00000000000 12701545532 020133 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/CMakeModules/MaintainerMode.cmake000644 001750 001750 00000002703 12656175560 024044 0ustar00hendrikhendrik000000 000000 option ( USE_MAINTAINER_MODE "Enable some stuff only relevant to developers" OFF ) if ( USE_MAINTAINER_MODE ) if ( CMAKE_COMPILER_IS_GNUCC ) set ( MAINTAINER_MODE_WARN_FLAGS all extra no-unused-parameter no-missing-field-initializers declaration-after-statement missing-declarations redundant-decls cast-align error ) set ( MAINTAINER_MODE_FLAGS ) foreach ( flag ${MAINTAINER_MODE_WARN_FLAGS} ) list ( APPEND MAINTAINER_MODE_FLAGS "W${flag}" ) endforeach ( flag ) foreach ( flag ${MAINTAINER_MODE_FLAGS} ) set ( cflag "-${flag}" ) set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${cflag}" ) foreach ( type DEBUG RELEASE MINSIZEREL RELWITHDEBINFO ) set ( CMAKE_C_FLAGS_${type} "${CMAKE_C_FLAGS_${type}} ${cflag}" ) endforeach ( type ) endforeach ( flag ) elseif ( MSVC ) set ( MAINTAINER_MODE_FLAGS W3 WX ) foreach ( flag ${MAINTAINER_MODE_FLAGS} ) set ( cflag "/${flag}" ) set ( CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${cflag}" ) foreach ( type DEBUG RELEASE MINSIZEREL RELWITHDEBINFO ) set ( CMAKE_C_FLAGS_${type} "${CMAKE_C_FLAGS_${type}} ${cflag}" ) endforeach ( type ) endforeach ( flag ) endif ( CMAKE_COMPILER_IS_GNUCC ) # foreach ( type DEBUG RELEASE MINSIZEREL RELWITHDEBINFO ) # message ( "CMAKE_C_FLAGS_${type} set to \"${CMAKE_C_FLAGS_${type}}\"" ) # endforeach ( type ) endif ( USE_MAINTAINER_MODE ) obexftp-0.24.2-Source/CMakeModules/FindFuse.cmake000644 001750 001750 00000004102 12003533401 022620 0ustar00hendrikhendrik000000 000000 # - Find Fuse (file system in userspace) # # It will use PkgConfig if present and supported, else search # it on its own. # # The following standard variables get defined: # Fuse_FOUND: true if fuse was found # Fuse_VERSION_STRING: the version of fuse, if any # Fuse_INCLUDE_DIRS: the directory that contains the include file # Fuse_LIBRARIES: full path to the libraries # Fuse_DEFINITIONS additional compiler flags find_package ( PkgConfig ) if ( PKG_CONFIG_FOUND ) if ( Fuse_FIND_VERSION ) pkg_check_modules ( PKGCONFIG_FUSE fuse=${Fuse_FIND_VERSION} ) else ( Fuse_FIND_VERSION ) pkg_check_modules ( PKGCONFIG_FUSE fuse ) endif ( Fuse_FIND_VERSION ) endif ( PKG_CONFIG_FOUND ) if ( PKGCONFIG_FUSE_FOUND ) set ( Fuse_FOUND ${PKGCONFIG_FUSE_FOUND} ) set ( Fuse_VERSION_STRING ${PKGCONFIG_FUSE_VERSION} ) set ( Fuse_DEFINITIONS ${PKGCONFIG_FUSE_CFLAGS_OTHER} ) set ( Fuse_INCLUDE_DIRS ${PKGCONFIG_FUSE_INCLUDE_DIRS} ) foreach ( i ${PKGCONFIG_FUSE_LIBRARIES} ) find_library ( ${i}_LIBRARY NAMES ${i} PATHS ${PKGCONFIG_FUSE_LIBRARY_DIRS} ) if ( ${i}_LIBRARY ) list ( APPEND Fuse_LIBRARIES ${${i}_LIBRARY} ) endif ( ${i}_LIBRARY ) mark_as_advanced ( ${i}_LIBRARY ) endforeach ( i ) else ( PKGCONFIG_FUSE_FOUND ) find_path ( Fuse_INCLUDE_DIRS NAMES fuse/fuse.h PATH_SUFFIXES include ) mark_as_advanced ( Fuse_INCLUDE_DIRS ) find_library ( fuse_LIBRARY NAMES fuse ) mark_as_advanced ( fuse_LIBRARY ) if ( fuse_LIBRARY ) set ( Fuse_LIBRARIES ${fuse_LIBRARY} ) endif ( fuse_LIBRARY ) set ( Fuse_DEFINITIONS -D_FILE_OFFSET_BITS=64 ) if ( Fuse_INCLUDE_DIRS AND Fuse_LIBRARIES ) set ( Fuse_FOUND true ) endif ( Fuse_INCLUDE_DIRS AND Fuse_LIBRARIES ) endif ( PKGCONFIG_FUSE_FOUND ) if ( NOT Fuse_FOUND ) if ( NOT Fuse_FIND_QUIETLY ) message ( STATUS "Fuse not found." ) endif ( NOT Fuse_FIND_QUIETLY ) if ( Fuse_FIND_REQUIRED ) message ( FATAL_ERROR "" ) endif ( Fuse_FIND_REQUIRED ) endif ( NOT Fuse_FOUND ) obexftp-0.24.2-Source/CMakeModules/FindIconv.cmake000644 001750 001750 00000003013 12270010430 022772 0ustar00hendrikhendrik000000 000000 find_path ( ICONV_INCLUDE_DIR iconv.h ) mark_as_advanced ( ICONV_INCLUDE_DIR ) set ( ICONV_INCLUDE_DIRS ${ICONV_INCLUDE_DIR} ) if ( ICONV_INCLUDE_DIRS ) include ( CheckFunctionExists ) unset ( CMAKE_REQUIRED_FLAGS ) unset ( CMAKE_REQUIRED_DEFINITIONS ) set ( CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIRS} ) unset ( CMAKE_REQUIRED_LIBRARIES ) check_function_exists ( iconv_open ICONV_FOUND ) if ( NOT ICONV_FOUND ) find_library ( iconv_LIBRARY iconv ) if ( iconv_LIBRARY ) set ( CMAKE_REQUIRED_LIBRARIES ${iconv_LIBRARY} ) check_function_exists ( iconv_open ICONV_FOUND ) if ( ICONV_FOUND ) set ( ICONV_LIBRARIES ${iconv_LIBRARY} ) endif ( ICONV_FOUND ) endif ( iconv_LIBRARY ) endif ( NOT ICONV_FOUND ) endif ( ICONV_INCLUDE_DIRS ) if ( ICONV_FOUND ) set ( ICONV_CONST_TEST_SOURCE " #include #include extern #ifdef __cplusplus \"C\" #endif #if defined(__STDC__) || defined(__cplusplus) size_t iconv (iconv_t cd, const char * *inbuf, size_t *inbytesleft, char * *outbuf, size_t *outbytesleft); #else size_t iconv(); #endif int main(void) { return 0; } ") unset ( CMAKE_REQUIRED_FLAGS ) unset ( CMAKE_REQUIRED_DEFINITIONS ) set ( CMAKE_REQUIRED_INCLUDES ${ICONV_INCLUDE_DIRS} ) unset ( CMAKE_REQUIRED_LIBRARIES ) check_c_source_compiles ( "${ICONV_CONST_TEST_SOURCE}" ICONV_USES_CONST ) endif ( ICONV_FOUND ) if ( NOT ICONV_FOUND ) if ( Iconv_REQUIRED ) message ( FATAL_ERROR "Iconv not found" ) endif ( Iconv_REQUIRED ) endif ( NOT ICONV_FOUND ) obexftp-0.24.2-Source/CMakeModules/FindBluetooth.cmake000644 001750 001750 00000007270 12005657005 023705 0ustar00hendrikhendrik000000 000000 # - Find system default bluetooth implementation # # On Linux it will use PkgConfig if present and supported, # else and on all other architectures, it looks for it on its own. # The following standard variables get defined: # Bluetooth_FOUND: true if Bluetooth was found # Bluetooth_INCLUDE_DIRS: the directory that contains the include file # Bluetooth_LIBRARIES: full path to the libraries include ( CheckCSourceCompiles ) include ( CheckLibraryExists ) include ( CheckIncludeFile ) if ( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) find_package ( PkgConfig ) if ( PKG_CONFIG_FOUND ) pkg_check_modules ( PKGCONFIG_BLUEZ bluez ) endif ( PKG_CONFIG_FOUND ) find_path ( Bluetooth_INCLUDE_DIRS NAMES bluetooth/bluetooth.h PATH_SUFFIXES include ) mark_as_advanced ( Bluetooth_INCLUDE_DIRS ) if ( PKGCONFIG_BLUEZ_FOUND ) foreach ( i ${PKGCONFIG_BLUEZ_LIBRARIES} ) find_library ( ${i}_LIBRARY NAMES ${i} PATHS ${PKGCONFIG_BLUEZ_LIBRARY_DIRS} ) mark_as_advanced ( ${i}_LIBRARY ) if ( ${i}_LIBRARY ) list ( APPEND Bluetooth_LIBRARIES ${${i}_LIBRARY} ) endif ( ${i}_LIBRARY ) endforeach ( i ) add_definitions ( -DHAVE_SDPLIB ) else ( PKGCONFIG_BLUEZ_FOUND ) find_library ( bluetooth_LIBRARY NAMES bluetooth PATH_SUFFIXES lib ) mark_as_advanced ( bluetooth_LIBRARY ) if ( bluetooth_LIBRARY ) set ( Bluetooth_LIBRARIES ${bluetooth_LIBRARY} ) endif ( bluetooth_LIBRARY ) endif ( PKGCONFIG_BLUEZ_FOUND ) if ( Bluetooth_INCLUDE_DIRS AND Bluetooth_LIBRARIES ) set ( Bluetooth_FOUND true ) endif ( Bluetooth_INCLUDE_DIRS AND Bluetooth_LIBRARIES ) elseif ( CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" ) find_path ( Bluetooth_INCLUDE_DIRS NAMES bluetooth.h PATH_SUFFIXES include ) mark_as_advanced ( Bluetooth_INCLUDE_DIRS ) find_library ( Bluetooth_LIBRARIES NAMES bluetooth PATH_SUFFIXES lib ) mark_as_advanced ( Bluetooth_LIBRARIES ) if ( Bluetooth_INCLUDE_DIRS ) set ( CMAKE_REQUIRED_INCLUDES ${Bluetooth_INCLUDE_DIRS} ) CHECK_C_SOURCE_COMPILES ( "#include int main () { struct sockaddr_rfcomm f; return 0; }" Bluetooth_FOUND ) endif ( Bluetooth_INCLUDE_DIRS ) elseif ( CMAKE_SYSTEM_NAME STREQUAL "NetBSD" ) find_path ( Bluetooth_INCLUDE_DIRS NAMES bluetooth.h PATH_SUFFIXES include ) mark_as_advanced ( Bluetooth_INCLUDE_DIRS ) find_library ( Bluetooth_LIBRARIES NAMES bluetooth PATH_SUFFIXES lib ) mark_as_advanced ( Bluetooth_LIBRARIES ) if ( Bluetooth_INCLUDE_DIRS ) set ( CMAKE_REQUIRED_INCLUDES ${Bluetooth_INCLUDE_DIRS} ) CHECK_C_SOURCE_COMPILES ( "#include int main () { struct sockaddr_bt f; return 0; }" Bluetooth_FOUND ) endif ( Bluetooth_INCLUDE_DIRS ) elseif ( WIN32 ) CHECK_C_SOURCE_COMPILES ( "#include #include int main () { SOCKADDR_BTH f; return 0; }" Bluetooth_FOUND ) endif ( CMAKE_SYSTEM_NAME STREQUAL "Linux" ) if ( Bluetooth_FOUND ) set ( Bluetooth_FOUND true ) else ( Bluetooth_FOUND ) set ( Bluetooth_FOUND false ) endif ( Bluetooth_FOUND ) if ( NOT Bluetooth_FOUND ) if ( NOT Bluetooth_FIND_QUIETLY ) message ( STATUS "Bluetooth not found." ) endif ( NOT Bluetooth_FIND_QUIETLY ) if ( Bluetooth_FIND_REQUIRED ) message ( FATAL_ERROR "Bluetooth not found but required." ) endif ( Bluetooth_FIND_REQUIRED ) endif ( NOT Bluetooth_FOUND ) obexftp-0.24.2-Source/ChangeLog000644 001750 001750 00000027715 12701527017 017406 0ustar00hendrikhendrik000000 000000 ObexFTP 0.24.2 (released 2016-04-07) ------------------------------------ * obexfs: Parse XML data with Expat library * obexfs: Properly encode XML special characters * obexfs: New option -r to specify root path * obexfs: New option -S to simulate free space * Fix probing * Add support for Gigaset devices * CMake improvements ObexFTP 0.24.1 (released 2014-02-03) ------------------------------------ * Fix build system bugs * Replace CRC implementation in libbfb ObexFTP 0.24 (released 2013-03-05) ---------------------------------- * Maintainer changed from Christian to Hendrik * change build system to using CMake * integrate obexfs-0.12 * fix build for OpenOBEX-1.7 ObexFTP 0.23 (released 2009-02-17) ---------------------------------- * allow win32 to use hci src names * adding a simpler connect wrapper * show OBEX_HandleInput errors * catch errors and let the user know * print timeout stats if available * sdp unregister more verbose * upgrading btkit * fix for win32 without bt * replacing deprecated automake vars * sizeof() fixes * removing bdaddr_t reference from obexftpd.c * adding bootstrap helper * concurrency bug in extconf.rb generated Makefile (fix by Alin Năstac) * switching from POD to asciidoc * clearing gnu-style implicit rules ObexFTP 0.22 (released 2008-06-15) ---------------------------------- * added proper unicode support * added support for transparent OBEX-over-AT mode * rewritten at-command function * added specific error messages * refactored to flexible bt_kit layer * fixed cache root duplicates * fixed off-by-one and unfreed mem in cache layer * added pkg-config file * added example code * switched to doxygen * added python binding callbacks * portable packed structs * enabled linux hci dev names for source selection * Python binding uses distutils now, tested by Adam Williamson * removed exit from bt discovery * Better autodetection for possible language bindings * reworked win32 support * Motorola SLVR L2 cobex fix by Andrey Rahmatullin * now using AC_HELP_STRING for compat with autoconf <=2.57 * added hci selection support, drafted by Manuel Naranjo * switched obexftp cli to new discovery api * prefer PCSUITE over FTP, req. by Martin Storsjö for Series 60 2nd Ed. * fixed compile error with >=swig-1.3.28 * renamed sdp browse function * fixed month/day swapping in atotime, spotted by Dr. Johannes Zellner * added BFC compatibility for newer Siemens phones * added PCSOFTWARE uuid support for SHARP phones * added motorola support * end bfb mode properly * added CPROT=0 support from 3GPP 27.007 * fixed ericsson init * fixed invalid conn_id in disconnect rep. by Alan J. McFarlane * better create flag handling in setpath * Changed LDADD to LIBADD sug. by Sergey Vlasov * obexftpd clean up by Hendrik Sattler * 64-bit fixes by Hendrik Sattler * Removed all (dangerous) obex_headerdata_t casts * Reorganized all swig-dependant Makefiles * Applied cobex write patch from Simon Ruggier * Applied from Frode Isaksen ObexFTP 0.21 (released 2006-06-27) ---------------------------------- 2006-05-26 Christian W. Zuckschwerdt * Fixes to obexftpd suggested by Hendrik Sattler 2006-05-24 Christian W. Zuckschwerdt * Added ruby binding * Added preliminary discovery function ObexFTP 0.20 (released 2006-05-16) ---------------------------------- 2006-05-16 Christian W. Zuckschwerdt * Change __S_IFDIR to S_IFDIR with fallback sug. by Alex Kanavin * Added old CLI switches and documentation sug. by Hendrik Sattler 2006-04-26 Christian W. Zuckschwerdt * Fixed the -g CLI switch (bug reported by many people) 2006-03-08 Christian W. Zuckschwerdt * Added obexfsd written by Alan Zhang * Fixed iconv (found by Stanislav Nikolov) 2006-03-07 Christian W. Zuckschwerdt * device/channel code cleanup ObexFTP 0.19 (released 2006-02-08) ---------------------------------- 2006-02-08 Christian W. Zuckschwerdt * Updated for OpenOBEX 1.1 (pkg-config) 2006-01-26 Christian W. Zuckschwerdt * Added --output switch by Daniel Burr/Andrzej Szombierski. 2006-01-21 Christian W. Zuckschwerdt * Simplified the swig/perl/Makefile.am. ObexFTP 0.18 (released 2006-01-18) ---------------------------------- 2006-01-11 Christian W. Zuckschwerdt * Fixed a pointer typo and a free() typo. 2005-12-12 Christian W. Zuckschwerdt * Added perl, python and tcl binding with swig. 2005-09-15 Christian W. Zuckschwerdt * Quick iconv hack. Needs to be done in openobex. 2005-09-14 Christian W. Zuckschwerdt * Rewrote folder-listing parser to enhance compatibility 2005-09-12 Christian W. Zuckschwerdt * Connection headers by Philip Kovacs 2005-08-06 Christian W. Zuckschwerdt * Nokia hack (suppressing FBS) * Capabilty retrieving by Marco Canini 2005-06-27 Christian W. Zuckschwerdt * USB support, mainly by Daniel Burr 2005-06-19 Christian W. Zuckschwerdt * Added implicit setpath support in every function. 2005-06-11 Christian W. Zuckschwerdt * Fixed quoting problem. Lets hope this wont break libtool. 2005-06-10 Christian W. Zuckschwerdt * Added simple caching * Removed recursive put. Apps should implement it themselves. 2005-06-09 Christian W. Zuckschwerdt * New configure flag to enable building docs (disabled by default now) 2005-03-23 Christian W. Zuckschwerdt * Security fix suggested by Kevin Finisterre 2005-03-21 Christian W. Zuckschwerdt * GCC 2.96 compat fixes by Paul Boddie 2005-01-15 Christian W. Zuckschwerdt * Documentation updated by Hendrik Sattler 2005-01-10 Christian W. Zuckschwerdt * Typo fix to setpath by Olivier Berger * Removed some BT ifdefs by Hendrik Sattler * Use VERSION macro suggested by Andrej Kacian ObexFTP 0.17 (released 2004-12-17) ---------------------------------- 2004-12-17 Christian W. Zuckschwerdt * Added sdp lib checks, reported by George Styles and Johan Debal 2004-12-12 Christian W. Zuckschwerdt * Fixed do_at_cmd, reported by Donald Burns 2004-11-21 Christian W. Zuckschwerdt * Bluetooth device and channel auto-discovery ObexFTP 0.16 (released 2004-11-23) ---------------------------------- 2004-11-20 Christian W. Zuckschwerdt * FreeBSD patch by Bruce Simpson 2004-11-19 Christian W. Zuckschwerdt * Bug fixes (for Sony-Ericsson) by David Haslam ObexFTP 0.15 (released 2004-11-13) ---------------------------------- 2004-11-12 Christian W. Zuckschwerdt * Don't send S45 UUID first (broke other phones too, sorry S45 users) 2004-11-10 Christian W. Zuckschwerdt * Fixed linebreaks in contributed backup script. ObexFTP 0.14 (released 2004-09-26) ---------------------------------- 2004-09-26 Christian W. Zuckschwerdt * Moved vmo converter into a seperate package 2004-09-05 Christian W. Zuckschwerdt * Serial-USB converter fix, Gerhard Reithofer 2004-08-10 Christian W. Zuckschwerdt * Uploads discard path info now. 2004-07-25 Christian W. Zuckschwerdt * Added support for Sony-Ericsson phones, debian Bug#261328 2004-06-11 Christian W. Zuckschwerdt * Version option added 2004-03-05 Christian W. Zuckschwerdt * NetBSD portability patch by Soren S. Jorvang 2004-02-04 Christian W. Zuckschwerdt * Skip transports not linked, François Fleuret 2004-01-30 Christian W. Zuckschwerdt * IrCOMM 1-line show stopper fixed by Stefan Behnel 2003-12-28 Christian W. Zuckschwerdt * setpath patch for T610 by Adam Goode 2003-10-22 Christian W. Zuckschwerdt * bfb_write_packets patch by Jorge Ventura * connection setup fixes (cobex) 2003-10-01 Christian W. Zuckschwerdt * Bluetooth support 2003-09-24 Christian W. Zuckschwerdt * Ericsson phones are now working with the unified cobex. * removed the automatic directory parsing, please just the -c switch. * Shuffled the option names for obexftp to counter missunderstandings. 2003-07-18 Christian W. Zuckschwerdt * fixed a Makefile bug reported by Carwyn Edwards ObexFTP 0.13 (released 2003-04-11) ---------------------------------- 2003-04-11 Christian W. Zuckschwerdt * all but data output goes to stderr now (suggested by Heiko) * The environment variable OBEXFTP_PORT is used as a default. ObexFTP 0.12 (released 2003-02-17) ---------------------------------- 2003-02-17 Christian W. Zuckschwerdt * Added vmo converters (suggested by Dmitry Zakharov) 2003-02-11 Christian W. Zuckschwerdt * Added UUID fallback for C55 (suggested by Hristo Todorov) ObexFTP 0.11 (released 2003-01-26) ---------------------------------- 2003-01-26 Christian W. Zuckschwerdt * Unified BFB and PE; 2003-01-19 Christian W. Zuckschwerdt * C++ compatible header files (suggested Carsten Pfeiffer) ObexFTP 0.10 (released 2003-01-10) ---------------------------------- 2003-01-09 Christian W. Zuckschwerdt * Big file transmission problem solved 2002-11-22 Christian W. Zuckschwerdt * Jan Metz supplied me with his RH8 box and some SL45i connected to it. Finally S45(i) is working. 2002-11-19 Christian W. Zuckschwerdt * this is the last release to support OpenOBEX 0.9.8 2002-11-14 Christian W. Zuckschwerdt * Removed glib dependancy * win32 target is working (tested with mingw) 2002-10-17 Christian W. Zuckschwerdt * Removed Siemens references in favor of OBEX enabled devices * Enhancements for upcoming OpenOBEX 1.0.0 2002-04-29 Christian W. Zuckschwerdt * Erricsson T39m support, req. by Ole Streicher 2002-03-04 Christian W. Zuckschwerdt * Try harder to connect. IRDA needs patience. * Wrote a man page. Should really be a docbook refentry. ObexFTP 0.9 (released 2002-02-18) --------------------------------- ObexFTP 0.8 (released 2002-02-14) --------------------------------- ObexFTP 0.7 (released 2002-02-13) --------------------------------- ObexFTP 0.6 (released 2002-02-12) --------------------------------- ObexFTP 0.5 (released 2002-02-11) --------------------------------- 2002-02-11 Christian W. Zuckschwerdt * cobex now capable of asynch operation ObexFTP 0.4 (released 2002-02-09) --------------------------------- 2002-02-09 Christian W. Zuckschwerdt * Rewrote main using getopt. ObexFTP 0.3 (released 2002-02-08) --------------------------------- 2002-02-08 Christian W. Zuckschwerdt * Fixed BFB protocol (Code 0x01 is ACK not PREPARE...). 2002-02-07 Christian W. Zuckschwerdt * Implemented BFB protocol. ObexFTP 0.2 (released 2002-01-19) --------------------------------- 2002-01-19 Christian W. Zuckschwerdt * Implemented delete and rename. ObexFTP 0.1 (released 2002-01-18) --------------------------------- 2002-01-18 Christian W. Zuckschwerdt * Initial beta. * It's work in progress so expect errors and report/fix then! obexftp-0.24.2-Source/CMakeLists.txt000644 001750 001750 00000006223 12701533651 020364 0ustar00hendrikhendrik000000 000000 cmake_minimum_required( VERSION 3.1 FATAL_ERROR ) cmake_policy ( VERSION 3.1 ) project ( obexftp VERSION 0.24.2 LANGUAGES C ) # # The path for our own CMake modules # set ( CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMakeModules ) include ( MaintainerMode ) include ( GNUInstallDirs ) set ( ENABLE_DEBUG 0 CACHE STRING "Set DEBUG level" ) set_property ( CACHE ENABLE_DEBUG PROPERTY STRINGS 0 1 2 3 4 ) add_definitions( -DOBEXFTP_DEBUG=${ENABLE_DEBUG} ) # # define how to build libraries # option ( BUILD_SHARED_LIBS "Build shared libraries" ON ) # # Set the required C standard: C99 # set ( CMAKE_C_STANDARD 99 ) set ( CMAKE_C_STANDARD_REQUIRED TRUE ) include_directories ( ${PROJECT_SOURCE_DIR} ${PROJECT_SOURCE_DIR}/includes ) # # many parts of this project need the OpenObex includes # find_package ( OpenObex ${OpenObex_FORCE_VERSION} QUIET NO_MODULE) if ( NOT OpenObex_FOUND ) find_package ( OpenObex REQUIRED ) endif ( NOT OpenObex_FOUND ) include_directories ( ${OpenObex_INCLUDE_DIRS} ) # # some code is only included if bluetooth is available # find_package ( Bluetooth ) if ( Bluetooth_FOUND ) include_directories ( ${Bluetooth_INCLUDE_DIRS} ) add_definitions ( -DHAVE_BLUETOOTH -DHAVE_SDP ) endif ( Bluetooth_FOUND ) add_subdirectory ( bfb ) add_subdirectory ( multicobex ) add_subdirectory ( obexftp ) add_subdirectory ( apps ) add_subdirectory ( fuse ) add_subdirectory ( swig ) add_subdirectory ( doc ) #examples set ( prefix "${CMAKE_INSTALL_PREFIX}" ) set ( exec_prefix "\${prefix}" ) set ( libdir "\${prefix}/${CMAKE_INSTALL_LIBDIR}" ) set ( includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}" ) set ( VERSION "${obexftp_VERSION}" ) set ( REQUIRES "bluez openobex" ) configure_file ( ${CMAKE_CURRENT_SOURCE_DIR}/obexftp.pc.in ${CMAKE_CURRENT_BINARY_DIR}/obexftp.pc @ONLY ) if ( NOT CMAKE_INSTALL_PKGCONFIGDIR ) set ( CMAKE_INSTALL_PKGCONFIGDIR ${CMAKE_INSTALL_LIBDIR}/pkgconfig CACHE PATH "Where to install .pc files to" FORCE ) endif ( NOT CMAKE_INSTALL_PKGCONFIGDIR ) mark_as_advanced ( CMAKE_INSTALL_PKGCONFIGDIR ) install ( FILES ${CMAKE_CURRENT_BINARY_DIR}/obexftp.pc DESTINATION ${CMAKE_INSTALL_PKGCONFIGDIR} COMPONENT devel ) # # The following adds CPack support # set ( CPACK_PACKAGE_DESCRIPTION_SUMMARY "ObexFTP" ) set ( CPACK_PACKAGE_VENDOR "The OpenObex Development Team" ) set ( CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt" ) set ( CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README" ) set ( CPACK_PACKAGE_VERSION_MAJOR "${obexftp_VERSION_MAJOR}") set ( CPACK_PACKAGE_VERSION_MINOR "${obexftp_VERSION_MINOR}") set ( CPACK_PACKAGE_VERSION_PATCH "${obexftp_VERSION_PATCH}") set ( CPACK_PACKAGE_VERSION "${obexftp_VERSION}" ) if ( UNIX ) set ( CPACK_GENERATOR "TGZ" ) set ( CPACK_SOURCE_GENERATOR "TGZ" ) elseif ( WIN32 ) # # For NSIS, install from http://nsis.sf.net. # For ZIP, install e.g. info-zip from http://www.info-zip.org. # set ( CPACK_GENERATOR "ZIP;NSIS" ) set ( CPACK_SOURCE_GENERATOR "ZIP" ) endif ( UNIX ) set ( CPACK_SOURCE_IGNORE_FILES "/build/" "/\\\\.git/" "/\\\\.gitignore$" "~$" ) # this must _follow_ the settings! include ( CPack ) obexftp-0.24.2-Source/fuse/000755 001750 001750 00000000000 12701545532 016564 5ustar00hendrikhendrik000000 000000 obexftp-0.24.2-Source/fuse/obexautofs.c000644 001750 001750 00000046636 12656174101 021125 0ustar00hendrikhendrik000000 000000 /* * obexautofs.c: FUSE Filesystem to access OBEX with automount * This is just a wrapper. ObexFTP API does the real work. * * Copyright (c) 2003-2006 Christian W. Zuckschwerdt * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ /* strndup */ #define _GNU_SOURCE /* at least fuse v 2.2 is needed */ #define FUSE_USE_VERSION 22 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define UNUSED(x) x __attribute__((unused)) #define DEBUGOUPUT #ifdef DEBUGOUPUT #define DEBUG(...) fprintf(stderr, __VA_ARGS__) #else #define DEBUG(...) do { } while (0) #endif typedef struct connection connection_t; struct connection { char *alias; int transport; char *addr; int channel; obexftp_client_t *cli; int nodal; int recent; connection_t *next; }; #define SCAN_INTERVAL 2 static time_t last_scan = 0; static connection_t *connections; static char *tty = NULL; // "/dev/ttyS0"; static char *source = NULL; // "00:11:22:33:44:55"; "hci0"; static int search_irda = 1; static int search_bt = 1; static int search_usb = 1; static int nonblock = 0; static int discover_irda(void) { return -1; } static int discover_usb(void) { char **devices, **dev; char name[25], *p; connection_t *conn; DEBUG("Scanning USB...\n"); devices = obexftp_discover(OBEX_TRANS_USB); for(dev = devices; *dev; dev++) { strcpy(name, "usb"); strncpy(&name[3], *dev, sizeof(name)-4); p = strchr(name, ' '); if (p) *p = '\0'; DEBUG("Found %s (%d), %s\n", name, atoi(*dev), *dev); for (conn = connections; conn; conn = conn->next) { if (!strcmp(conn->addr, name)) { conn->recent++; break; } } if (!conn) { DEBUG("Adding %s\n", name); conn = calloc(1, sizeof(connection_t)); if (!conn) return -1; conn->alias = NULL; conn->transport = OBEX_TRANS_USB; conn->addr = strdup(name); conn->channel = atoi(*dev); //conn->cli = cli_open(OBEX_TRANS_USB, NULL, conn->channel); conn->recent++; conn->next = connections; connections = conn; } } return 0; } static int discover_tty(char *UNUSED(port)) { return -1; } static int discover_bt(void) { char *hci = NULL; char **devs, **dev, *name; connection_t *conn; DEBUG("Scanning ...\n"); devs = obexftp_discover_bt_src(hci); if(!devs) { perror("Inquiry failed."); return -1; } for(dev = devs; dev && *dev; dev++) { for (conn = connections; conn; conn = conn->next) { if (!strcmp(conn->addr, *dev)) { conn->recent++; break; } } if (!conn) { name = obexftp_bt_name_src(*dev, hci); DEBUG("Adding\t%s\t%s\n", *dev, name); conn = calloc(1, sizeof(connection_t)); if (!conn) return -1; conn->alias = name; conn->transport = OBEX_TRANS_BLUETOOTH; conn->addr = *dev; conn->channel = obexftp_browse_bt_ftp(conn->addr); //conn->cli = cli_open(OBEX_TRANS_BLUETOOTH, conn->addr, conn->channel); conn->recent++; conn->next = connections; connections = conn; } else free(*dev); } free(devs); return 0; } static void cli_close(obexftp_client_t *cli); static int discover_devices(void) { connection_t *conn, *prev; for (conn = connections; conn; conn = conn->next) conn->recent = 0; if (search_irda) discover_irda(); if (search_bt) discover_bt(); if (search_usb) discover_usb(); if (tty) discover_tty(tty); /* remove from head */ while (connections && connections->recent == 0) { DEBUG("Deleting %s\n", connections->addr); conn = connections; connections = conn->next; cli_close(conn->cli); if (conn->alias) free(conn->alias); free(conn->addr); free(conn); } /* remove from body */ for (prev = connections; prev; prev = prev->next) if(prev->next && prev->next->recent == 0) { DEBUG("Deleting2 %s\n", prev->next->addr); conn = prev->next; prev->next = conn->next; cli_close(conn->cli); if (conn->alias) free(conn->alias); free(conn->addr); free(conn); } return 0; } typedef struct data_buffer data_buffer_t; struct data_buffer { size_t size; char *data; int write_mode; /* is this a write buffer? */ }; static char *mknod_dummy = NULL; /* bad coder, no biscuits! */ /* connection handling operations */ static obexftp_client_t *cli_open(int transport, char *addr, int channel) { obexftp_client_t *cli; int retry; /* Open */ cli = obexftp_open (transport, NULL, NULL, NULL); if(cli == NULL) { /* Error opening obexftp-client */ return NULL; } for (retry = 0; retry < 3; retry++) { /* Connect */ if (obexftp_connect_src (cli, source, addr, channel, UUID_FBS, sizeof(UUID_FBS)) >= 0) return cli; /* Still trying to connect */ sleep(1); } return NULL; } static void cli_close(obexftp_client_t *cli) { if (!cli) return; /* Disconnect */ (void) obexftp_disconnect (cli); /* Close */ obexftp_close (cli); } static int ofs_connect(connection_t *conn) { if (!conn || !conn->cli) return -ENOENT; if (nonblock) { if (++conn->nodal > 1) { conn->nodal--; return -EBUSY; } } else { while (++conn->nodal > 1) { conn->nodal--; sleep(1); } } DEBUG("%s() >>>blocking<<<\n", __func__); return 0; } static void ofs_disconnect(connection_t *conn) { if (!conn || !conn->cli) return; /* -ENOENT */ conn->nodal--; DEBUG("%s() <<>>\n", __func__); } static connection_t *ofs_find_connection(const char *path, char **filepath) { int namelen; connection_t *conn; if (!path || path[0] != '/') { DEBUG("Invalid base path \"%s\"\n", path); return NULL; } path++; *filepath = strchr(path, '/'); if (*filepath) namelen = *filepath - path; else namelen = strlen(path); for (conn = connections; conn; conn = conn->next) { if (!strncmp(conn->addr, path, namelen) || (conn->alias && !strncmp(conn->alias, path, namelen))) { if (!conn->cli) conn->cli = cli_open(conn->transport, conn->addr, conn->channel); return conn; } } return NULL; } /* file and directory operations */ static int ofs_getattr(const char *path, struct stat *stbuf) { connection_t *conn; char *filepath; stat_entry_t *st; int res; if(!path || *path == '\0' || !strcmp(path, "/")) { /* root */ stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 1; /* should be NSUB+2 for dirs */ stbuf->st_uid = getuid(); stbuf->st_gid = getgid(); stbuf->st_size = 0; stbuf->st_blocks = 0; stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = time(NULL); return 0; } DEBUG("%s() '%s'\n", __func__, path); if (mknod_dummy && !strcmp(path, mknod_dummy)) { /* fresh mknod dummy */ stbuf->st_mode = S_IFREG | 0755; stbuf->st_nlink = 1; /* should be NSUB+2 for dirs */ stbuf->st_uid = getuid(); stbuf->st_gid = getgid(); stbuf->st_size = 0; stbuf->st_blocks = 0; stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = time(NULL); free(mknod_dummy); mknod_dummy = NULL; return 0; } conn = ofs_find_connection(path, &filepath); if (!conn) return -ENOENT; if(!filepath) { /* the device entry itself */ if (!strcmp(path + 1, conn->addr)) stbuf->st_mode = S_IFDIR | 0755; else stbuf->st_mode = S_IFLNK | 0777; stbuf->st_nlink = 1; /* should be NSUB+2 for dirs */ stbuf->st_uid = getuid(); stbuf->st_gid = getgid(); stbuf->st_size = 0; stbuf->st_blocks = 0; stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = time(NULL); return 0; } res = ofs_connect(conn); if(res < 0) return res; /* errno */ st = obexftp_stat(conn->cli, filepath); ofs_disconnect(conn); if (!st) return -ENOENT; stbuf->st_mode = st->mode; stbuf->st_nlink = 1; /* should be NSUB+2 for dirs */ stbuf->st_uid = getuid(); stbuf->st_gid = getgid(); stbuf->st_size = st->size; stbuf->st_blksize = 512; /* they expect us to do so... */ stbuf->st_blocks = (st->size + stbuf->st_blksize) / stbuf->st_blksize; stbuf->st_mtime = st->mtime; stbuf->st_atime = st->mtime; stbuf->st_ctime = st->mtime; return 0; } static int ofs_readlink (const char *path, char *link, size_t UNUSED(size)) { connection_t *conn; for (conn = connections; conn; conn = conn->next) { if(conn->alias && !strcmp(conn->alias, path + 1)) { strcpy(link, conn->addr); return 0; } } return -ENOENT; } static int ofs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) { connection_t *conn; char *filepath; DIR *dir; stat_entry_t *ent; int res; if(!path || *path == '\0' || !strcmp(path, "/")) { /* list devices */ if (last_scan + SCAN_INTERVAL < time(NULL)) { discover_devices(); last_scan = time(NULL); } DEBUG("listing devices...\n"); res = filler(h, ".", DT_DIR, 0); res = filler(h, "..", DT_DIR, 0); for (conn = connections; conn; conn = conn->next) { if (conn->alias) res = filler(h, conn->alias, DT_LNK, 0); res = filler(h, conn->addr, DT_DIR, 0); if(res != 0) break; } return 0; } conn = ofs_find_connection(path, &filepath); if (!conn) return -1; /* FIXME */ res = ofs_connect(conn); if(res < 0) return res; /* errno */ dir = obexftp_opendir(conn->cli, filepath); if (!dir) { ofs_disconnect(conn); return -ENOENT; } res = filler(h, ".", DT_DIR, 0); res = filler(h, "..", DT_DIR, 0); while ((ent = obexftp_readdir(dir)) != NULL) { DEBUG("GETDIR:%s\n", ent->name); res = filler(h, ent->name, S_ISDIR(ent->mode) ? DT_DIR : DT_REG, 0); if(res != 0) break; } obexftp_closedir(dir); ofs_disconnect(conn); return 0; } /* needed for creating files and writing to them */ static int ofs_mknod(const char *path, mode_t UNUSED(mode), dev_t UNUSED(dev)) { /* check for access */ /* create dummy for subsequent stat */ if (mknod_dummy) { free(mknod_dummy); fprintf(stderr, "warning: overlapping mknod calls.\n"); } mknod_dummy = strdup(path); return 0; } static int ofs_mkdir(const char *path, mode_t UNUSED(mode)) { connection_t *conn; char *filepath; int res; if(!path || *path != '/') return 0; conn = ofs_find_connection(path, &filepath); if (!conn) return -1; /* FIXME */ res = ofs_connect(conn); if(res < 0) return res; /* errno */ (void) obexftp_setpath(conn->cli, filepath, 1); ofs_disconnect(conn); return 0; } static int ofs_unlink(const char *path) { connection_t *conn; char *filepath; int res; if(!path || *path != '/') return 0; conn = ofs_find_connection(path, &filepath); if (!conn) return -1; /* FIXME */ res = ofs_connect(conn); if(res < 0) return res; /* errno */ (void) obexftp_del(conn->cli, filepath); ofs_disconnect(conn); return 0; } static int ofs_rename(const char *from, const char *to) { connection_t *conn; char *filepath; int res; if(!from || *from != '/') return 0; if(!to || *to != '/') return 0; conn = ofs_find_connection(from, &filepath); if (!conn) return -1; /* FIXME */ res = ofs_connect(conn); if(res < 0) return res; /* errno */ (void) obexftp_rename(conn->cli, from, to); ofs_disconnect(conn); return 0; } /* needed for overwriting files */ static int ofs_truncate(const char *UNUSED(path), off_t UNUSED(offset)) { DEBUG("%s() called. This is a dummy!\n", __func__); return 0; } /* well RWX for everyone I guess! */ static int ofs_open(const char *UNUSED(path), struct fuse_file_info *fi) { data_buffer_t *wb; wb = calloc(1, sizeof(data_buffer_t)); if (!wb) return -1; fi->fh = (unsigned long)wb; return 0; } static int ofs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *UNUSED(fi)) { connection_t *conn; char *filepath; data_buffer_t *wb; int res = 0; size_t actual; if(!path || *path != '/') return 0; wb = (data_buffer_t *)fi->fh; if (!wb->data) { conn = ofs_find_connection(path, &filepath); if (!conn) return -1; /* FIXME */ res = ofs_connect(conn); if(res < 0) return res; /* errno */ (void) obexftp_get(conn->cli, NULL, filepath); wb->size = conn->cli->buf_size; wb->data = conn->cli->buf_data; /* would be better to memcpy this */ //conn->cli->buf_data = NULL; /* now the data is ours -- without copying */ ofs_disconnect(conn); } actual = wb->size - offset; if (actual > size) actual = size; DEBUG("reading %s at %" PRId64 " for %zu (peek: %02x\n", path, offset, actual, wb->data[offset]); memcpy(buf, wb->data + offset, actual); return actual; } static int ofs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { data_buffer_t *wb; size_t newsize; DEBUG("Writing %s at %" PRId64 " for %zu\n", path, offset, size); wb = (data_buffer_t *)fi->fh; if (!wb) return -1; if (offset + size > wb->size) newsize = offset + size; else newsize = wb->size; /* don't change the buffer size */ if (!wb->data) wb->data = malloc(newsize); else if (newsize != wb->size) wb->data = realloc(wb->data, newsize); if (!wb->data) return -1; wb->size = newsize; wb->write_mode = 1; DEBUG("memcpy to %p (%p) from %p cnt %zu\n", wb->data + offset, wb->data, buf, size); (void) memcpy(&wb->data[offset], buf, size); return size; } /* careful, this can be a read release or a write release */ static int ofs_release(const char *path, struct fuse_file_info *fi) { connection_t *conn; char *filepath; data_buffer_t *wb; int res; wb = (data_buffer_t *)fi->fh; DEBUG("Releasing: %s (%p)\n", path, wb); if (wb && wb->data && wb->write_mode) { DEBUG("Now writing %s for %zu (%02x)\n", path, wb->size, wb->data[0]); conn = ofs_find_connection(path, &filepath); if (!conn) return -1; /* FIXME */ res = ofs_connect(conn); if(res < 0) return res; /* errno */ (void) obexftp_put_data(conn->cli, (uint8_t*)wb->data, wb->size, filepath); ofs_disconnect(conn); free(wb->data); free(wb); } return 0; } #ifdef SIEMENS /* just sum all clients */ static int ofs_statfs(const char *UNUSED(label), struct statfs *st) { connection_t *conn; int size = 0, free = 0; for (conn = connections; conn; conn = conn->next) if (conn->cli && ofs_connect(conn) >= 0) { /* for S45 */ (void) obexftp_disconnect (conn->cli); (void) obexftp_connect_uuid (conn->cli, conn->addr, conn->channel, UUID_S45, sizeof(UUID_S45)); /* Retrieve Infos */ (void) obexftp_info(conn->cli, 0x01); size += conn->cli->apparam_info; (void) obexftp_info(conn->cli, 0x02); free += conn->cli->apparam_info; DEBUG("%s() GOT FS STAT: %d / %d\n", __func__, free, size); (void) obexftp_disconnect (conn->cli); (void) obexftp_connect (conn->cli, conn->addr, conn->channel); ofs_disconnect(conn); } memset(st, 0, sizeof(struct statfs)); st->f_bsize = 1; /* optimal transfer block size */ st->f_blocks = size; /* total data blocks in file system */ st->f_bfree = free; /* free blocks in fs */ st->f_bavail = free; /* free blocks avail to non-superuser */ /* st->f_files; / * total file nodes in file system */ /* st->f_ffree; / * free file nodes in fs */ /* st->f_namelen; / * maximum length of filenames */ return 0; } #endif static void *ofs_init(void) { /* Open connection */ //res = cli_open(); //if(res < 0) // return res; /* errno */ //discover_bt(&alias, &bdaddr, &channel); //cli_open(); return NULL; } static void ofs_destroy(void *UNUSED(private_data)) { connection_t *conn; DEBUG("terminating...\n"); /* Close connection */ for (conn = connections; conn; conn = conn->next) { cli_close(conn->cli); if (conn->alias) free(conn->alias); free(conn->addr); free(conn); } return; } /* main */ static struct fuse_operations ofs_oper = { getattr: ofs_getattr, readlink: ofs_readlink, opendir: NULL, readdir: NULL, releasedir: NULL, getdir: ofs_getdir, mknod: ofs_mknod, mkdir: ofs_mkdir, symlink: NULL, unlink: ofs_unlink, rmdir: ofs_unlink, rename: ofs_rename, link: NULL, chmod: NULL, chown: NULL, truncate: ofs_truncate, utime: NULL, open: ofs_open, read: ofs_read, write: ofs_write, #ifdef SIEMENS statfs: ofs_statfs, #endif release: ofs_release, flush: NULL, fsync: NULL, init: ofs_init, destroy: ofs_destroy }; int main(int argc, char *argv[]) { while (1) { int option_index = 0; int c; static struct option long_options[] = { {"noirda", no_argument, NULL, 'I'}, {"nobluetooth", no_argument, NULL, 'B'}, {"nousb", no_argument, NULL, 'U'}, {"tty", required_argument, NULL, 't'}, {"hci", required_argument, NULL, 'd'}, {"nonblock", no_argument, NULL, 'N'}, {"help", no_argument, NULL, 'h'}, {"usage", no_argument, NULL, 'h'}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "+IBUt:d:Nh", long_options, &option_index); if (c == -1) break; switch (c) { case 'I': search_irda = 0; break; case 'B': search_bt = 0; break; case 'U': search_usb = 0; break; case 't': if (tty != NULL) free (tty); tty = NULL; if (strcasecmp(optarg, "irda")) tty = optarg; break; case 'd': source = optarg; break; case 'N': nonblock = 1; break; case 'h': /* printf("ObexFS %s\n", VERSION); */ printf("Usage: %s [-I] [-B] [-U] [-t ] [-d ] [-N] [-- ]\n" "Transfer files from/to Mobile Equipment.\n" "Copyright (c) 2002-2005 Christian W. Zuckschwerdt\n" "\n" " -I, --noirda dont search for IrDA devices\n" " -B, --nobluetooth dont search for bluetooth devices\n" " -U, --nousb dont search for usb devices\n" " -t, --tty search for devices at this tty\n\n" " -d, --hci use only this source device address or number\n" " -N, --nonblock nonblocking mode\n\n" " -h, --help, --usage this help text\n\n" "Options to fusermount need to be preceeded by two dashes (--).\n" "\n", argv[0]); exit(0); break; default: printf("Try `%s --help' for more information.\n", argv[0]); exit(0); } } if (!search_irda && !search_bt && !search_usb && !tty) { fprintf(stderr, "No device selected. Use --help for help.\n"); exit(0); } argv[optind-1] = argv[0]; fprintf(stderr, "IrDA searching not available.\n"); fprintf(stderr, "USB searching not available.\n"); fprintf(stderr, "TTY searching not available.\n"); /* loop */ fuse_main(argc-optind+1, &argv[optind-1], &ofs_oper); return 0; } obexftp-0.24.2-Source/fuse/CMakeLists.txt000644 001750 001750 00000001164 12701253753 021327 0ustar00hendrikhendrik000000 000000 find_package ( Fuse ) if ( Fuse_FOUND ) include_directories ( ${Fuse_INCLUDE_DIRS} ) add_definitions ( ${Fuse_DEFINITIONS} ) find_package ( EXPAT REQUIRED ) include_directories ( ${EXPAT_INCLUDE_DIRS} ) add_executable ( obexfs obexfs.c ) target_link_libraries ( obexfs obexftp ${Fuse_LIBRARIES} ${EXPAT_LIBRARIES} ) add_executable ( obexautofs obexautofs.c ) target_link_libraries ( obexautofs obexftp ${Fuse_LIBRARIES} ) install ( TARGETS obexfs obexautofs RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT applications ) endif ( Fuse_FOUND ) obexftp-0.24.2-Source/fuse/obexfs.c000644 001750 001750 00000051161 12701527572 020226 0ustar00hendrikhendrik000000 000000 /* * obexfs.c: FUSE Filesystem to access OBEX * This is just a wrapper. ObexFTP API does the real work. * * Copyright (c) 2003-2006 Christian W. Zuckschwerdt * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * */ /* strndup */ #define _GNU_SOURCE /* at least fuse v 2.2 is needed */ #define FUSE_USE_VERSION 22 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define UNUSED(x) x __attribute__((unused)) #define DEBUGOUPUT #ifdef DEBUGOUPUT #define DEBUG(...) fprintf(stderr, __VA_ARGS__) #else #define DEBUG(...) do { } while (0) #endif typedef struct data_buffer data_buffer_t; struct data_buffer { size_t size; char *data; bool write_mode; /* is this a write buffer? */ }; static obexftp_client_t *cli = NULL; static int transport = 0; static char *source = NULL; // "00:11:22:33:44:55"; "hci0"; static char *device = NULL; // "00:11:22:33:44:55"; "/dev/ttyS0"; static int channel = -1; static char *root = NULL; // "E:"; static int root_len = 0; // Length of 'root'. static bool nonblock = false; // Free/total space (in bytes) to report if can't get real info. static int report_space = 0; static char *mknod_dummy = NULL; /* bad coder, no cookies! */ static int nodal = 0; static char* translate_path(const char* path) { char* tpath = calloc(sizeof(char), root_len + strlen(path) + 1); if (root) strcpy(tpath, root); strcpy(tpath + root_len, path); DEBUG("TRANSLATED: %s\n", tpath); return tpath; } static int cli_open() { int retry; if (cli != NULL) return 0; /* Open */ cli = obexftp_open (transport, NULL, NULL, NULL); if(cli == NULL) { /* Error opening obexftp-client */ return -1; } if (channel < 0) { channel = obexftp_browse_bt_ftp(device); } for (retry = 0; retry < 3; retry++) { /* Connect */ #ifdef SIEMENS_S45 if (obexftp_connect_src (cli, source, device, channel, UUID_S45, sizeof(UUID_S45)) >= 0) #else if (obexftp_connect_src (cli, source, device, channel, UUID_FBS, sizeof(UUID_FBS)) >= 0) #endif return 0; /* Still trying to connect */ sleep(1); } cli = NULL; return -1; } static void cli_close() { if (cli != NULL) { /* Disconnect */ (void) obexftp_disconnect (cli); /* Close */ obexftp_close (cli); } cli = NULL; } static int ofs_connect() { if (!cli) return -1; if (nonblock) { if (++nodal > 1) { nodal--; return -EBUSY; } } else { while (++nodal > 1) { nodal--; sleep(1); } } DEBUG("%s() >>>blocking<<<\n", __func__); return 0; } static void ofs_disconnect() { nodal--; DEBUG("%s() <<>>\n", __func__); } static int ofs_getattr(const char *path, struct stat *stbuf) { char *tpath; stat_entry_t *st; int res; if(!path || *path == '\0' || !strcmp(path, "/")) { stbuf->st_mode = S_IFDIR | 0755; stbuf->st_nlink = 1; /* should be NSUB+2 for dirs */ stbuf->st_uid = getuid(); stbuf->st_gid = getgid(); stbuf->st_size = 0; stbuf->st_blocks = 0; stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = time(NULL); return 0; } DEBUG("%s() '%s'\n", __func__, path); if (mknod_dummy && !strcmp(path, mknod_dummy)) { stbuf->st_mode = S_IFREG | 0755; stbuf->st_nlink = 1; /* should be NSUB+2 for dirs */ stbuf->st_uid = getuid(); stbuf->st_gid = getgid(); stbuf->st_size = 0; stbuf->st_blocks = 0; stbuf->st_atime = stbuf->st_mtime = stbuf->st_ctime = time(NULL); free(mknod_dummy); mknod_dummy = NULL; return 0; } res = ofs_connect(); if(res < 0) return res; /* errno */ tpath = translate_path(path); st = obexftp_stat(cli, tpath); free(tpath); ofs_disconnect(); if (!st) return -ENOENT; stbuf->st_mode = st->mode; stbuf->st_nlink = 1; /* should be NSUB+2 for dirs */ stbuf->st_uid = getuid(); stbuf->st_gid = getgid(); stbuf->st_size = st->size; stbuf->st_blksize = 512; /* they expect us to do so... */ stbuf->st_blocks = (st->size + stbuf->st_blksize) / stbuf->st_blksize; stbuf->st_mtime = st->mtime; stbuf->st_atime = st->mtime; stbuf->st_ctime = st->mtime; return 0; } static int ofs_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t filler) { char *tpath; DIR *dir; stat_entry_t *ent; int res; res = ofs_connect(); if(res < 0) return res; /* errno */ tpath = translate_path(path); dir = obexftp_opendir(cli, tpath); if (!dir) { free(tpath); ofs_disconnect(); return -ENOENT; } res = filler(h, ".", DT_DIR, 0); res = filler(h, "..", DT_DIR, 0); while ((ent = obexftp_readdir(dir)) != NULL) { DEBUG("GETDIR:%s\n", ent->name); res = filler(h, ent->name, S_ISDIR(ent->mode) ? DT_DIR : DT_REG, 0); if(res != 0) break; } obexftp_closedir(dir); free(tpath); ofs_disconnect(); return 0; } /* needed for creating files and writing to them */ static int ofs_mknod(const char *path, mode_t UNUSED(mode), dev_t UNUSED(dev)) { /* check for access */ /* create dummy for subsequent stat */ if (mknod_dummy) { free(mknod_dummy); fprintf(stderr, "warning: overlapping mknod calls.\n"); } mknod_dummy = strdup(path); return 0; } static int ofs_mkdir(const char *path, mode_t UNUSED(mode)) { char *tpath; int res; if(!path || *path != '/') return 0; res = ofs_connect(); if(res < 0) return res; /* errno */ tpath = translate_path(path); (void) obexftp_setpath(cli, tpath, 1); free(tpath); ofs_disconnect(); return 0; } static int ofs_unlink(const char *path) { char *tpath; int res; if(!path || *path != '/') return 0; res = ofs_connect(); if(res < 0) return res; /* errno */ tpath = translate_path(path); (void) obexftp_del(cli, tpath); free(tpath); ofs_disconnect(); return 0; } static int ofs_rename(const char *from, const char *to) { char *tfrom, *tto; int res; if(!from || *from != '/') return 0; if(!to || *to != '/') return 0; res = ofs_connect(); if(res < 0) return res; /* errno */ tfrom = translate_path(from); tto = translate_path(to); (void) obexftp_rename(cli, tfrom, tto); free(tto); free(tfrom); ofs_disconnect(); return 0; } /* needed for overwriting files */ static int ofs_truncate(const char *UNUSED(path), off_t UNUSED(offset)) { DEBUG("%s() called. This is a dummy!\n", __func__); return 0; } /* well RWX for everyone I guess! */ static int ofs_open(const char *UNUSED(path), struct fuse_file_info *fi) { data_buffer_t *wb; wb = calloc(1, sizeof(data_buffer_t)); if (!wb) return -1; fi->fh = (unsigned long)wb; return 0; } static int ofs_read(const char *path, char *buf, size_t size, off_t offset, struct fuse_file_info *UNUSED(fi)) { char *tpath; data_buffer_t *wb; int res = 0; size_t actual; if(!path || *path != '/') return 0; wb = (data_buffer_t *)fi->fh; if (!wb->data) { res = ofs_connect(); if(res < 0) return res; /* errno */ tpath = translate_path(path); (void) obexftp_get(cli, NULL, tpath); free(tpath); wb->size = cli->buf_size; wb->data = cli->buf_data; /* would be better to memcpy this */ //cli->buf_data = NULL; /* now the data is ours -- without copying */ ofs_disconnect(); } actual = wb->size - offset; if (actual > size) actual = size; DEBUG("reading %s at %" PRId64 " for %zu (peek: %02x\n", path, offset, actual, wb->data[offset]); memcpy(buf, wb->data + offset, actual); return actual; } static int ofs_write(const char *path, const char *buf, size_t size, off_t offset, struct fuse_file_info *fi) { data_buffer_t *wb; size_t newsize; DEBUG("Writing %s at %" PRId64 " for %zu\n", path, offset, size); wb = (data_buffer_t *)fi->fh; if (!wb) return -1; if (offset + size > wb->size) newsize = offset + size; else newsize = wb->size; /* don't change the buffer size */ if (!wb->data) wb->data = malloc(newsize); else if (newsize != wb->size) wb->data = realloc(wb->data, newsize); if (!wb->data) return -1; wb->size = newsize; wb->write_mode = true; DEBUG("memcpy to %p (%p) from %p cnt %zu\n", wb->data + offset, wb->data, buf, size); (void) memcpy(&wb->data[offset], buf, size); return size; } /* careful, this can be a read release or a write release */ static int ofs_release(const char *path, struct fuse_file_info *fi) { char *tpath; data_buffer_t *wb; int res; wb = (data_buffer_t *)fi->fh; DEBUG("Releasing: %s (%p)\n", path, wb); if (wb && wb->data && wb->write_mode) { DEBUG("Now writing %s for %zu (%02x)\n", path, wb->size, wb->data[0]); res = ofs_connect(); if(res < 0) return res; /* errno */ tpath = translate_path(path); (void) obexftp_put_data(cli, (uint8_t *)wb->data, wb->size, tpath); free(tpath); ofs_disconnect(); free(wb->data); free(wb); } return 0; } struct parsing_data { /* Input */ const char *path; /* Intermediate states */ enum state_t { PS_ROOT = 0, PS_CAPABILITY, PS_GENERAL, PS_MEMORY, PS_MEM_TYPE, PS_LOCATION, PS_FREE, PS_USED, PS_FILENLEN, PS_FINISH, PS_ERROR, } state; // State based on found XML tags int depth; // XML tag depth char *mem_location; unsigned long mem_used; unsigned long mem_free; unsigned long mem_namelen; int path_match_len; // Needed to find best-matching entry /* Output */ const char *error; struct statfs meminfo; }; static void xml_element_start(void* user_data, const char* name, const char** UNUSED(attrs)) { struct parsing_data *data = (struct parsing_data*)user_data; switch (data->state) { case PS_ROOT: if (data->depth == 0 && strcmp(name, "Capability") == 0) { data->state = PS_CAPABILITY; } else { data->error = "Root element must be \"Capability\""; data->state = PS_ERROR; } break; case PS_CAPABILITY: if (data->depth == 1 && strcmp(name, "General") == 0) data->state = PS_GENERAL; break; case PS_GENERAL: if (data->depth == 2 && strcmp(name, "Memory") == 0) data->state = PS_MEMORY; break; case PS_MEMORY: if (data->depth == 3) { if (strcmp(name, "MemType") == 0) data->state = PS_MEM_TYPE; else if (strcmp(name, "Location") == 0) data->state = PS_LOCATION; else if (strcmp(name, "Free") == 0) data->state = PS_FREE; else if (strcmp(name, "Used") == 0) data->state = PS_USED; else if (strcmp(name, "FileNLen") == 0) data->state = PS_FILENLEN; } break; case PS_MEM_TYPE: case PS_LOCATION: case PS_FREE: case PS_USED: case PS_FILENLEN: // Memory properties must be plain text. data->error = "Memory properties must be plain text, no elements inside are allowed"; data->state = PS_ERROR; break; case PS_FINISH: case PS_ERROR: break; } ++(data->depth); } static void xml_element_end(void* user_data, const char* name) { struct parsing_data *data = (struct parsing_data*)user_data; (data->depth)--; switch (data->state) { case PS_ROOT: break; case PS_CAPABILITY: if (data->depth == 0 && strcmp(name, "Capability") == 0) { data->error = "\"General\" section not found"; data->state = PS_ERROR; } break; case PS_GENERAL: if (data->depth == 1 && strcmp(name, "General") == 0) data->state = PS_FINISH; break; case PS_MEMORY: if (data->depth == 2 && strcmp(name, "Memory") == 0) { bool use_memory_entry = false; ssize_t len = data->mem_location? strlen(data->mem_location): 0; data->state = PS_GENERAL; if (len == 0 && data->path_match_len < 0) { /* use memory entry in case that it contains no/empty * location entry and there was no previous location */ use_memory_entry = true; data->path_match_len = 0; } else { /* Check if this memory entity is a better match */ if (data->path_match_len < len && len <= (int)strlen(data->path) && strncasecmp(data->path, data->mem_location, len) == 0 && (data->path[len] == '/' || data->path[len] == 0)) { use_memory_entry = true; data->path_match_len = len; } } if (use_memory_entry) { data->meminfo.f_bsize = 1; data->meminfo.f_blocks = data->mem_used + data->mem_free; data->meminfo.f_bfree = data->mem_free; data->meminfo.f_bavail = data->mem_free; data->meminfo.f_namelen = data->mem_namelen; } if (data->mem_location) free(data->mem_location); } break; case PS_MEM_TYPE: case PS_LOCATION: case PS_FREE: case PS_USED: case PS_FILENLEN: data->state = PS_MEMORY; break; case PS_FINISH: case PS_ERROR: break; } } static unsigned long parse_ulong(const char* str) { long result; errno = 0; result = strtol(str, NULL, 10); //check invalid string or invalid value if (errno == 0 || result >= 0) return (unsigned long)result; return 0UL; } static void xml_character_data(void* user_data, const char* str, int len) { struct parsing_data *data = (struct parsing_data*)user_data; int i; char *tmp = NULL; switch (data->state) { case PS_MEM_TYPE: break; case PS_LOCATION: if (len > 0) { data->mem_location = strndup(str, len); /* Convert path separators to unix type */ for (i = 0; i < len; ++i) { if (data->mem_location[i] == '\\') data->mem_location[i] = '/'; } /* Remove trailing directory separator */ if (data->mem_location[len-1] == '/') data->mem_location[len-1] = 0; } break; case PS_FREE: tmp = strndup(str, len); data->mem_free = parse_ulong(tmp); break; case PS_USED: tmp = strndup(str, len); data->mem_used = parse_ulong(tmp); break; case PS_FILENLEN: tmp = strndup(str, len); data->mem_namelen = parse_ulong(tmp); break; default: break; } if (tmp) free(tmp); } static int ofs_statfs(const char *path, struct statfs *st) { int res; char *tpath = translate_path(path); DEBUG("%s() %s\n", __FUNCTION__, path); memset(st, 0, sizeof(*st)); st->f_bsize = 1; st->f_blocks = report_space; st->f_bfree = report_space; st->f_bavail = report_space; res = ofs_connect(); if(res < 0) return res; /* errno */ #ifdef SIEMENS_S45 /* Retrieve Infos */ (void) obexftp_info(cli, 0x01); st->f_blocks = cli->apparam_info; (void) obexftp_info(cli, 0x02); st->f_bfree = cli->apparam_info; st->f_bavail = st->f_bfree; #else (void) obexftp_setpath(cli, tpath, 1); res = obexftp_get_type(cli, XOBEX_CAPABILITY, 0, 0); if (res >= 0) { XML_Parser parser; struct parsing_data data; memset(&data, 0, sizeof(data)); data.path = tpath + 1; data.path_match_len = -1; parser = XML_ParserCreate(NULL); XML_SetUserData(parser, &data); XML_SetElementHandler(parser, xml_element_start, xml_element_end); XML_SetCharacterDataHandler(parser, xml_character_data); if (XML_Parse(parser, cli->buf_data, cli->buf_size, 1)) { if (data.error) { DEBUG("%s(): PARSE ERROR: %s\n", __func__, data.error); } else if (data.path_match_len >= 0) { *st = data.meminfo; } } else { DEBUG("%s(): PARSE ERROR: %s at line %d\n", __func__, XML_ErrorString(XML_GetErrorCode(parser)), XML_GetCurrentLineNumber(parser) ); } XML_ParserFree(parser); } #endif DEBUG("%s() GOT FS STAT: %" PRId64 " / %" PRId64 "\n", __func__, st->f_bfree, st->f_blocks); ofs_disconnect(); free(tpath); return 0; } static void *ofs_init(void) { //cli_open(); return NULL; } static void ofs_destroy(void *UNUSED(private_data)) { fprintf(stderr, "terminating...\n"); cli_close(); return; } static int ofs_utime(const char *a, struct utimbuf *b) { return 0; } static int ofs_chmod(const char *a, mode_t b) { return 0; } static int ofs_chown(const char *a, uid_t b, gid_t c) { return 0; } static struct fuse_operations ofs_oper = { getattr: ofs_getattr, readlink: NULL, opendir: NULL, readdir: NULL, releasedir: NULL, getdir: ofs_getdir, mknod: ofs_mknod, mkdir: ofs_mkdir, symlink: NULL, unlink: ofs_unlink, rmdir: ofs_unlink, rename: ofs_rename, link: NULL, chmod: ofs_chmod, chown: ofs_chown, truncate: ofs_truncate, utime: ofs_utime, open: ofs_open, read: ofs_read, write: ofs_write, statfs: ofs_statfs, release: ofs_release, flush: NULL, fsync: NULL, init: ofs_init, destroy: ofs_destroy }; int main(int argc, char *argv[]) { int res; while (1) { int option_index = 0; int c; static struct option long_options[] = { {"irda", no_argument, NULL, 'i'}, {"bluetooth", required_argument, NULL, 'b'}, {"channel", required_argument, NULL, 'B'}, {"hci", required_argument, NULL, 'd'}, {"usb", required_argument, NULL, 'u'}, {"tty", required_argument, NULL, 't'}, {"network", required_argument, NULL, 'n'}, {"root", required_argument, NULL, 'r'}, {"nonblock", no_argument, NULL, 'N'}, {"report-space",required_argument, NULL, 'S'}, {"help", no_argument, NULL, 'h'}, {"usage", no_argument, NULL, 'h'}, {0, 0, 0, 0} }; c = getopt_long (argc, argv, "+ib:B:d:u:t:n:r:NS:h", long_options, &option_index); if (c == -1) break; switch (c) { case 'i': transport = OBEX_TRANS_IRDA; device = NULL; channel = 0; break; case 'b': transport = OBEX_TRANS_BLUETOOTH; device = optarg; channel = -1; break; case 'B': channel = atoi(optarg); break; case 'd': source = optarg; break; case 'u': if (geteuid() != 0) fprintf(stderr, "If USB doesn't work setup permissions in udev or run as superuser.\n"); transport = OBEX_TRANS_USB; device = NULL; channel = atoi(optarg); break; case 't': transport = OBEX_TRANS_CUSTOM; device = optarg; channel = 0; break; case 'n': transport = OBEX_TRANS_INET; device = optarg; channel = 650; { char *p =strchr(optarg, ':'); if (p) { *p = '\0'; channel = atoi(++p); } } { int n; if (sscanf(optarg, "%d.%d.%d.%d", &n, &n, &n, &n) != 4) fprintf(stderr, "Please use dotted quad notation.\n"); } break; case 'r': root = optarg; break; case 'N': nonblock = true; break; case 'S': report_space = atoi(optarg); break; case 'h': /* printf("ObexFS %s\n", VERSION); */ printf("Usage: %s [-i | -b [-B ] [-d ] | -u | -t | -n ] [-- ]\n" "Transfer files from/to Mobile Equipment.\n" "Copyright (c) 2002-2005 Christian W. Zuckschwerdt\n" "\n" " -i, --irda connect using IrDA transport\n" " -b, --bluetooth connect to this bluetooth device\n" " -B, --channel use this bluetooth channel when connecting\n" " -d, --hci use source device with this address or number\n" " -u, --usb connect to this usb interface number\n" " -t, --tty connect to this tty using a custom transport\n" " -n, --network connect to this network host\n\n" " -r, --root path on device to use as root\n\n" " -N, --nonblock nonblocking mode\n" " -S, --report-space report this number as total/free space\n\n" " -h, --help, --usage this help text\n\n" "Options to fusermount need to be preceeded by two dashes (--).\n" "\n", argv[0]); exit(0); break; default: printf("Try `%s --help' for more information.\n", argv[0]); exit(0); } } if (transport == 0) { fprintf(stderr, "No device selected. Use --help for help.\n"); exit(0); } if (root == NULL) root = ""; root_len = strlen(root); while (root_len > 0 && (root[root_len-1] == '/' || root[root_len-1] == '\\')) { root[root_len-1] = '\0'; --root_len; } argv[optind-1] = argv[0]; /* Open connection */ res = cli_open(); if(res < 0) return res; /* errno */ /* loop */ fuse_main(argc-optind+1, &argv[optind-1], &ofs_oper); /* Close connection */ cli_close(); return 0; } obexftp-0.24.2-Source/License.txt000644 001750 001750 00000002640 12270545272 017751 0ustar00hendrikhendrik000000 000000 Licenses ======== The files bfb/crcmodel.c bfb/crcmodel.h bfb/crctable.h bfb/irda_fcs.c bfb/irda_fcs.h are copied (with small modifications) from A Painless Guide to CRC Error Detection Algorithms Copyright (C) 1993 Ross Williams and are in the public domain. ================================================================================ All other .h and .c files are distributed under the license as stated at the start of each file. This is either LGPLv2+ or GPLv2+. ================================================================================ The files used by the CMake build system have the following license: Copyright (C) 2011-2014 Hendrik Sattler This is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with these files. If not, see . Alternatively, you can use the same license that CMake is licensed with. obexftp-0.24.2-Source/GPL-2.txt000644 001750 001750 00000043254 12270545403 017152 0ustar00hendrikhendrik000000 000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. obexftp-0.24.2-Source/LGPL-2.1.txt000644 001750 001750 00000063642 12270545417 017435 0ustar00hendrikhendrik000000 000000 GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it!