summaryrefslogtreecommitdiff
path: root/xdg-vfs-gnome
diff options
context:
space:
mode:
Diffstat (limited to 'xdg-vfs-gnome')
-rw-r--r--xdg-vfs-gnome/.cvsignore26
-rw-r--r--xdg-vfs-gnome/AUTHORS1
-rw-r--r--xdg-vfs-gnome/COPYING18
-rw-r--r--xdg-vfs-gnome/ChangeLog7
-rw-r--r--xdg-vfs-gnome/INSTALL236
-rw-r--r--xdg-vfs-gnome/Makefile.am1
-rw-r--r--xdg-vfs-gnome/Makefile.cvs6
-rw-r--r--xdg-vfs-gnome/NEWS1
-rw-r--r--xdg-vfs-gnome/README132
-rw-r--r--xdg-vfs-gnome/configure.ac27
-rw-r--r--xdg-vfs-gnome/desc/xdg-vfs.xml475
-rw-r--r--xdg-vfs-gnome/src/.cvsignore8
-rw-r--r--xdg-vfs-gnome/src/Makefile.am13
-rw-r--r--xdg-vfs-gnome/src/xdg_vfs.c531
-rw-r--r--xdg-vfs-gnome/src/xdg_vfs.h135
-rw-r--r--xdg-vfs-gnome/src/xdg_vfs_common.h146
-rw-r--r--xdg-vfs-gnome/src/xdg_vfs_gnome.c1099
-rw-r--r--xdg-vfs-gnome/src/xdg_vfs_gnome.h39
-rw-r--r--xdg-vfs-gnome/src/xdg_vfs_gnome_monitor.c238
-rw-r--r--xdg-vfs-gnome/src/xdg_vfs_gnome_volumes.c521
20 files changed, 3660 insertions, 0 deletions
diff --git a/xdg-vfs-gnome/.cvsignore b/xdg-vfs-gnome/.cvsignore
new file mode 100644
index 0000000..280e90a
--- /dev/null
+++ b/xdg-vfs-gnome/.cvsignore
@@ -0,0 +1,26 @@
+*.la
+*.lo
+*.o
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.cache
+config.h
+config.h.in
+config.log
+config.status
+configure
+libtool
+config.guess
+config.sub
+depcomp
+install-sh
+ltmain.sh
+missing
+stamp-h1
+.libs
+.deps
+.cdtproject
+.project
+
diff --git a/xdg-vfs-gnome/AUTHORS b/xdg-vfs-gnome/AUTHORS
new file mode 100644
index 0000000..25d341d
--- /dev/null
+++ b/xdg-vfs-gnome/AUTHORS
@@ -0,0 +1 @@
+Norbert Frese (nf2@scheinwelt.at) 2006 \ No newline at end of file
diff --git a/xdg-vfs-gnome/COPYING b/xdg-vfs-gnome/COPYING
new file mode 100644
index 0000000..1edf08c
--- /dev/null
+++ b/xdg-vfs-gnome/COPYING
@@ -0,0 +1,18 @@
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
diff --git a/xdg-vfs-gnome/ChangeLog b/xdg-vfs-gnome/ChangeLog
new file mode 100644
index 0000000..ede0d5c
--- /dev/null
+++ b/xdg-vfs-gnome/ChangeLog
@@ -0,0 +1,7 @@
+2005-11-21 gettextize <bug-gnu-gettext@gnu.org>
+
+ * Makefile.am (SUBDIRS): Add po.
+ (ACLOCAL_AMFLAGS): New variable.
+ (EXTRA_DIST): New variable.
+ * configure.ac (AC_OUTPUT): Add po/Makefile.in.
+
diff --git a/xdg-vfs-gnome/INSTALL b/xdg-vfs-gnome/INSTALL
new file mode 100644
index 0000000..23e5f25
--- /dev/null
+++ b/xdg-vfs-gnome/INSTALL
@@ -0,0 +1,236 @@
+Installation Instructions
+*************************
+
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
+unlimited permission to copy, distribute and modify it.
+
+Basic Installation
+==================
+
+These are generic installation instructions.
+
+ The `configure' shell script attempts to guess correct values for
+various system-dependent variables used during compilation. It uses
+those values to create a `Makefile' in each directory of the package.
+It may also create one or more `.h' files containing system-dependent
+definitions. Finally, it creates a shell script `config.status' that
+you can run in the future to recreate the current configuration, and a
+file `config.log' containing compiler output (useful mainly for
+debugging `configure').
+
+ It can also use an optional file (typically called `config.cache'
+and enabled with `--cache-file=config.cache' or simply `-C') that saves
+the results of its tests to speed up reconfiguring. (Caching is
+disabled by default to prevent problems with accidental use of stale
+cache files.)
+
+ If you need to do unusual things to compile the package, please try
+to figure out how `configure' could check whether to do them, and mail
+diffs or instructions to the address given in the `README' so they can
+be considered for the next release. If you are using the cache, and at
+some point `config.cache' contains results you don't want to keep, you
+may remove or edit it.
+
+ The file `configure.ac' (or `configure.in') is used to create
+`configure' by a program called `autoconf'. You only need
+`configure.ac' if you want to change it or regenerate `configure' using
+a newer version of `autoconf'.
+
+The simplest way to compile this package is:
+
+ 1. `cd' to the directory containing the package's source code and type
+ `./configure' to configure the package for your system. If you're
+ using `csh' on an old version of System V, you might need to type
+ `sh ./configure' instead to prevent `csh' from trying to execute
+ `configure' itself.
+
+ Running `configure' takes awhile. While running, it prints some
+ messages telling which features it is checking for.
+
+ 2. Type `make' to compile the package.
+
+ 3. Optionally, type `make check' to run any self-tests that come with
+ the package.
+
+ 4. Type `make install' to install the programs and any data files and
+ documentation.
+
+ 5. You can remove the program binaries and object files from the
+ source code directory by typing `make clean'. To also remove the
+ files that `configure' created (so you can compile the package for
+ a different kind of computer), type `make distclean'. There is
+ also a `make maintainer-clean' target, but that is intended mainly
+ for the package's developers. If you use it, you may have to get
+ all sorts of other programs in order to regenerate files that came
+ with the distribution.
+
+Compilers and Options
+=====================
+
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about. Run `./configure --help' for
+details on some of the pertinent environment variables.
+
+ You can give `configure' initial values for configuration parameters
+by setting variables in the command line or in the environment. Here
+is an example:
+
+ ./configure CC=c89 CFLAGS=-O2 LIBS=-lposix
+
+ *Note Defining Variables::, for more details.
+
+Compiling For Multiple Architectures
+====================================
+
+You can compile the package for more than one kind of computer at the
+same time, by placing the object files for each architecture in their
+own directory. To do this, you must use a version of `make' that
+supports the `VPATH' variable, such as GNU `make'. `cd' to the
+directory where you want the object files and executables to go and run
+the `configure' script. `configure' automatically checks for the
+source code in the directory that `configure' is in and in `..'.
+
+ If you have to use a `make' that does not support the `VPATH'
+variable, you have to compile the package for one architecture at a
+time in the source code directory. After you have installed the
+package for one architecture, use `make distclean' before reconfiguring
+for another architecture.
+
+Installation Names
+==================
+
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc. You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
+
+ You can specify separate installation prefixes for
+architecture-specific files and architecture-independent files. If you
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
+
+ In addition, if you use an unusual directory layout you can give
+options like `--bindir=DIR' to specify different values for particular
+kinds of files. Run `configure --help' for a list of the directories
+you can set and what kinds of files go in them.
+
+ If the package supports it, you can cause programs to be installed
+with an extra prefix or suffix on their names by giving `configure' the
+option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
+
+Optional Features
+=================
+
+Some packages pay attention to `--enable-FEATURE' options to
+`configure', where FEATURE indicates an optional part of the package.
+They may also pay attention to `--with-PACKAGE' options, where PACKAGE
+is something like `gnu-as' or `x' (for the X Window System). The
+`README' should mention any `--enable-' and `--with-' options that the
+package recognizes.
+
+ For packages that use the X Window System, `configure' can usually
+find the X include and library files automatically, but if it doesn't,
+you can use the `configure' options `--x-includes=DIR' and
+`--x-libraries=DIR' to specify their locations.
+
+Specifying the System Type
+==========================
+
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
+`--build=TYPE' option. TYPE can either be a short name for the system
+type, such as `sun4', or a canonical name which has the form:
+
+ CPU-COMPANY-SYSTEM
+
+where SYSTEM can have one of these forms:
+
+ OS KERNEL-OS
+
+ See the file `config.sub' for the possible values of each field. If
+`config.sub' isn't included in this package, then this package doesn't
+need to know the machine type.
+
+ If you are _building_ compiler tools for cross-compiling, you should
+use the option `--target=TYPE' to select the type of system they will
+produce code for.
+
+ If you want to _use_ a cross compiler, that generates code for a
+platform different from the build platform, you should specify the
+"host" platform (i.e., that on which the generated programs will
+eventually be run) with `--host=TYPE'.
+
+Sharing Defaults
+================
+
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
+`configure' looks for `PREFIX/share/config.site' if it exists, then
+`PREFIX/etc/config.site' if it exists. Or, you can set the
+`CONFIG_SITE' environment variable to the location of the site script.
+A warning: not all `configure' scripts look for a site script.
+
+Defining Variables
+==================
+
+Variables not defined in a site shell script can be set in the
+environment passed to `configure'. However, some packages may run
+configure again during the build, and the customized values of these
+variables may be lost. In order to avoid this problem, you should set
+them in the `configure' command line, using `VAR=value'. For example:
+
+ ./configure CC=/usr/local2/bin/gcc
+
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script). Here is a another example:
+
+ /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
+configuration-related scripts to be executed by `/bin/bash'.
+
+`configure' Invocation
+======================
+
+`configure' recognizes the following options to control how it operates.
+
+`--help'
+`-h'
+ Print a summary of the options to `configure', and exit.
+
+`--version'
+`-V'
+ Print the version of Autoconf used to generate the `configure'
+ script, and exit.
+
+`--cache-file=FILE'
+ Enable the cache: use and save the results of the tests in FILE,
+ traditionally `config.cache'. FILE defaults to `/dev/null' to
+ disable caching.
+
+`--config-cache'
+`-C'
+ Alias for `--cache-file=config.cache'.
+
+`--quiet'
+`--silent'
+`-q'
+ Do not print messages saying which checks are being made. To
+ suppress all normal output, redirect it to `/dev/null' (any error
+ messages will still be shown).
+
+`--srcdir=DIR'
+ Look for the package's source code in directory DIR. Usually
+ `configure' can determine that directory automatically.
+
+`configure' also accepts some other, not widely useful, options. Run
+`configure --help' for more details.
+
diff --git a/xdg-vfs-gnome/Makefile.am b/xdg-vfs-gnome/Makefile.am
new file mode 100644
index 0000000..af437a6
--- /dev/null
+++ b/xdg-vfs-gnome/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src
diff --git a/xdg-vfs-gnome/Makefile.cvs b/xdg-vfs-gnome/Makefile.cvs
new file mode 100644
index 0000000..1e17bc9
--- /dev/null
+++ b/xdg-vfs-gnome/Makefile.cvs
@@ -0,0 +1,6 @@
+all:
+ @libtoolize
+ @aclocal
+ @autoheader
+ @automake --add-missing
+ @autoconf
diff --git a/xdg-vfs-gnome/NEWS b/xdg-vfs-gnome/NEWS
new file mode 100644
index 0000000..4af1832
--- /dev/null
+++ b/xdg-vfs-gnome/NEWS
@@ -0,0 +1 @@
+None \ No newline at end of file
diff --git a/xdg-vfs-gnome/README b/xdg-vfs-gnome/README
new file mode 100644
index 0000000..177431f
--- /dev/null
+++ b/xdg-vfs-gnome/README
@@ -0,0 +1,132 @@
+XDG_VFS_GNOME
+=============
+
+xdg_vfs_gnome is a command line client for gnome-vfs. It can read and write
+files, list directories, open file-dialogs,... File-data is not stored in
+temporary files, but instead is pushed/pulled via stdin and stdout.
+
+xdg_vfs_gnome is linked to the gnomeui libraries and therefore will pop up password dialogs etc. (which the gnome-vfs command line utilities can't)
+
+The aim of 'xdg_vfs_gnome' is to give third party desktop applications access
+to Gnome-VFS without linking to the Gnome-libraries directly. It could be hidden behind a generic 'xdg_vfs' script, which switches between KIO,
+Gnome-VFS,... command line clients.
+
+
+Samples:
+========
+
+-) reading a file
+
+$ xdg_vfs_gnome get file:///etc/lilo.conf
+
+$ xdg_vfs_gnome get http://www.freedesktop.org
+
+will stream a remote file to stdout which could be read into the hosts
+applications memory via the C-function popen(..,'r');
+
+$ xdg_vfs_gnome openfiledlg --instant-get
+
+will open a file-dialog to browse to a remote or local file and instantly
+stream the file-data of the selected file to stdout.
+
+$ xdg_vfs_gnome openfiledlg --instant-get --qry-fileinfo --slow-mime --tagged
+
+By adding those switches xdg_vfs_gnome will also 'stat' the remote file and
+try to detect it's mime-type, size,...
+
+-) writing a file
+
+$ cat /etc/passwd | xdg_vfs_gnome put ftp://user@host/mydir/file.txt
+
+or use something like popen(..,'w') to stream file-data to create a remote file.
+
+-) listing a directory
+
+$ xdg_vfs_gnome ls sftp://user@host/dir/
+
+
+There are two operation modes:
+==============================
+
+*) single command
+
+*) shell mode (like the command-line ftp client). In shell mode the
+ host application can talk to 'xdg_vfs_gnome' by connecting to the
+ stdin and stdout pipes to execute a sequence of vfs commands.
+ (for instance QProcess or functions like g_spawn_async_with_pipes() allow
+ connecting to stdin and stdout of a child process)
+
+The advantage of shell mode is that passwords are kept in memory
+(the user doesn't have log in again and again) and avoiding startup-delay
+when executing multiple commands (for instance if the client application
+is a file-manager)
+
+Tagged-mode:
+============
+
+the -t, --tagged option tells xdg_gnome_vfs to add 'labels' when a command
+returns multiple 'parts'. For instance
+
+> xdg_vfs_gnome openfiledlg --instant-get --qry-fileinfo --tagged
+
+will return an [OpenFileDlg], a [FileInfo] and a [Data] section.
+
+Escaping file data:
+===================
+
+When operating in shell- or tagged- mode you will need an escape character
+to signal the end of binary data. This is done via the -e and --escape-data
+switch. By default '~' is the escape character. '~~' has to be treated as
+single '~' and '~\n' as EOF. The escape-character can be changed by
+the -e35 or --escape-data=35 option. (when you want to use '#' ASCII 35 as escape
+character)
+
+Usage screen:
+=============
+
+Usage: xdg_vfs [command] [options] [filename]
+
+ Commands:
+ get [filename] : remote file->stdout
+ info [file or dir] : stat a remote file->stdout
+ put [filename] : stdin->create remote file
+ ls [dir] : list directory
+ openfiledlg [dir] : show open file dialog and return selected file
+ savefiledlg [dir] [fname] : show save file dialog and return selected file
+ shell : interactive mode
+
+ Options:
+ -t, --tagged : tagged mode (file-data should be escaped)
+ -i, --qry-fileinfo : qry file-info when retrieving a file
+ --show-metadata : show metadata when retrieving a file
+ requires tagged mode!
+ -m, --slow-mime : more accurate mime-type detection (slow)
+ -e, --escape-data : escape file data (for end of data detection)
+ -eXXX, --escape-data=XXX : set and use a user defined escape character
+ XXX = ascii code!
+ --end-seperator= : add a custom seperator inbetween blocks
+ --overwrite : allow overwriting files (put)
+ --instant-get : openfiledilog instant get file->stdout
+ --instant-put : savefiledilog instant put file from stdin
+
+
+Todo:
+=====
+
+*) Implement more VFS-Commands (set file-info, mkdir/rmdir, copy, move,...)
+
+*) Progress reporting via stdout
+
+*) multi file-open-dialog
+
+*) Improve exit codes
+
+*) Write xdg_vfs_kde
+
+*) -w switch. Is there a way to pass the window-id to Gnome for accurate placement of dialogs?
+
+*) Write a sample client application (a simple file-manager for instance)
+
+...
+
+
diff --git a/xdg-vfs-gnome/configure.ac b/xdg-vfs-gnome/configure.ac
new file mode 100644
index 0000000..8dc0073
--- /dev/null
+++ b/xdg-vfs-gnome/configure.ac
@@ -0,0 +1,27 @@
+dnl Process this file with autoconf to produce a configure script.
+
+dnl AC_INIT(src/main.c)
+AC_INIT(src/xdg_vfs_gnome.c)
+dnl AM_CONFIG_HEADER(config.h)
+
+PACKAGE=xdg-vfs-gnome
+VERSION=0.1.14
+
+AM_INIT_AUTOMAKE($PACKAGE,$VERSION)
+
+AC_PROG_CC
+AC_STDC_HEADERS
+AC_PROG_INSTALL
+
+AC_ENABLE_SHARED(yes)
+AC_PROG_LIBTOOL
+
+PKG_CHECK_MODULES(DEPS, gtk+-2.0 >= 2.2 gnome-vfs-2.0 >= 2.0 libgnomeui-2.0 >= 2.0)
+
+AC_SUBST(DEPS_CFLAGS)
+AC_SUBST(DEPS_LIBS)
+
+AC_OUTPUT([
+Makefile
+src/Makefile
+])
diff --git a/xdg-vfs-gnome/desc/xdg-vfs.xml b/xdg-vfs-gnome/desc/xdg-vfs.xml
new file mode 100644
index 0000000..cc0e828
--- /dev/null
+++ b/xdg-vfs-gnome/desc/xdg-vfs.xml
@@ -0,0 +1,475 @@
+<?xml version="1.0"?>
+<?xml-stylesheet type="text/xsl"
+ href="http://docbook.sourceforge.net/release/xsl/current/manpages/docbook.xsl"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+ "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
+]>
+<refentry id="xdg-mime">
+ <refentryinfo>
+ <title>xdg-vfs Manual</title>
+ <copyright>
+ <year>2006</year>
+ </copyright>
+ <author>
+ <firstname>Norbert</firstname>
+ <surname>Frese</surname>
+ </author>
+ <address><email>nf2@scheinwelt.at</email></address>
+ <releaseinfo>This is release 0.1 of the xdg-mime Manual.</releaseinfo>
+ </refentryinfo>
+
+ <refmeta>
+ <refentrytitle>xdg-vfs</refentrytitle>
+ <manvolnum>1</manvolnum>
+ </refmeta>
+
+ <refnamediv>
+ <refname>xdg-vfs</refname>
+ <refpurpose>command line tool for accessing the desktops vfs system</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+ <cmdsynopsis>
+ <command>xdg-vfs</command>
+ <arg choice="plain"><option>get</option></arg>
+ <arg><option>--tagged</option>
+ <arg><option>--qry-fileinfo</option>
+ <arg><option>--slow-mime</option></arg>
+ </arg>
+ </arg>
+ <arg><option>--escape-data</option></arg>
+ <arg choice="plain"><replaceable>URI</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>xdg-vfs</command>
+ <arg choice="plain"><option>put</option></arg>
+ <arg><option>--tagged</option></arg>
+ <arg><option>--escape-data</option></arg>
+ <arg><option>--overwrite</option></arg>
+ <arg choice="plain"><replaceable>URI</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>xdg-vfs</command>
+ <arg choice="plain"><option>info</option></arg>
+ <arg><option>--tagged</option></arg>
+ <arg><option>--slow-mime</option></arg>
+ <arg choice="plain"><replaceable>URI</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>xdg-vfs</command>
+ <arg choice="plain"><option>ls</option></arg>
+ <arg><option>--tagged</option></arg>
+ <arg><option>--slow-mime</option></arg>
+ <arg choice="plain"><replaceable>URI</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>xdg-vfs</command>
+ <arg choice="plain"><option>openfiledlg</option></arg>
+ <arg><option>--tagged</option>
+ <arg><option>--qry-fileinfo</option>
+ <arg><option>--slow-mime</option></arg>
+ </arg>
+ </arg>
+ <arg><option>--instant-get</option></arg>
+ <arg><option>--escape-data</option></arg>
+ <arg><replaceable>START_URI</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>xdg-vfs</command>
+ <arg choice="plain"><option>savefiledlg</option></arg>
+ <arg><option>--tagged</option></arg>
+ <arg><option>--instant-put</option></arg>
+ <arg><option>--escape-data</option></arg>
+ <arg><replaceable>START_DIR_URI</replaceable></arg>
+ <arg><replaceable>DEFAULT_FILENAME</replaceable></arg>
+ </cmdsynopsis>
+ <cmdsynopsis>
+ <command>xdg-vfs</command>
+ <arg choice="plain"><option>shell</option></arg>
+ </cmdsynopsis>
+</refsynopsisdiv>
+
+ <refsect1 id="description">
+ <title>Description</title>
+ <para>
+ The xdg-vfs program can be used to access the desktops vfs system.
+ </para>
+ </refsect1>
+ <refsect1 id="commands">
+ <title>Commands</title>
+ <variablelist>
+ <varlistentry>
+ <term><option>get</option></term>
+ <listitem>
+ <simpara>
+ Download a file <replaceable>URI</replaceable> and stream contents to stdout.
+ </simpara>
+ <simpara>
+ In tagged mode it will return <computeroutput>[GET]</computeroutput> as section header,
+ the filename as key/value pair
+ <computeroutput>uri=file:///dir/filename</computeroutput>
+ and the subsection header <computeroutput>(>>>ESCAPED_DATA>>>)</computeroutput> or
+ <computeroutput>(>>>RAW_DATA>>>)</computeroutput> followed by the file-data.
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>put</option></term>
+ <listitem>
+ <simpara>
+ Write a file <replaceable>URI</replaceable> and stream contents from stdin.
+ </simpara>
+ <simpara>
+ In tagged mode it will return <computeroutput>[PUT]</computeroutput> as section header,
+ the filename as key/value pair
+ <computeroutput>uri=file:///dir/filename</computeroutput>
+ and the subsection header <computeroutput>(&lt;&lt;&lt;ESCAPED_DATA&lt;&lt;&lt;)</computeroutput> or
+ <computeroutput>(&lt;&lt;&lt;RAW_DATA&lt;&lt;&lt;)</computeroutput>, waiting for the file-data on stdin.
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>info</option></term>
+ <listitem>
+ <simpara>
+ Determine file-info of <replaceable>URI</replaceable> and determine its mime-type.
+ </simpara>
+ <simpara>
+ In tagged mode it will return <computeroutput>[FILEINFO]</computeroutput> as section header.
+ </simpara>
+ <para>
+ The attributes of the file are described by the following key=value pairs. In case the file is a
+ Symlink, the attributes of the target file will be shown. Therefore the filetype will never be
+ 'SYMLINK'.
+ <variablelist>
+ <varlistentry>
+ <term><computeroutput>uri=</computeroutput></term>
+ <listitem>
+ <simpara>
+ Absolute URI of the file
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><computeroutput>basename=</computeroutput></term>
+ <listitem>
+ <simpara>
+ Filename without path
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><computeroutput>size=</computeroutput></term>
+ <listitem>
+ <simpara>
+ Byte-size of the file
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><computeroutput>permissions=</computeroutput></term>
+ <listitem>
+ <simpara>
+ Permissions (octal)
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><computeroutput>filetype=</computeroutput></term>
+ <listitem>
+ <simpara>
+ <computeroutput>UNKNOWN, REGULAR, DIRECTORY, FIFO, SOCKET,
+ CHARDEV, BLOCKDEV</computeroutput> or <computeroutput>SYMLINK</computeroutput>
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><computeroutput>ctime=, atime=, mtime=</computeroutput></term>
+ <listitem>
+ <simpara>
+ Timestamps
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><computeroutput>userid=, groupid=</computeroutput></term>
+ <listitem>
+ <simpara>
+ User and Group-ID (Gnome-VFS)
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><computeroutput>user=, group=</computeroutput></term>
+ <listitem>
+ <simpara>
+ User- and Groupname (KIO)
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><computeroutput>mimetype=</computeroutput></term>
+ <listitem>
+ <simpara>
+ Mimetype
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><computeroutput>linkdest=</computeroutput></term>
+ <listitem>
+ <simpara>
+ Target if the file is a symbolic link
+ </simpara>
+ </listitem>
+ </varlistentry>
+</variablelist>
+
+
+ </para>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>ls</option></term>
+ <listitem>
+ <simpara>
+ List directory <replaceable>URI</replaceable>.
+ </simpara>
+ <simpara>
+ In tagged mode it will print <computeroutput>[LS]</computeroutput> as section header, and the
+ Entries (same format as for 'info' command) lead by the subheader
+ <computeroutput>(DIRENTRY)</computeroutput>.
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>openfiledlg</option></term>
+ <listitem>
+ <simpara>
+ Show an open-file-dialog and set the inital dir/filename to <replaceable>START_URI</replaceable>. Can be combined
+ with the <command>get</command> command by using the --instant-get switch.
+ </simpara>
+ <simpara>
+ In tagged mode it will print <computeroutput>[OPENFILEDLG]</computeroutput> as section header. The
+ returned key-value pairs are: <computeroutput>selected_localpath=</computeroutput>
+ and <computeroutput>selected_uri=</computeroutput>. The first one will only show up for local files.
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>savefiledlg</option></term>
+ <listitem>
+ <simpara>
+ Show an save-file-dialog and set the inital dir/filename to <replaceable>START_DIR_URI</replaceable>,
+ and the default-filename <replaceable>DEFAULT_FILENAME</replaceable>.
+Can be combined
+ with the <command>put</command> command by using the --instant-put switch.
+ </simpara>
+ <simpara>
+ In tagged mode it will print <computeroutput>[SAVEFILEDLG]</computeroutput> as section header. The
+ returned key-value pairs are: <computeroutput>selected_localpath=</computeroutput>
+ and <computeroutput>selected_uri=</computeroutput>. The first one will only show up for local files.
+ </simpara>
+ </listitem>
+ </varlistentry>
+ <varlistentry>
+ <term><option>shell</option></term>
+ <listitem>
+ <simpara>
+ Enter interactive shell mode (like the command-line ftp client).
+ Will always turn --tagged mode on. --escaped mode is strongly recommended
+ when transfering files via stdin/stdout. In shell mode the
+ host application can talk to <command>xdg-vfs</command> by connecting to the
+ stdin and stdout pipes to execute a sequence of vfs commands.
+ (for instance QProcess or functions like g_spawn_async_with_pipes() allow
+ connecting to stdin and stdout of a child process)
+ </simpara>
+ </listitem>
+ </varlistentry>
+ </variablelist>
+
+ </refsect1>
+
+
+ <refsect1 id="options">
+ <title>Options</title>
+ <variablelist>
+ <varlistentry>
+ <term><option>--tagged, -t</option></term>
+ <listitem>
+ <simpara>
+ Switch to machine parsable <emphasis>tagged-mode</emphasis>.
+ Main sections will have square brackets: <replaceable>[GET]</replaceable>.
+ Subsections will have round brackets: <replaceable>(DIRENTRY)</replaceable>
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term><option>--escape-data, -e</option></term>
+ <listitem>
+ <simpara>
+ Use an <replaceable>escape-character</replaceable> when writing/reading file-data to signal EOF.
+ Strongly recommended in <emphasis>tagged-mode</emphasis>.
+ By default '~' is the escape character. '~~' has to be treated as
+ single '~' and '~\n' as EOF. The escape-character can be changed by
+ the <command>-e35</command> or <command>--escape-data=35</command> option.
+ (when you want to use '#' ASCII 35 as escape
+ character)
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--qry-fileinfo, -i</option></term>
+ <listitem>
+ <simpara>
+ Run fileinfo <command>info</command> command before retieving a file (in commands <command>get</command>
+ or <command>openfiledlg --instant-get</command>.
+ Will only work in <command>--tagged</command> mode.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--overwrite</option></term>
+ <listitem>
+ <simpara>
+ Allow overwriting an existing file in command <command>put</command>.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--instant-get</option></term>
+ <listitem>
+ <simpara>
+ Instantly <command>get</command> data of selected file in a <command>openfiledlg</command>.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--instant-put</option></term>
+ <listitem>
+ <simpara>
+ Instantly <command>put</command> data of selected file in a <command>savefiledlg</command>.
+ The user will be asked if he wants to overwrite the file - therefor the --overwrite flag is assumed 'on'
+ here.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+
+ <varlistentry>
+ <term><option>--help</option></term>
+ <listitem>
+ <simpara>
+ Show this help.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ <varlistentry>
+ <term><option>--version</option></term>
+ <listitem>
+ <simpara>
+ Show the xdg-vfs version information.
+ </simpara>
+ </listitem>
+ </varlistentry>
+
+ </variablelist>
+ </refsect1>
+ <refsect1 id="examples">
+ <title>Examples</title>
+ <para>
+<programlisting>
+xdg-vfs get file:///etc/lilo.conf
+
+xdg-vfs get http://www.freedesktop.org
+</programlisting>
+ Will stream a remote file to stdout which could be read into the hosts
+applications memory via the C-function popen(..,'r');
+ </para>
+ <para>
+<programlisting>
+xdg-vfs openfiledlg --instant-get
+</programlisting>
+ Will open a file-dialog to browse to a remote or local file and instantly
+ stream the file-data of the selected file to stdout.
+
+ </para>
+ <para>
+<programlisting>
+xdg-vfs openfiledlg --instant-get --qry-fileinfo --slow-mime --tagged --escape-data
+</programlisting>
+ By adding those switches xdg_vfs_gnome will also 'stat' the remote file and
+ try to detect it's mime-type, size,... Escaping file-data is always recommended in --tagged mode.
+ </para>
+ <para>
+<programlisting>
+cat /etc/passwd | xdg-vfs put ftp://user@host/mydir/file.txt
+</programlisting>
+ or use something like popen(..,'w') to stream file-data to create a remote file.
+ </para>
+ <para>
+<programlisting>
+xdg-vfs ls sftp://user@host/dir/ --tagged
+</programlisting>
+ List a remote directory. Tagged mode is recommended for listing directories.
+
+ </para>
+ <para>
+ This shows the output of a command in 'tagged' mode (when the user selects /etc/passwd):
+
+<programlisting>
+$ src/xdg_vfs_gnome openfiledlg --instant-get -i --tagged -e
+[OPENFILEDLG]
+selected_localpath=/etc/passwd
+selected_uri=file:///etc/passwd
+[FILEINFO]
+basename=passwd
+size=1389
+userid=0
+groupid=0
+permissions=644
+mtime=1149433809
+atime=1149596399
+ctime=1149433809
+filetype=REGULAR
+mimetype=text/plain
+uri=file:///etc/passwd
+[GET]
+uri=file:///etc/passwd
+(>>>ESCAPED_DATA>>>)
+root:x:0:0:root:/root:/bin/bash
+bin:x:1:1:bin:/bin:/bin/sh
+~
+$
+</programlisting>
+ </para>
+ </refsect1>
+ <refsect1 id="rvals">
+ <title>Return Codes</title>
+ <para>
+ Return values of the xdg-vfs backends:
+<programlisting>
+OK 0
+CANCELED 10
+USAGEERR 11
+NOTSUPPORTED 12
+GENERIC 13
+INITERR 14
+DATAERR 15
+IOERR 16
+NOTPERMITTED 17
+INVALIDURI 18
+</programlisting>
+
+
+ </para>
+ </refsect1>
+
+</refentry>
diff --git a/xdg-vfs-gnome/src/.cvsignore b/xdg-vfs-gnome/src/.cvsignore
new file mode 100644
index 0000000..26a73db
--- /dev/null
+++ b/xdg-vfs-gnome/src/.cvsignore
@@ -0,0 +1,8 @@
+*.la
+*.lo
+*.o
+.deps
+.libs
+Makefile
+Makefile.in
+
diff --git a/xdg-vfs-gnome/src/Makefile.am b/xdg-vfs-gnome/src/Makefile.am
new file mode 100644
index 0000000..712950c
--- /dev/null
+++ b/xdg-vfs-gnome/src/Makefile.am
@@ -0,0 +1,13 @@
+bin_PROGRAMS = xdg_vfs_gnome
+
+xdg_vfs_gnome_SOURCES = xdg_vfs_gnome.c \
+ xdg_vfs.c \
+ xdg_vfs_gnome_volumes.c \
+ xdg_vfs_gnome_monitor.c
+
+xdg_vfs_gnome_LDADD = $(DEPS_LIBS)
+
+AM_CFLAGS = $(DEPS_CFLAGS)
+
+noinst_HEADERS = xdg_vfs.h xdg_vfs_common.h xdg_vfs_gnome.h
+
diff --git a/xdg-vfs-gnome/src/xdg_vfs.c b/xdg-vfs-gnome/src/xdg_vfs.c
new file mode 100644
index 0000000..f0956da
--- /dev/null
+++ b/xdg-vfs-gnome/src/xdg_vfs.c
@@ -0,0 +1,531 @@
+/*
+# xdg_vfs.c
+#
+# Copyright 2006, Norbert Frese
+#
+# LICENSE:
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#---------------------------------------------*/
+
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+#include "xdg_vfs_common.h"
+#include "xdg_vfs.h"
+
+char * end_seperator;
+int data_esc_char= DEFAULT_DATA_ESC_CHAR;
+int xdgvfs_file_permissions = XDGVFS_DEFAULT_FILE_PERMISSIONS;
+int xdgvfs_dir_permissions = XDGVFS_DEFAULT_DIR_PERMISSIONS;
+int debug_mode = 1;
+
+int xdg_vfs_getDataEscChar()
+{
+ return data_esc_char;
+}
+
+char * xdg_vfs_getCustomEndSeparator()
+{
+ return end_seperator;
+}
+
+/**
+* print a key/value pair
+* (value is a string)
+*/
+void xdg_vfs_ppair_str(FILE * f, const char * key, const char * value, int opts)
+{
+ fprintf(f,key);
+ fprintf(f,"=");
+ if (value) fprintf(f,"%s\n", value);
+ else fprintf(f, "\n");
+}
+
+/**
+* look if there is a cancel character on stdin
+*/
+int xdg_vfs_chk_stdin(int wait_secs)
+{
+ /* check for canceled */
+ int filedes = fileno (stdin);
+ int r;
+ fd_set set;
+ struct timeval timeout;
+
+
+ /* Initialize the file descriptor set. */
+ FD_ZERO (&set);
+ FD_SET (filedes, &set);
+
+ /* Initialize the timeout data structure. */
+ timeout.tv_sec = wait_secs;
+ timeout.tv_usec = 0;
+
+ /* select returns 0 if timeout, 1 if input available, -1 if error. */
+ r= select (FD_SETSIZE, &set, NULL, NULL, &timeout);
+ if (r==0) return 0;
+ if (r==-1)
+ {
+ fprintf(stderr, "WARNING: Error when checking stdin for cancel character\n");
+ return -1; /* error! */
+ }
+ return 1;
+}
+
+int xdg_vfs_chk_canceled(int opts) {
+
+ if (!(opts & XDGVFS_OPT_CANCELABLE)) return 0;
+
+ int r = xdg_vfs_chk_stdin(0)==1;
+
+ if (r==1)
+ {
+ int c = getc(stdin);
+ if (c==DEFAULT_CANCEL_CHAR) return 1;
+ fprintf(stderr, "WARNING: Bad cancel character!\n");
+ return 1;
+ }
+ return r;
+}
+
+int empty_stdin() { /* not used */
+
+ /* fclean(stdin); */
+ while (xdg_vfs_chk_stdin(0)==1) {
+ char buf[10];
+ read(stdin, buf, 10);
+ }
+}
+
+
+/**
+* print usage
+*/
+int pusage(int opts)
+{
+ if (!(opts & XDGVFS_OPT_INTERACTIVE_MODE))
+ fprintf(stderr, "Usage: xdg_vfs [command] [options] [filenames]\n");
+ else
+ fprintf(stderr, "Usage: [command] [options] [filename]\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, " Commands: \n");
+
+ fprintf(stderr, " backend : print backend infos\n");
+ fprintf(stderr, " get [uri] : remote file->stdout\n");
+ fprintf(stderr, " put [uri] : stdin->create remote file\n");
+ fprintf(stderr, " info [uri] : stat a remote file\n");
+ fprintf(stderr, " setattrs [uri] : set file attributes\n");
+ fprintf(stderr, " cp [uri] [uri] : copy file\n");
+ fprintf(stderr, " mv [uri] [uri] : move/rename file\n");
+ fprintf(stderr, " rm [uri] : remove file\n");
+ fprintf(stderr, " mkdir [uri] : make directory\n");
+ fprintf(stderr, " rmdir [uri] : remove directory\n");
+ fprintf(stderr, " ls [uri] : list directory\n");
+ fprintf(stderr, " mount [id] : mount\n");
+ fprintf(stderr, " openfiledlg [uri] : show file-save dialog\n");
+ fprintf(stderr, " savefiledlg [uri] [fname] : show file-open dialog\n");
+ if (!(opts & XDGVFS_OPT_INTERACTIVE_MODE))
+ fprintf(stderr, " shell : interactive mode\n");
+ else
+ fprintf(stderr, " quit : exit interactive mode\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, " Options: \n");
+ fprintf(stderr, " -t, --tagged : tagged mode (file-data should be escaped)\n");
+ fprintf(stderr, " -i, --qry-fileinfo : qry file-info when retrieving a file\n");
+ /* fprintf(stderr, " --show-metadata : show metadata when retrieving a file\n"); */
+ fprintf(stderr, " requires tagged mode!\n");
+ fprintf(stderr, " --dive-de-links : dive into desktop-entry links (if folders)\n");
+ fprintf(stderr, " -m, --slow-mime : more accurate mime-type detection (slow)\n");
+ fprintf(stderr, " -e, --escape-data : escape file data (for end of data detection)\n");
+ fprintf(stderr, " -eXXX, --escape-data=XXX : set and use a user defined escape character\n");
+ fprintf(stderr, " XXX = ascii code!\n");
+ fprintf(stderr, " --cancelable : allow sending cancel character to stdin\n");
+ fprintf(stderr, " --user= : setattrs: set user\n");
+ fprintf(stderr, " --group= : setattrs: set group\n");
+ fprintf(stderr, " --permissions= : set permissions when creating a file or dir\n");
+ fprintf(stderr, " : or in setattrs\n");
+ /* fprintf(stderr, " --end-seperator= : add a custom seperator inbetween blocks\n"); */
+ fprintf(stderr, " --overwrite : allow overwriting files (put)\n");
+ fprintf(stderr, " --instant-get : openfiledilog instant get file->stdout\n");
+ fprintf(stderr, " --instant-put : savefiledilog instant put file from stdin\n");
+ fprintf(stderr, " --title= : set dialog title\n");
+ fprintf(stderr, " --progress : show progress when copying or moving a file\n");
+ fprintf(stderr, "\n");
+ return XDGVFS_ERRORCODE_BAD_PARAMETER ;
+}
+
+/**
+* count ordinary args
+*/
+int countargs(int argc, char ** argv)
+{
+ int i;
+ int ctr=0;
+ for (i=0;i<argc;i++)
+ {
+ if (argv[i][0] != '-')
+ {
+ ctr++;
+ }
+ }
+ return ctr;
+}
+
+
+/**
+* get n'th arg ignoring options
+*/
+char * getarg(int argc, char ** argv, int nr)
+{
+ int i;
+ int ctr=0;
+ for (i=0;i<argc;i++)
+ {
+ if (argv[i][0] != '-')
+ {
+ if (ctr++==nr) return argv[i];
+ }
+ }
+ return NULL;
+}
+
+/**
+* get certain option value
+*/
+char * getoptarg(int argc, char ** argv, const char * optname)
+{
+ int i;
+ int ctr=0;
+ for (i=0;i<argc;i++)
+ {
+ if (strncmp (argv[i], optname, strlen(optname))==0) return argv[i]+strlen(optname);
+ }
+ return NULL;
+}
+
+/**
+* execute commands
+*/
+int docommand(int argc, char ** argv, int globopts)
+{
+ char * command; char * s; char * title;
+ int cargs = countargs(argc, argv);
+ int opts = globopts;
+ int r;
+
+ command = getarg(argc,argv, 1);
+
+ if (!command) return pusage(opts);
+
+
+ if (getoptarg(argc,argv, "-t") || getoptarg(argc,argv, "--tagged"))
+ opts |= XDGVFS_OPT_TAGGED;
+ if (getoptarg(argc,argv, "-e") || getoptarg(argc,argv, "--escape-data"))
+ {
+ opts |= XDGVFS_OPT_DATAESCAPED;
+ s = getoptarg(argc,argv, "-e");
+ if (s && strlen(s)>0) data_esc_char = atoi(s);
+ s = getoptarg(argc,argv, "--escape-data=");
+ if (s && strlen(s)>0) data_esc_char = atoi(s);
+ }
+
+ if (getoptarg(argc,argv, "--permissions="))
+ {
+ s = getoptarg(argc,argv, "--permissions=");
+ if (s && strlen(s)>0)
+ {
+ int perms= atoi(s);
+ xdgvfs_file_permissions = perms;
+ xdgvfs_dir_permissions = perms;
+ }
+ }
+
+ if (getoptarg(argc,argv, "-m") || getoptarg(argc,argv, "--slow-mime"))
+ opts |= XDGVFS_OPT_SLOW_MIME_TYPE;
+ if (getoptarg(argc,argv, "--overwrite"))
+ opts |= XDGVFS_OPT_OVERWRITE;
+
+ if (getoptarg(argc,argv, "--cancelable"))
+ opts |= XDGVFS_OPT_CANCELABLE;
+
+ if (getoptarg(argc,argv, "--instant-get"))
+ opts |= XDGVFS_OPT_INSTANT_GET;
+
+ if (getoptarg(argc,argv, "--instant-put"))
+ opts |= XDGVFS_OPT_INSTANT_PUT;
+
+ if (getoptarg(argc,argv, "--dive-de-links"))
+ opts |= XDGVFS_OPT_DIVE_DE_LINKS;
+
+
+ if (getoptarg(argc,argv, "-i") || getoptarg(argc,argv, "--qry-fileinfo"))
+ opts |= XDGVFS_OPT_GET_FILEINFO;
+
+ if (getoptarg(argc,argv, "--show-metadata"))
+ opts |= XDGVFS_OPT_SHOW_METADATA;
+ if (getoptarg(argc,argv, "-p") || getoptarg(argc,argv, "--progress"))
+ opts |= XDGVFS_OPT_PROGRESS;
+
+ title=getoptarg(argc,argv, "--title=");
+
+
+ /* printf("debu=%d %d\n", opts, countargs(argc, argv)); */
+
+ /* get command? */
+ if (cargs == 2 && strcmp(command, "backend")==0)
+ {
+ return xdg_vfs_backend(opts);
+ }
+ else if (cargs == 3 && strcmp(command, "get")==0)
+ {
+ return xdg_vfs_get(getarg(argc,argv, 2), opts);
+ /* info command? */
+ }
+ else if (cargs == 3 && strcmp(command, "info")==0)
+ {
+ return xdg_vfs_getFileInfo(getarg(argc,argv, 2), opts);
+ }
+ else if (cargs == 3 && strcmp(command, "setattrs")==0)
+ {
+ XdgVfsSetFileInfoData fiData = { 0,0,0,0 };
+ fiData.user = getoptarg(argc,argv, "--user=");
+ fiData.group = getoptarg(argc,argv, "--group=");
+ if (getoptarg(argc,argv, "--permissions="))
+ {
+ s = getoptarg(argc,argv, "--permissions=");
+ if (s && strlen(s)>0)
+ {
+ fiData.perms=atoi(s);
+ fiData.setPermsFlag = 1;
+ }
+ }
+ return xdg_vfs_setFileInfo(getarg(argc,argv, 2), &fiData, opts);
+ /* ls caommand? */
+ }
+ else if (cargs == 3 && strcmp(command, "ls")==0)
+ {
+ return xdg_vfs_dir(getarg(argc,argv, 2), opts);
+ /* mount command? */
+ }
+ else if (cargs == 3 && strcmp(command, "mount")==0)
+ {
+ return xdg_vfs_mount(getarg(argc,argv, 2), opts);
+ /* mkdir command? */
+ }
+ else if (cargs == 3 && strcmp(command, "mkdir")==0)
+ {
+ return xdg_vfs_mkdir(getarg(argc,argv, 2), xdgvfs_dir_permissions, opts);
+ }
+ else if (cargs == 3 && strcmp(command, "rmdir")==0)
+ {
+ return xdg_vfs_rmdir(getarg(argc,argv, 2), opts);
+ }
+ else if (cargs == 3 && strcmp(command, "put")==0)
+ {
+ return xdg_vfs_put(getarg(argc,argv, 2), xdgvfs_file_permissions, opts);
+ }
+ else if (cargs == 3 && strcmp(command, "rm")==0)
+ {
+ return xdg_vfs_rm(getarg(argc,argv, 2), opts);
+ }
+ else if (cargs == 3 && strcmp(command, "monfile")==0)
+ {
+ return xdg_vfs_monitor(getarg(argc,argv, 2), 0, opts);
+ }
+ else if (cargs == 3 && strcmp(command, "mondir")==0)
+ {
+ return xdg_vfs_monitor(getarg(argc,argv, 2), 1, opts);
+ }
+ else if (cargs == 3 && strcmp(command, "rmmon")==0)
+ {
+ return xdg_vfs_monitor_cancel(getarg(argc,argv, 2), opts);
+ }
+ else if (cargs >= 2 && strcmp(command, "openfiledlg")==0)
+ {
+ return xdg_vfs_openfiledlg(getarg(argc,argv, 2), NULL, title, opts);
+ }
+ else if (cargs >= 2 && strcmp(command, "savefiledlg")==0)
+ {
+ return xdg_vfs_savefiledlg(getarg(argc,argv, 2),getarg(argc,argv, 3),
+ title, xdgvfs_file_permissions, opts);
+ }
+ else if (cargs == 4 && strcmp(command, "cp")==0)
+ {
+ return xdg_vfs_cp(getarg(argc,argv, 2),getarg(argc,argv, 3), xdgvfs_file_permissions, 0, opts);
+ }
+ else if (cargs == 4 && strcmp(command, "mv")==0)
+ {
+ return xdg_vfs_cp(getarg(argc,argv, 2),getarg(argc,argv, 3), xdgvfs_file_permissions, 1, opts);
+ }
+ else
+ {
+ return pusage(opts);
+ }
+ return 1;
+}
+
+/**
+* main() function
+*/
+int xdg_vfs_main(int argc, char ** argv)
+{
+ if (argc < 2)
+ {
+ return pusage(0);
+ }
+
+ xdg_vfs_init_desklib(argc, argv);
+
+ /* SHELL mode */
+ if (countargs(argc,argv)==2 && strcmp(getarg(argc,argv, 1), "shell")==0)
+ {
+ while(1)
+ {
+ char * lineptr = NULL;
+ ssize_t len;
+ size_t n = 0;
+
+ char ** av = calloc(SHELL_MAXARGS, sizeof(char*));
+ av[0] = "shell";
+ int ac = 1;
+
+ int rcode;
+
+ fprintf(stdout, "> ");
+ fflush(stdout);
+ xdg_vfs_monitor_list_events(0);
+ while (!xdg_vfs_iterate_mainloop_until_incoming_data(fileno(stdin)))
+ {
+ xdg_vfs_monitor_list_events(0);
+ }
+ len=getline (&lineptr, &n, stdin);
+
+ if (len<0) {
+ if (len=EOF) {
+ fprintf(stderr, "xdg-vfs shell mode: stdin closed -> exit\n");
+ exit(XDGVFS_ERRORCODE_IO_ERROR);
+ }
+ perror("xdg-vfs shell mode: stdin problem -> exit");
+ exit(XDGVFS_ERRORCODE_IO_ERROR);
+ }
+
+ /* printf("lineptr=%s len=%d\n", lineptr, len); */
+ /* while(ac < SHELL_MAXARGS && (av[ac]=strtok(ac==1 ? lineptr : NULL, " \n")) )
+ ac++; */
+
+ {
+ char * lout = calloc(strlen(lineptr)+1,1);
+ int c=0;
+ int co=0;
+ av[ac++] = lout; /* first arg */
+ int parsing_error=0;
+ while(lineptr[c]!='\0') /* read shell line into arg array */
+ {
+ if (lineptr[c] == '"') /* quoted strings */
+ {
+ c++;
+ while(lineptr[c]!='\0')
+ {
+ if (lineptr[c] == '\\')
+ {
+
+ c++;
+ if (lineptr[c]=='\\' || lineptr[c]=='"')
+ {
+ lout[co++] = lineptr[c++];
+ continue;
+ } else
+ {
+ fprintf(stderr, "ERROR: Only '\\' or '\"' are allowed to be escaped with '\\' inside double quotes in shell mode!!!\n");
+ parsing_error=1;
+ }
+
+ } else
+ {
+ if (lineptr[c] == '"')
+ {
+ c++;
+ break;
+ }
+ lout[co++] = lineptr[c++];
+ }
+ }
+
+ }
+
+ if (lineptr[c] == ' ')
+ {
+ lout[co] = '\0';
+ av[ac++] = lout+co+1;
+ co++;
+ if (ac >= SHELL_MAXARGS) return XDGVFS_ERRORCODE_BAD_PARAMETER;
+ } else if (lineptr[c] == '\n')
+ {
+ /* skip newline */
+ }
+ else
+ {
+ lout[co++] = lineptr[c];
+ }
+ c++;
+ }
+
+ /* if (debug_mode) fprintf(stderr,"av= %s|%s|%s|%s|%s|%s n=%d\n", av[0], av[1], av[2], av[3], av[4],av[5],ac); */
+
+ if (av[1] && strcmp(av[1], "quit")==0)
+ {
+ fprintf(stderr, "BYE!\n");
+ return 0;
+ }
+
+ if (!parsing_error)
+ {
+ rcode = docommand(ac,av, XDGVFS_OPT_INTERACTIVE_MODE | XDGVFS_OPT_TAGGED);
+ if (rcode==0) fprintf(stdout, "%s\n", XDGVFS_TAG_DONE);
+ else fprintf(stdout, "%s %d\n", XDGVFS_TAG_FAILED, rcode);
+ }
+ else
+ {
+ fprintf(stdout, "%s %d\n", XDGVFS_TAG_FAILED, XDGVFS_ERRORCODE_BAD_PARAMETER);
+ }
+
+ free(lineptr);
+ free(av);
+ free(lout);
+ xdg_vfs_iterate_mainloop();
+ }
+ }
+ /* single command mode */
+ }
+ else
+ {
+ return docommand(argc,argv, 0);
+ }
+
+}
+
+
+
diff --git a/xdg-vfs-gnome/src/xdg_vfs.h b/xdg-vfs-gnome/src/xdg_vfs.h
new file mode 100644
index 0000000..26a87b9
--- /dev/null
+++ b/xdg-vfs-gnome/src/xdg_vfs.h
@@ -0,0 +1,135 @@
+/*
+# xdg_vfs.h
+#
+# Copyright 2006, Norbert Frese
+#
+# LICENSE:
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#---------------------------------------------*/
+
+#ifndef XDG_VFS_H
+#define XDG_VFS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#define DATA_BUF_SIZE 4096
+#define SHELL_MAXARGS 30
+
+#define XDGVFS_DEFAULT_FILE_PERMISSIONS S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
+#define XDGVFS_DEFAULT_DIR_PERMISSIONS S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IXOTH
+
+
+
+
+/* cli option flags */
+
+#define XDGVFS_OPT_TAGGED 1
+#define XDGVFS_OPT_DATAESCAPED 2
+#define XDGVFS_OPT_SLOW_MIME_TYPE 4
+#define XDGVFS_OPT_GET_FILEINFO 8
+#define XDGVFS_OPT_INSTANT_GET 16
+#define XDGVFS_OPT_INSTANT_PUT 32
+#define XDGVFS_OPT_OVERWRITE 64
+#define XDGVFS_OPT_SHOW_METADATA 128
+#define XDGVFS_OPT_INTERACTIVE_MODE 256
+#define XDGVFS_OPT_PROGRESS 512
+#define XDGVFS_OPT_CANCELABLE 1024
+#define XDGVFS_OPT_DIVE_DE_LINKS 2048
+
+
+
+#define XDGVFS_TEXT_SAVEFILEDLG_TITLE "Save File"
+#define XDGVFS_TEXT_OPENFILEDLG_TITLE "Open File"
+
+typedef struct {
+ const char * user;
+ const char * group;
+ unsigned int perms;
+ int setPermsFlag;
+} XdgVfsSetFileInfoData;
+
+/* implementation independent functions */
+
+int xdg_vfs_main(int argc, char ** argv);
+
+int xdg_vfs_getDataEscChar();
+
+char * xdg_vfs_getCustomEndSeparator();
+
+void xdg_vfs_ppair_str(FILE * f, const char * key, const char * value, int opts);
+
+int xdg_vfs_chk_canceled(int opts);
+
+/* implementation functions */
+
+int xdg_vfs_init_desklib(int argc, char** argv);
+
+int xdg_vfs_iterate_mainloop();
+
+int xdg_vfs_iterate_mainloop_until_incoming_data(int fd);
+
+/* command implementations */
+
+int xdg_vfs_backend(int opts);
+
+int xdg_vfs_dir(const char * text_uri, int opts);
+
+int xdg_vfs_mount(const char * mountpoint_id, int opts);
+
+int xdg_vfs_getFileInfo(const char * text_uri, int opts);
+
+int xdg_vfs_setFileInfo(const char * text_uri, XdgVfsSetFileInfoData * fiData, int opts);
+
+int xdg_vfs_get(const char * text_uri, int opts);
+
+int xdg_vfs_put(const char * text_uri, int perms, int opts);
+
+int xdg_vfs_cp(const char * text_uri_src, const char * text_uri_target, unsigned int perms, int move_flag, int opts);
+
+int xdg_vfs_mkdir(const char * text_uri, unsigned int perms, int opts);
+
+int xdg_vfs_rmdir(const char * text_uri, int opts);
+
+int xdg_vfs_rm(const char * text_uri, int opts);
+
+int xdg_vfs_openfiledlg(const char * default_dir, const char * default_filename, const char * title, int opts);
+
+int xdg_vfs_savefiledlg(const char * default_dir, const char * default_filename,
+ const char * title, unsigned int perms, int opts);
+
+int xdg_vfs_monitor(char * uri, int is_directory, int opts);
+
+int xdg_vfs_monitor_cancel(char * uri, int opts);
+
+int xdg_vfs_monitor_list_events(int opts);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/xdg-vfs-gnome/src/xdg_vfs_common.h b/xdg-vfs-gnome/src/xdg_vfs_common.h
new file mode 100644
index 0000000..3963983
--- /dev/null
+++ b/xdg-vfs-gnome/src/xdg_vfs_common.h
@@ -0,0 +1,146 @@
+/*
+# xdg_vfs_common.h
+#
+# Copyright 2006, Norbert Frese
+#
+# LICENSE:
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#---------------------------------------------*/
+
+#ifndef XDG_VFS_COMMON_H
+#define XDG_VFS_COMMON_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define DEFAULT_DATA_ESC_CHAR 126
+#define DEFAULT_CANCEL_CHAR (int)'!'
+
+/* error codes */
+
+#define XDGVFS_ERRORCODE_OK 0
+#define XDGVFS_ERRORCODE_CANCELED 10
+#define XDGVFS_ERRORCODE_BAD_PARAMETER 11
+#define XDGVFS_ERRORCODE_NOT_SUPPORTED 12
+#define XDGVFS_ERRORCODE_GENERIC 13
+#define XDGVFS_ERRORCODE_INIT_ERROR 14
+#define XDGVFS_ERRORCODE_DATA_ERROR 15
+#define XDGVFS_ERRORCODE_IO_ERROR 16
+#define XDGVFS_ERRORCODE_NOT_PERMITTED 17
+#define XDGVFS_ERRORCODE_MALFORMED_URL 18
+#define XDGVFS_ERRORCODE_PROTOCOL_ERROR 19
+#define XDGVFS_ERRORCODE_USR_OR_GRP_NOT_FOUND 20
+#define XDGVFS_ERRORCODE_INTERNAL 21
+#define XDGVFS_ERRORCODE_CANNOT_OPEN_FOR_WRITING 22
+#define XDGVFS_ERRORCODE_CANNOT_OPEN_FOR_READING 23
+#define XDGVFS_ERRORCODE_IS_DIRECTORY 24
+#define XDGVFS_ERRORCODE_IS_FILE 25
+#define XDGVFS_ERRORCODE_NOT_FOUND 26
+#define XDGVFS_ERRORCODE_ALREADY_EXISTS 27
+#define XDGVFS_ERRORCODE_HOST_NOT_FOUND 28
+#define XDGVFS_ERRORCODE_ACCESS_DENIED 29
+#define XDGVFS_ERRORCODE_CANNOT_ENTER_DIRECTORY 30
+#define XDGVFS_ERRORCODE_PROTOCOL_IS_NOT_A_FILESYSTEM 31
+#define XDGVFS_ERRORCODE_LOOP 32
+#define XDGVFS_ERRORCODE_COULD_NOT_CREATE_SOCKET 33
+#define XDGVFS_ERRORCODE_COULD_NOT_CONNECT 34
+#define XDGVFS_ERRORCODE_ERR_CONNECTION_BROKEN 35
+#define XDGVFS_ERRORCODE_COULD_NOT_MOUNT 36
+#define XDGVFS_ERRORCODE_COULD_NOT_UNMOUNT 37
+#define XDGVFS_ERRORCODE_SOCKET_ERROR 38
+#define XDGVFS_ERRORCODE_LOGIN_FAILED 39
+#define XDGVFS_ERRORCODE_OPERATION_FAILED 40
+#define XDGVFS_ERRORCODE_CANNOT_RESUME 41
+#define XDGVFS_ERRORCODE_OUT_OF_MEMORY 42
+#define XDGVFS_ERRORCODE_UNKNOWN_PROXY_HOST 43
+#define XDGVFS_ERRORCODE_ABORTED 44
+#define XDGVFS_ERRORCODE_TIMEOUT 45
+#define XDGVFS_ERRORCODE_SERVICE_NOT_AVAILABLE 46
+#define XDGVFS_ERRORCODE_CANNOT_DELETE_ORIGINAL 47
+#define XDGVFS_ERRORCODE_CANNOT_DELETE_PARTIAL 48
+#define XDGVFS_ERRORCODE_CANNOT_RENAME_ORIGINAL 49
+#define XDGVFS_ERRORCODE_CANNOT_RENAME_PARTIAL 50
+#define XDGVFS_ERRORCODE_NEED_PASSWD 51
+#define XDGVFS_ERRORCODE_NO_CONTENT 52
+#define XDGVFS_ERRORCODE_NO_SPACE 53
+#define XDGVFS_ERRORCODE_IDENTICAL_FILES 54
+#define XDGVFS_ERRORCODE_CORRUPTED_DATA 55
+#define XDGVFS_ERRORCODE_WRONG_FORMAT 56
+#define XDGVFS_ERRORCODE_ERROR_BAD_FILE 66
+#define XDGVFS_ERRORCODE_TOO_BIG 67
+#define XDGVFS_ERRORCODE_NOT_OPEN 68
+#define XDGVFS_ERRORCODE_INVALID_OPEN_MODE 69
+#define XDGVFS_ERRORCODE_TOO_MANY_OPEN_FILES 70
+#define XDGVFS_ERRORCODE_EOF 71
+#define XDGVFS_ERRORCODE_IN_PROGRESS 72
+#define XDGVFS_ERRORCODE_INTERRUPTED 73
+#define XDGVFS_ERRORCODE_HOST_HAS_NO_ADDRESS 74
+#define XDGVFS_ERRORCODE_DIRECTORY_NOT_EMPTY 75
+#define XDGVFS_ERRORCODE_TOO_MANY_LINKS 76
+#define XDGVFS_ERRORCODE_READ_ONLY_FILE_SYSTEM 77
+#define XDGVFS_ERRORCODE_NOT_SAME_FILE_SYSTEM 78
+#define XDGVFS_ERRORCODE_NAME_TOO_LONG 79
+#define XDGVFS_ERRORCODE_SERVICE_OBSOLETE 80
+#define XDGVFS_ERRORCODE_NO_DEFAULT 81
+#define XDGVFS_ERRORCODE_NAMESERVER 82
+#define XDGVFS_ERRORCODE_LOCKED 83
+#define XDGVFS_ERRORCODE_DEPRECATED_FUNCTION 84
+#define XDGVFS_ERRORCODE_DIRECTORY_BUSY 85
+#define XDGVFS_ERRORCODE_NOT_A_DIRECTORY 86
+
+
+/* tags (private!) */
+
+#define XDGVFS_TAG_DATA_OUT "(>>>RAW_DATA>>>)"
+#define XDGVFS_TAG_ESCAPEDDATA_OUT "(>>>ESCAPED_DATA>>>)"
+#define XDGVFS_TAG_DATA_IN "(<<<RAW_DATA<<<)"
+#define XDGVFS_TAG_ESCAPEDDATA_IN "(<<<ESCAPED_DATA<<<)"
+
+#define XDGVFS_TAG_BACKEND "[BACKEND]"
+#define XDGVFS_TAG_GET "[GET]"
+#define XDGVFS_TAG_PUT "[PUT]"
+#define XDGVFS_TAG_CP "[CP]"
+#define XDGVFS_TAG_MV "[MV]"
+#define XDGVFS_TAG_LS "[LS]"
+#define XDGVFS_TAG_FILEINFO "[FILEINFO]"
+#define XDGVFS_TAG_SETATTRS "[SETATTRS]"
+#define XDGVFS_TAG_SAVEFILEDLG "[SAVEFILEDLG]"
+#define XDGVFS_TAG_OPENFILEDLG "[OPENFILEDLG]"
+#define XDGVFS_TAG_MKDIR "[MKDIR]"
+#define XDGVFS_TAG_RMDIR "[RMDIR]"
+#define XDGVFS_TAG_RM "[RM]"
+#define XDGVFS_TAG_MOUNT "[MOUNT]"
+#define XDGVFS_TAG_MONITOREVENT "*"
+
+
+#define XDGVFS_TAG_METADATA "(METADATA)"
+#define XDGVFS_TAG_DIRENTRY "(DIRENTRY)"
+#define XDGVFS_TAG_PROGRESS "(PROGRESS)"
+
+#define XDGVFS_TAG_DONE ":-)"
+#define XDGVFS_TAG_FAILED ":-("
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
diff --git a/xdg-vfs-gnome/src/xdg_vfs_gnome.c b/xdg-vfs-gnome/src/xdg_vfs_gnome.c
new file mode 100644
index 0000000..de13dba
--- /dev/null
+++ b/xdg-vfs-gnome/src/xdg_vfs_gnome.c
@@ -0,0 +1,1099 @@
+/*
+# xdg_vfs_gnome.c
+#
+# Copyright 2006, Norbert Frese
+#
+# LICENSE:
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#---------------------------------------------*/
+
+/**
+ * READ:
+ * http://cvs.gnome.org/viewcvs/libgnomeui/file-chooser/
+ * http://cvs.gnome.org/viewcvs/libgnomeui/libgnomeui/gnome-icon-lookup.c
+ * http://standards.freedesktop.org/desktop-entry-spec/
+ * http://developer.gimp.org/api/2.0/glib/glib-Key-value-file-parser.html
+ * http://developer.gnome.org/doc/API/2.0/gnome-vfs-2.0/
+ *
+ */
+
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libgnomeui/libgnomeui.h>
+#include <time.h>
+
+#include <pwd.h>
+#include <grp.h>
+
+#include "xdg_vfs_common.h"
+#include "xdg_vfs.h"
+#include "xdg_vfs_gnome.h"
+
+#define DESKTOP_GROUP "Desktop Entry"
+
+
+/*
+* translate error codes
+*/
+typedef struct
+{
+ GnomeVFSResult result;
+ int xdgVfsErr;
+} MapGnomeVFSResult;
+
+MapGnomeVFSResult mapGVFSErrArr[] =
+{
+ { GNOME_VFS_OK , XDGVFS_ERRORCODE_OK } ,
+ { GNOME_VFS_ERROR_NOT_FOUND , XDGVFS_ERRORCODE_NOT_FOUND } ,
+ { GNOME_VFS_ERROR_GENERIC , XDGVFS_ERRORCODE_GENERIC } ,
+ { GNOME_VFS_ERROR_INTERNAL , XDGVFS_ERRORCODE_INTERNAL } ,
+ { GNOME_VFS_ERROR_BAD_PARAMETERS , XDGVFS_ERRORCODE_BAD_PARAMETER } ,
+ { GNOME_VFS_ERROR_NOT_SUPPORTED , XDGVFS_ERRORCODE_NOT_SUPPORTED } ,
+ { GNOME_VFS_ERROR_IO , XDGVFS_ERRORCODE_IO_ERROR } ,
+ { GNOME_VFS_ERROR_CORRUPTED_DATA , XDGVFS_ERRORCODE_CORRUPTED_DATA } ,
+ { GNOME_VFS_ERROR_WRONG_FORMAT , XDGVFS_ERRORCODE_WRONG_FORMAT } ,
+ { GNOME_VFS_ERROR_BAD_FILE , XDGVFS_ERRORCODE_ERROR_BAD_FILE } ,
+ { GNOME_VFS_ERROR_TOO_BIG , XDGVFS_ERRORCODE_TOO_BIG } ,
+ { GNOME_VFS_ERROR_NO_SPACE , XDGVFS_ERRORCODE_NO_SPACE } ,
+ { GNOME_VFS_ERROR_READ_ONLY , XDGVFS_ERRORCODE_CANNOT_OPEN_FOR_WRITING } ,
+ { GNOME_VFS_ERROR_INVALID_URI , XDGVFS_ERRORCODE_MALFORMED_URL } ,
+ { GNOME_VFS_ERROR_NOT_OPEN , XDGVFS_ERRORCODE_NOT_OPEN } ,
+ { GNOME_VFS_ERROR_INVALID_OPEN_MODE , XDGVFS_ERRORCODE_INVALID_OPEN_MODE } ,
+ { GNOME_VFS_ERROR_ACCESS_DENIED , XDGVFS_ERRORCODE_ACCESS_DENIED } ,
+ { GNOME_VFS_ERROR_TOO_MANY_OPEN_FILES , XDGVFS_ERRORCODE_TOO_MANY_OPEN_FILES } ,
+ { GNOME_VFS_ERROR_EOF , XDGVFS_ERRORCODE_EOF } ,
+ { GNOME_VFS_ERROR_NOT_A_DIRECTORY , XDGVFS_ERRORCODE_NOT_A_DIRECTORY } ,
+ { GNOME_VFS_ERROR_IN_PROGRESS , XDGVFS_ERRORCODE_IN_PROGRESS } ,
+ { GNOME_VFS_ERROR_INTERRUPTED , XDGVFS_ERRORCODE_INTERRUPTED } ,
+ { GNOME_VFS_ERROR_FILE_EXISTS , XDGVFS_ERRORCODE_ALREADY_EXISTS } ,
+ { GNOME_VFS_ERROR_LOOP , XDGVFS_ERRORCODE_LOOP } ,
+ { GNOME_VFS_ERROR_NOT_PERMITTED , XDGVFS_ERRORCODE_NOT_PERMITTED } ,
+ { GNOME_VFS_ERROR_IS_DIRECTORY , XDGVFS_ERRORCODE_IS_DIRECTORY } ,
+ { GNOME_VFS_ERROR_NO_MEMORY , XDGVFS_ERRORCODE_OUT_OF_MEMORY } ,
+ { GNOME_VFS_ERROR_HOST_NOT_FOUND , XDGVFS_ERRORCODE_HOST_NOT_FOUND } ,
+ { GNOME_VFS_ERROR_INVALID_HOST_NAME , XDGVFS_ERRORCODE_HOST_NOT_FOUND } ,
+ { GNOME_VFS_ERROR_HOST_HAS_NO_ADDRESS , XDGVFS_ERRORCODE_HOST_HAS_NO_ADDRESS } ,
+ { GNOME_VFS_ERROR_LOGIN_FAILED , XDGVFS_ERRORCODE_LOGIN_FAILED } ,
+ { GNOME_VFS_ERROR_CANCELLED , XDGVFS_ERRORCODE_CANCELED } ,
+ { GNOME_VFS_ERROR_DIRECTORY_BUSY , XDGVFS_ERRORCODE_DIRECTORY_BUSY } ,
+ { GNOME_VFS_ERROR_DIRECTORY_NOT_EMPTY , XDGVFS_ERRORCODE_DIRECTORY_NOT_EMPTY } ,
+ { GNOME_VFS_ERROR_TOO_MANY_LINKS , XDGVFS_ERRORCODE_TOO_MANY_LINKS } ,
+ { GNOME_VFS_ERROR_READ_ONLY_FILE_SYSTEM , XDGVFS_ERRORCODE_READ_ONLY_FILE_SYSTEM } ,
+ { GNOME_VFS_ERROR_NOT_SAME_FILE_SYSTEM , XDGVFS_ERRORCODE_NOT_SAME_FILE_SYSTEM } ,
+ { GNOME_VFS_ERROR_NAME_TOO_LONG , XDGVFS_ERRORCODE_NAME_TOO_LONG } ,
+ { GNOME_VFS_ERROR_SERVICE_NOT_AVAILABLE , XDGVFS_ERRORCODE_SERVICE_NOT_AVAILABLE } ,
+ { GNOME_VFS_ERROR_SERVICE_OBSOLETE , XDGVFS_ERRORCODE_SERVICE_OBSOLETE } ,
+ { GNOME_VFS_ERROR_PROTOCOL_ERROR , XDGVFS_ERRORCODE_PROTOCOL_ERROR } ,
+ { GNOME_VFS_ERROR_NO_MASTER_BROWSER , XDGVFS_ERRORCODE_INTERNAL } ,
+ { GNOME_VFS_ERROR_NO_DEFAULT , XDGVFS_ERRORCODE_NO_DEFAULT } ,
+ { GNOME_VFS_ERROR_NO_HANDLER , XDGVFS_ERRORCODE_PROTOCOL_ERROR } ,
+ { GNOME_VFS_ERROR_PARSE , XDGVFS_ERRORCODE_CORRUPTED_DATA } ,
+ { GNOME_VFS_ERROR_LAUNCH , XDGVFS_ERRORCODE_INIT_ERROR } ,
+ { GNOME_VFS_ERROR_TIMEOUT , XDGVFS_ERRORCODE_TIMEOUT } ,
+ { GNOME_VFS_ERROR_NAMESERVER , XDGVFS_ERRORCODE_NAMESERVER } ,
+ { GNOME_VFS_ERROR_LOCKED , XDGVFS_ERRORCODE_LOCKED } ,
+ { GNOME_VFS_ERROR_DEPRECATED_FUNCTION , XDGVFS_ERRORCODE_DEPRECATED_FUNCTION }
+};
+
+int translate_GnomeVFSResult(GnomeVFSResult result)
+{
+ int i;
+ for (i=0;i<sizeof(mapGVFSErrArr)/sizeof(MapGnomeVFSResult);i++)
+ {
+ /* printf(" %d %d\n", mapErrArr[i].kioErr, mapErrArr[i].xdgVfsErr); */
+ if (mapGVFSErrArr[i].result == result) return mapGVFSErrArr[i].xdgVfsErr;
+ }
+ return XDGVFS_ERRORCODE_GENERIC;
+
+}
+
+/**
+* initialize gnome
+*/
+int xdg_vfs_init_desklib(int argc, char** argv)
+{
+ GnomeProgram *my_app;
+ GOptionContext *option_context;
+
+ my_app = gnome_program_init(PACKAGE, VERSION, LIBGNOMEUI_MODULE,
+ argc, argv, GNOME_PARAM_NONE);
+
+ gnome_authentication_manager_init();
+
+ if (!gnome_vfs_init ())
+ {
+ fprintf(stderr, "Count not init Gnome-VFS!\n");
+ return XDGVFS_ERRORCODE_INIT_ERROR;
+ }
+
+ return 0;
+}
+
+/**
+* finish pending GUI-events
+*/
+int xdg_vfs_iterate_mainloop()
+{
+ while (g_main_context_pending (NULL))
+ g_main_context_iteration(NULL, FALSE);
+}
+
+/**
+* print gnome-vfs error
+*/
+int print_and_translate_result(GnomeVFSResult result)
+{
+ const gchar * s;
+ s = gnome_vfs_result_to_string (result);
+
+ fprintf(stderr, "ERROR: GnomeVFSResult=%s\n",s);
+ //free(s);
+ return translate_GnomeVFSResult(result);
+}
+
+#define READ_ENTIRE_FILE_INITAL_BUFSIZE 100
+/**
+ * read entire file for desktop files
+ */
+GnomeVFSResult _gnome_vfs_readEntireFile(const char * text_uri, size_t * size, char ** fileData, int opts)
+{
+ char * buffer = malloc(READ_ENTIRE_FILE_INITAL_BUFSIZE);
+ size_t bufSize = READ_ENTIRE_FILE_INITAL_BUFSIZE;
+ GnomeVFSFileSize bytes_read;
+ int pos=0;
+ char * full_uri = gnome_vfs_make_uri_from_input(text_uri);
+ GnomeVFSHandle *handle;
+ GnomeVFSResult r;
+
+ *fileData = NULL;
+
+ r=gnome_vfs_open(&handle, full_uri, GNOME_VFS_OPEN_READ);
+ if (r!=GNOME_VFS_OK)
+ {
+ return r;
+ }
+
+ while (1)
+ {
+ if (bufSize-pos <= 1) {
+ bufSize += READ_ENTIRE_FILE_INITAL_BUFSIZE;
+ buffer = realloc(buffer, bufSize);
+ }
+
+ r=gnome_vfs_read(handle, buffer+pos, bufSize - pos, &bytes_read);
+ //fprintf(stderr, "gnome-vfs-read fname=%s, pos=%d bufSize=%d bytes_read=%d\n", full_uri, pos, bufSize, bytes_read);
+
+ if (r!=GNOME_VFS_OK)
+ {
+ if (r==GNOME_VFS_ERROR_EOF) {
+ break;
+ }
+ free(buffer);
+ gnome_vfs_close (handle);
+ return r;
+ }
+ pos += bytes_read;
+
+ }
+/* if (pos != size) {
+ free(buffer);
+ fprintf(stderr, "Reading entire file problem pos=%d != size=%d\n", pos, size);
+ gnome_vfs_close (handle);
+ return GNOME_VFS_ERROR_IO;
+ } */
+ *fileData = buffer;
+ *size = pos;
+ return GNOME_VFS_OK;
+}
+
+
+GnomeVFSResult _follow_desktop_link(const char * filename, int opts) {
+ GnomeVFSResult r;
+ GKeyFile *desktop_file;
+ char * desktop_file_data;
+ size_t desktop_file_data_size;
+ GError * gerror = NULL;
+
+ desktop_file = g_key_file_new ();
+
+ r = _gnome_vfs_readEntireFile(filename, &desktop_file_data_size, &desktop_file_data, opts);
+ if (r != GNOME_VFS_OK) return r;
+
+ int parseR = g_key_file_load_from_data(desktop_file,
+ desktop_file_data,
+ desktop_file_data_size,
+ G_KEY_FILE_NONE,
+ &gerror);
+ g_free(desktop_file_data);
+ if (!parseR) {
+ if (gerror != NULL)
+ {
+ fprintf (stderr, "Unable to parse desktop file: %s\n", gerror->message);
+ g_error_free (gerror);
+ g_key_file_free (desktop_file);
+ }
+ }
+
+ gchar *name;
+ gchar *type;
+ gchar *URL;
+ gchar *icon;
+
+ type = g_key_file_get_value (desktop_file, DESKTOP_GROUP, "Type", NULL);
+
+ if (!strncmp (type, "Link", 4) && !strncmp (type, "FSDevice", 8))
+ {
+ g_free(type);
+ g_key_file_free (desktop_file);
+ return ! GNOME_VFS_OK;
+ }
+
+ name = g_key_file_get_value (desktop_file, DESKTOP_GROUP, "Name", NULL);
+
+
+
+ URL = g_key_file_get_value (desktop_file, DESKTOP_GROUP, "URL", NULL);
+
+ icon = g_key_file_get_value (desktop_file, DESKTOP_GROUP, "Icon", NULL);
+
+ if (name) fprintf (stdout, "basename=%s\n", name);
+ if (type) fprintf (stdout, "# de type=%s\n", type);
+ if (URL) fprintf (stdout, "uri=%s\n", URL);
+ if (icon) fprintf (stdout, "iconname=%s\n", icon);
+
+ fprintf(stdout, "filetype=DIRECTORY\n");
+
+ /*
+ ret =
+ g_free (type);
+ */
+
+ g_free(name);
+ g_free(type);
+ g_free(URL);
+ g_free(icon);
+
+ g_key_file_free (desktop_file);
+
+ return GNOME_VFS_OK;
+
+}
+
+/**
+* print fileinfo in key-value pair style
+*/
+void xdg_gnome_vfs_printFileInfo(FILE * f, const char * full_uri, GnomeVFSFileInfo * info, int opts)
+{
+
+ GnomeVFSFileInfoFields valid = info->valid_fields;
+ int did_de_dive = 0;
+
+
+ if (opts & XDGVFS_OPT_DIVE_DE_LINKS)
+ {
+
+ if ((info->valid_fields & GNOME_VFS_FILE_INFO_FIELDS_MIME_TYPE) != 0
+ && strcmp (gnome_vfs_file_info_get_mime_type (info), "application/x-desktop") == 0)
+ {
+
+ if (_follow_desktop_link(full_uri, opts) == GNOME_VFS_OK)
+ {
+ // fprintf(stderr, "dive!\n");
+ return;
+ }
+
+ }
+ }
+
+ fprintf(f, "basename=%s\n", info->name);
+
+ if (valid & GNOME_VFS_FILE_INFO_FIELDS_SIZE)
+ {
+ fprintf(f, "size=%u\n", info->size);
+ }
+ if (1)
+ {
+ struct passwd * passwdEntry;
+ struct group * groupEntry;
+
+ passwdEntry = getpwuid ((uid_t)info->uid);
+ if (passwdEntry)
+ {
+ xdg_vfs_ppair_str(f, "user", passwdEntry->pw_name, opts);
+ }
+
+ groupEntry = getgrgid ((gid_t)info->gid);
+ if (groupEntry)
+ {
+ xdg_vfs_ppair_str(f, "group", groupEntry->gr_name, opts);
+ }
+
+ /* fprintf(f, "userid=%d\n", info->uid);
+ fprintf(f, "groupid=%d\n", info->gid); */
+ }
+
+ if (valid & GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS)
+ {
+ fprintf(f, "permissions=%d\n", info->permissions);
+ }
+
+ if (valid & GNOME_VFS_FILE_INFO_FIELDS_MTIME)
+ {
+ fprintf(f, "mtime=%d\n", info->mtime);
+ }
+
+ if (valid & GNOME_VFS_FILE_INFO_FIELDS_ATIME)
+ {
+ fprintf(f, "atime=%d\n", info->atime);
+ }
+
+ if (valid & GNOME_VFS_FILE_INFO_FIELDS_CTIME)
+ {
+ fprintf(f, "ctime=%d\n", info->ctime);
+ }
+
+ if (valid & GNOME_VFS_FILE_INFO_FIELDS_TYPE)
+ {
+ char * tstr="UNKNOWN";
+
+ switch(info->type)
+ {
+ case(GNOME_VFS_FILE_TYPE_UNKNOWN): tstr = "UNKNOWN"; break;
+ case(GNOME_VFS_FILE_TYPE_REGULAR): tstr = "REGULAR"; break;
+ case(GNOME_VFS_FILE_TYPE_DIRECTORY): tstr = "DIRECTORY"; break;
+ case(GNOME_VFS_FILE_TYPE_FIFO): tstr = "FIFO"; break;
+ case(GNOME_VFS_FILE_TYPE_SOCKET): tstr = "SOCKET"; break;
+ case(GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE): tstr = "CHARDEV"; break;
+ case(GNOME_VFS_FILE_TYPE_BLOCK_DEVICE): tstr = "BLOCKDEV"; break;
+ case(GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK): tstr = "SYMLINK"; break;
+ /* default: tstr = "UNKNOWN"; break; */
+ }
+ fprintf(f, "filetype=%s\n", tstr);
+
+ }
+
+ if (valid & GNOME_VFS_FILE_INFO_FIELDS_SYMLINK_NAME)
+ {
+ fprintf(f, "linkdest=%s\n", info->symlink_name);
+ }
+
+ if (valid & GNOME_VFS_FILE_INFO_FIELDS_SIZE)
+ {
+ fprintf(f, "mimetype=%s\n", info->mime_type);
+ }
+
+ GnomeIconLookupResultFlags iconLookupResultFlags;
+ char * iconname = gnome_icon_lookup (gtk_icon_theme_get_default (),
+ NULL,
+ NULL /* const char *file_uri */,
+ NULL,
+ info,
+ info->mime_type,
+ GNOME_ICON_LOOKUP_FLAGS_NONE,
+ &iconLookupResultFlags);
+ if (iconname) fprintf(f, "iconname=%s\n", iconname);
+ g_free(iconname);
+
+ xdg_vfs_ppair_str(stdout, "uri", full_uri, opts);
+
+ if (xdg_vfs_getCustomEndSeparator())
+ fprintf(stdout, "\n%s\n", xdg_vfs_getCustomEndSeparator());
+}
+
+
+/**
+* Command: fileinfo
+*/
+int xdg_vfs_getFileInfo(const char * text_uri, int opts)
+{
+ GnomeVFSResult r;
+ GnomeVFSFileInfo * info = gnome_vfs_file_info_new ();
+ char * full_uri = gnome_vfs_make_uri_from_input(text_uri);
+
+ if (opts & XDGVFS_OPT_TAGGED) puts(XDGVFS_TAG_FILEINFO);
+
+ GnomeVFSFileInfoOptions infoOpts = GNOME_VFS_FILE_INFO_FOLLOW_LINKS | GNOME_VFS_FILE_INFO_GET_MIME_TYPE;
+
+ if (opts & XDGVFS_OPT_SLOW_MIME_TYPE) infoOpts |= GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE;
+
+ r=gnome_vfs_get_file_info(full_uri,
+ info,
+ infoOpts);
+ xdg_vfs_iterate_mainloop();
+
+ if (r!=GNOME_VFS_OK)
+ {
+ g_free(full_uri);
+ gnome_vfs_file_info_unref (info);
+ return print_and_translate_result(r);
+ }
+
+ xdg_gnome_vfs_printFileInfo(stdout, full_uri, info, opts);
+
+
+ gnome_vfs_file_info_unref (info);
+ g_free(full_uri);
+ return 0;
+}
+
+/**
+* Command: setattrs
+*/
+int xdg_vfs_setFileInfo(const char * text_uri, XdgVfsSetFileInfoData * fiData, int opts)
+{
+ GnomeVFSResult r;
+ char * full_uri = gnome_vfs_make_uri_from_input(text_uri);
+ struct passwd * passwdEntry;
+ struct group * groupEntry;
+ GnomeVFSFileInfo * info = gnome_vfs_file_info_new ();
+ info->valid_fields = GNOME_VFS_FILE_INFO_FIELDS_NONE;
+ GnomeVFSSetFileInfoMask setFileInfoMask = GNOME_VFS_SET_FILE_INFO_NONE;
+
+ if (opts & XDGVFS_OPT_TAGGED) puts(XDGVFS_TAG_SETATTRS);
+
+ if (fiData->user)
+ {
+ passwdEntry = getpwnam(fiData->user);
+ if (passwdEntry)
+ {
+ setFileInfoMask |= GNOME_VFS_SET_FILE_INFO_OWNER;
+
+ info->uid = passwdEntry->pw_uid;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: User '%s' not found in passwd\n", fiData->user);
+ gnome_vfs_file_info_unref (info); g_free(full_uri);
+ return XDGVFS_ERRORCODE_USR_OR_GRP_NOT_FOUND;
+ }
+ }
+
+ if (fiData->group)
+ {
+ groupEntry = getgrnam(fiData->group);
+ if (groupEntry)
+ {
+ setFileInfoMask |= GNOME_VFS_SET_FILE_INFO_OWNER;
+ info->gid = groupEntry->gr_gid;
+ }
+ else
+ {
+ fprintf(stderr, "ERROR: Group '%s' not found in group database\n", fiData->group);
+ gnome_vfs_file_info_unref (info); g_free(full_uri);
+ return XDGVFS_ERRORCODE_USR_OR_GRP_NOT_FOUND;
+ }
+ }
+
+ if (fiData->setPermsFlag)
+ {
+ setFileInfoMask |= GNOME_VFS_SET_FILE_INFO_PERMISSIONS;
+ info->valid_fields |= GNOME_VFS_FILE_INFO_FIELDS_PERMISSIONS;
+ info->permissions = fiData->perms;
+ }
+
+ r = gnome_vfs_set_file_info(full_uri, info, setFileInfoMask);
+
+ xdg_vfs_iterate_mainloop();
+
+ if (r!=GNOME_VFS_OK)
+ {
+ g_free(full_uri);
+ gnome_vfs_file_info_unref (info);
+ return print_and_translate_result(r);
+ }
+
+ xdg_vfs_ppair_str(stdout, "uri", full_uri, opts);
+
+ gnome_vfs_file_info_unref (info);
+ g_free(full_uri);
+ return XDGVFS_ERRORCODE_OK;
+}
+
+/**
+* Command: list directory
+*/
+int xdg_vfs_dir(const char * text_uri, int opts)
+{
+ GnomeVFSResult r;
+ GnomeVFSDirectoryHandle *handle;
+ char * full_uri = gnome_vfs_make_uri_from_input(text_uri);
+ GnomeVFSFileInfo * info = gnome_vfs_file_info_new ();
+
+ if (opts & XDGVFS_OPT_TAGGED) {
+ puts(XDGVFS_TAG_LS);
+ xdg_vfs_ppair_str(stdout, "uri", full_uri, opts);
+ }
+
+ if (strcmp(full_uri, "tvolumes:")==0)
+ {
+ test_volume_list();
+ return XDGVFS_ERRORCODE_OK;
+ }
+
+ if (strcmp(full_uri, "tdrives:")==0)
+ {
+ test_drive_list();
+ return XDGVFS_ERRORCODE_OK;
+ }
+
+ if (strcmp(full_uri, "vfsroot://")==0)
+ {
+ _xdg_vfs_gnome_ls_vfsroot(opts & XDGVFS_OPT_TAGGED);
+ return XDGVFS_ERRORCODE_OK;
+ }
+
+
+ GnomeVFSFileInfoOptions infoOpts = GNOME_VFS_FILE_INFO_FOLLOW_LINKS | GNOME_VFS_FILE_INFO_GET_MIME_TYPE;
+
+ if (opts & XDGVFS_OPT_SLOW_MIME_TYPE) infoOpts |= GNOME_VFS_FILE_INFO_FORCE_SLOW_MIME_TYPE;
+
+ r=gnome_vfs_directory_open (&handle,
+ full_uri,
+ infoOpts);
+
+ xdg_vfs_iterate_mainloop();
+
+ if (r!=GNOME_VFS_OK)
+ {
+ if (r==GNOME_VFS_ERROR_CANCELLED)
+ {
+ fprintf(stderr, "ERROR: Operation canceled\n");
+ return XDGVFS_ERRORCODE_CANCELED;
+ }
+ return print_and_translate_result(r);
+ }
+
+ while(1)
+ {
+ // char *entryUri;
+ r=gnome_vfs_directory_read_next(handle, info);
+ if (r!=GNOME_VFS_OK)
+ {
+ if (r==GNOME_VFS_ERROR_EOF) break; /* ok EOF */
+ return print_and_translate_result(r);
+ }
+ if (opts & XDGVFS_OPT_TAGGED) puts(XDGVFS_TAG_DIRENTRY);
+
+
+ GnomeVFSURI* dirUri = gnome_vfs_uri_new(full_uri);
+ GnomeVFSURI* fileUri = gnome_vfs_uri_append_path(dirUri,
+ info->name);
+
+ char * nuri = gnome_vfs_uri_to_string(fileUri,
+ GNOME_VFS_URI_HIDE_NONE);
+/*
+ if (!g_str_has_suffix (full_uri, "/"))
+ entryUri = g_strconcat(full_uri, "/", info->name, NULL);
+ else
+ entryUri = g_strconcat(full_uri, info->name, NULL);
+
+ char * entryUriEscaped = gnome_vfs_make_uri_from_input(entryUri);
+*/
+
+ xdg_gnome_vfs_printFileInfo(stdout, nuri, info, opts);
+
+
+ // xdg_vfs_ppair_str(stdout, "uri", entryUriEscaped, opts);
+ //g_free(entryUriEscaped);
+ //g_free(entryUri);
+ gnome_vfs_uri_unref (dirUri);
+ gnome_vfs_uri_unref (fileUri);
+ g_free(nuri);
+
+ gnome_vfs_file_info_clear (info);
+ if (!(opts & XDGVFS_OPT_TAGGED)) putchar(10);
+ }
+
+ gnome_vfs_directory_close(handle);
+ gnome_vfs_file_info_unref (info);
+ return XDGVFS_ERRORCODE_OK;
+
+}
+
+/**
+* Command: read file
+*/
+int xdg_vfs_get(const char * text_uri, int opts)
+{
+ char buffer[DATA_BUF_SIZE];
+ GnomeVFSFileSize bytes_read;
+ int i, rr;
+ int escChar = xdg_vfs_getDataEscChar();
+ char * full_uri = gnome_vfs_make_uri_from_input(text_uri);
+ GnomeVFSHandle *handle;
+ GnomeVFSResult r;
+
+ if (opts & XDGVFS_OPT_GET_FILEINFO)
+ {
+ if (!(opts & XDGVFS_OPT_TAGGED))
+ {
+ fprintf(stderr, "ERROR: qry fileinfo in 'get' command requires tagged mode!\n");
+ return XDGVFS_ERRORCODE_BAD_PARAMETER;
+ }
+ rr=xdg_vfs_getFileInfo(text_uri, opts);
+ if (rr != 0) return rr;
+ }
+
+ if (opts & XDGVFS_OPT_TAGGED)
+ {
+ puts(XDGVFS_TAG_GET);
+ xdg_vfs_ppair_str(stdout, "uri", full_uri, opts);
+ }
+ r=gnome_vfs_open(&handle, full_uri, GNOME_VFS_OPEN_READ);
+ if (r!=GNOME_VFS_OK)
+ {
+ if (r==GNOME_VFS_ERROR_CANCELLED)
+ {
+ fprintf(stderr, "ERROR: Operation canceled\n");
+ return XDGVFS_ERRORCODE_CANCELED;
+ }
+ return print_and_translate_result(r);
+ }
+
+ xdg_vfs_iterate_mainloop();
+
+ if (opts & XDGVFS_OPT_TAGGED)
+ {
+ puts(opts & XDGVFS_OPT_DATAESCAPED ? XDGVFS_TAG_ESCAPEDDATA_OUT : XDGVFS_TAG_DATA_OUT);
+ }
+
+ while (1)
+ {
+ r=gnome_vfs_read(handle, buffer, DATA_BUF_SIZE, &bytes_read);
+ if (r!=GNOME_VFS_OK)
+ {
+ if (r==GNOME_VFS_ERROR_EOF) break; /* ok EOF */
+ return print_and_translate_result(r);
+ }
+ for(i=0;i<bytes_read;i++)
+ {
+ int c = (int)buffer[i];
+ /* escape char */
+ if (c == escChar && opts & XDGVFS_OPT_DATAESCAPED) putchar(escChar);
+ putchar (c);
+ }
+
+ }
+ if (opts & XDGVFS_OPT_DATAESCAPED)
+ {
+ putchar(escChar); // Escape char
+ putchar(10);
+ //fprintf(stdout, "\n[/Data]\n");
+ } else if (opts & XDGVFS_OPT_TAGGED) putchar(10);
+
+ if (xdg_vfs_getCustomEndSeparator())
+ fprintf(stdout, "%s\n", xdg_vfs_getCustomEndSeparator());
+ gnome_vfs_close(handle);
+ return XDGVFS_ERRORCODE_OK;
+}
+
+/**
+* Command: mkdir
+*/
+int xdg_vfs_mkdir(const char * text_uri, unsigned int perms, int opts)
+{
+ GnomeVFSResult r;
+ char * full_uri = gnome_vfs_make_uri_from_input(text_uri);
+ if (opts & XDGVFS_OPT_TAGGED)
+ {
+ puts(XDGVFS_TAG_MKDIR);
+ xdg_vfs_ppair_str(stdout, "uri", full_uri, opts);
+ }
+ r = gnome_vfs_make_directory(full_uri, perms);
+ if (r!=GNOME_VFS_OK)
+ {
+ return print_and_translate_result(r);
+ }
+ return XDGVFS_ERRORCODE_OK;
+}
+
+/**
+* Command: rmdir
+*/
+int xdg_vfs_rmdir(const char * text_uri, int opts)
+{
+ GnomeVFSResult r;
+ char * full_uri = gnome_vfs_make_uri_from_input(text_uri);
+ if (opts & XDGVFS_OPT_TAGGED)
+ {
+ puts(XDGVFS_TAG_RMDIR);
+ xdg_vfs_ppair_str(stdout, "uri", full_uri, opts);
+ }
+ r= gnome_vfs_remove_directory(full_uri);
+ if (r!=GNOME_VFS_OK)
+ {
+ return print_and_translate_result(r);
+ }
+ return XDGVFS_ERRORCODE_OK;
+}
+
+/**
+* Command: rm
+*/
+int xdg_vfs_rm(const char * text_uri, int opts)
+{
+ GnomeVFSResult r;
+ char * full_uri = gnome_vfs_make_uri_from_input(text_uri);
+ if (opts & XDGVFS_OPT_TAGGED)
+ {
+ puts(XDGVFS_TAG_RM);
+ xdg_vfs_ppair_str(stdout, "uri", full_uri, opts);
+ }
+ r= gnome_vfs_unlink (full_uri);
+ if (r!=GNOME_VFS_OK)
+ {
+ return print_and_translate_result(r);
+ }
+ return XDGVFS_ERRORCODE_OK;
+}
+
+/**
+* Copy/Move progress callback
+*/
+time_t progress_lasttime=0;
+
+gint gnomeVFSXferProgressCallback (GnomeVFSXferProgressInfo *info,
+ gpointer data)
+{
+ int opts = 0;
+
+ if (data) opts = *((int *)data);
+ if (opts & XDGVFS_OPT_PROGRESS && info)
+ {
+ time_t now = time(NULL);
+ if ((progress_lasttime < now))
+ {
+ progress_lasttime=now;
+ puts(XDGVFS_TAG_PROGRESS);
+ printf("total_bytes=%d\n", info->file_size);
+ printf("bytes_copied=%d\n", info->bytes_copied);
+ }
+ }
+ info->vfs_status = GNOME_VFS_OK;
+ if (xdg_vfs_chk_canceled(opts))
+ {
+ return FALSE;
+ }
+ return TRUE;
+}
+
+/**
+* Command: cp/mv
+*/
+int xdg_vfs_cp(const char * text_uri_src, const char * text_uri_target, unsigned int perms, int move_flag, int opts)
+{
+ GnomeVFSResult r;
+ GnomeVFSXferOptions xfer_opts = (move_flag ? GNOME_VFS_XFER_REMOVESOURCE : GNOME_VFS_XFER_DEFAULT);
+ GnomeVFSXferErrorMode error_mode = GNOME_VFS_XFER_ERROR_MODE_ABORT;
+ GnomeVFSXferOverwriteMode overwrite_mode =
+ (opts & XDGVFS_OPT_OVERWRITE)
+ ? GNOME_VFS_XFER_OVERWRITE_MODE_REPLACE
+ : GNOME_VFS_XFER_OVERWRITE_MODE_ABORT;
+ const char * full_uri_src = gnome_vfs_make_uri_from_input(text_uri_src);
+ const char * full_uri_target = gnome_vfs_make_uri_from_input(text_uri_target);
+ GnomeVFSURI* gfull_uri_src = gnome_vfs_uri_new(full_uri_src);
+ GnomeVFSURI* gfull_uri_target = gnome_vfs_uri_new(full_uri_target);
+
+ if (opts & XDGVFS_OPT_TAGGED)
+ {
+ puts(move_flag ? XDGVFS_TAG_MV : XDGVFS_TAG_CP);
+ xdg_vfs_ppair_str(stdout, "uri_src", full_uri_src, opts);
+ xdg_vfs_ppair_str(stdout, "uri_target", full_uri_target, opts);
+ }
+
+ r = gnome_vfs_xfer_uri (gfull_uri_src,
+ gfull_uri_target,
+ xfer_opts,
+ error_mode,
+ overwrite_mode,
+ gnomeVFSXferProgressCallback,
+ &opts);
+ gnome_vfs_uri_unref (gfull_uri_src);
+ gnome_vfs_uri_unref (gfull_uri_target);
+
+ if (r!=GNOME_VFS_OK)
+ {
+ return print_and_translate_result(r);
+ }
+ return XDGVFS_ERRORCODE_OK;
+}
+
+/**
+* Command: write file
+*/
+int xdg_vfs_put(const char * text_uri, int perms, int opts)
+{
+ char buffer[DATA_BUF_SIZE];
+ GnomeVFSFileSize bytes_written;
+ int i, rr, c;
+ int escChar = xdg_vfs_getDataEscChar();
+ char * full_uri = gnome_vfs_make_uri_from_input(text_uri);
+ GnomeVFSHandle *handle;
+ GnomeVFSResult r;
+
+ if (opts & XDGVFS_OPT_TAGGED)
+ {
+ puts(XDGVFS_TAG_PUT);
+ xdg_vfs_ppair_str(stdout, "uri", full_uri, opts);
+ // puts(opts & XDGVFS_OPT_DATAESCAPED ? XDGVFS_TAG_ESCAPEDDATA_IN : XDGVFS_TAG_DATA_IN);
+ }
+
+ r=gnome_vfs_create(&handle, full_uri,
+ GNOME_VFS_OPEN_WRITE,
+ !(opts & XDGVFS_OPT_OVERWRITE),
+ perms);
+
+ xdg_vfs_iterate_mainloop();
+
+ //r=gnome_vfs_open(&handle, text_uri, GNOME_VFS_OPEN_WRITE);
+ if (r!=GNOME_VFS_OK)
+ {
+ g_free(full_uri);
+ if (r==GNOME_VFS_ERROR_CANCELLED)
+ {
+ fprintf(stderr, "ERROR: Operation canceled\n");
+ return XDGVFS_ERRORCODE_CANCELED;
+ }
+ return print_and_translate_result(r);
+ }
+
+ if (opts & XDGVFS_OPT_TAGGED) // wait for data!
+ {
+ puts(opts & XDGVFS_OPT_DATAESCAPED ? XDGVFS_TAG_ESCAPEDDATA_IN : XDGVFS_TAG_DATA_IN);
+ fflush(stdout);
+ }
+
+
+ while (1)
+ {
+ int eofflag=0;
+ int len = 0;
+ for (i=0;i<DATA_BUF_SIZE;i++)
+ { /* read chunk */
+ c = getc(stdin);
+ if (c==EOF)
+ {
+ eofflag =1;
+ break;
+ }
+ if (c == escChar && opts & XDGVFS_OPT_DATAESCAPED)
+ {
+ int c2 = getc(stdin);
+ if (c2==EOF)
+ {
+ eofflag =1;
+ break;
+ }
+
+ if (c2!=escChar)
+ {
+ if (c2!='\n')
+ {
+ g_free(full_uri);
+ fprintf(stderr, "ERROR: Data escaping error\n");
+ return XDGVFS_ERRORCODE_DATA_ERROR;
+ }
+ eofflag = 1;
+ break;
+ }
+ }
+
+
+ buffer[i] = (unsigned char)c;
+ len++;
+ }
+
+ /* check for errors */
+ if (ferror (stdin))
+ {
+ //fprintf(stderr, "ERROR: Stdin error\n");
+ g_free(full_uri);
+ perror("ERROR: Stdin error\n");
+ return XDGVFS_ERRORCODE_DATA_ERROR;
+ }
+
+ char * p = buffer;
+ while (len>0)
+ { /* write chunk */
+ r=gnome_vfs_write(handle, p, len, &bytes_written);
+ if (r!=GNOME_VFS_OK)
+ {
+ // error delete file
+ g_free(full_uri);
+ return print_and_translate_result(r);
+ }
+ p += bytes_written;
+ len -= bytes_written;
+ }
+ if(eofflag) break;
+ }
+ gnome_vfs_close(handle);
+ g_free(full_uri);
+ return XDGVFS_ERRORCODE_OK;
+}
+
+/**
+* Command: open file dialog
+*/
+int xdg_vfs_openfiledlg(const char * default_dir, const char * default_filename, const char * title, int opts)
+{
+ GtkWidget *dialog;
+
+ gtk_init (0, NULL);
+
+
+ dialog = gtk_file_chooser_dialog_new (title ? title : XDGVFS_TEXT_OPENFILEDLG_TITLE,
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_OPEN,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ /*
+
+ dialog = gtk_file_chooser_dialog_new ("Save File",
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ */
+
+ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER (dialog), FALSE);
+
+ if (default_dir) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_dir);
+ //if (default_filename) gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_filename);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ char *filename, *uri;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+ uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
+
+ if (!(opts & XDGVFS_OPT_INSTANT_GET) || opts & XDGVFS_OPT_TAGGED)
+ {
+ if (opts & XDGVFS_OPT_TAGGED) puts(XDGVFS_TAG_OPENFILEDLG);
+ if (filename) fprintf(stdout, "selected_localpath=%s\n", filename);
+ if (uri) fprintf(stdout, "selected_uri=%s\n", uri);
+
+ if (xdg_vfs_getCustomEndSeparator())
+ fprintf(stdout, "\n%s\n", xdg_vfs_getCustomEndSeparator());
+ }
+
+ gtk_widget_destroy (dialog);
+ if (opts & XDGVFS_OPT_INSTANT_GET) return xdg_vfs_get(uri, opts);
+ return XDGVFS_ERRORCODE_OK;
+
+ }
+ else
+ {
+ gtk_widget_destroy (dialog);
+ fprintf(stderr, "ERROR: Dialog canceled\n");
+ return XDGVFS_ERRORCODE_CANCELED;
+ }
+}
+
+/**
+* Command: save file dlg
+*/
+int xdg_vfs_savefiledlg(const char * default_dir, const char * default_filename,
+ const char * title, unsigned int perms, int opts)
+{
+ GtkWidget *dialog;
+
+ gtk_init (0, NULL);
+
+ dialog = gtk_file_chooser_dialog_new (title ? title : XDGVFS_TEXT_SAVEFILEDLG_TITLE,
+ NULL,
+ GTK_FILE_CHOOSER_ACTION_SAVE,
+ GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+ GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+ NULL);
+
+ gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER (dialog), FALSE);
+ gtk_file_chooser_set_do_overwrite_confirmation (GTK_FILE_CHOOSER (dialog), TRUE);
+
+ if (default_dir) gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog), default_dir);
+ if (default_filename) gtk_file_chooser_set_current_name (GTK_FILE_CHOOSER (dialog), default_filename);
+
+ if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
+ {
+ char *filename, *uri;
+
+ filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
+
+ uri = gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (dialog));
+
+ if (!(opts & XDGVFS_OPT_INSTANT_PUT) || opts & XDGVFS_OPT_TAGGED)
+ {
+ if (opts & XDGVFS_OPT_TAGGED) puts(XDGVFS_TAG_SAVEFILEDLG);
+ if (filename) fprintf(stdout, "selected_localpath=%s\n", filename);
+ if (uri) fprintf(stdout, "selected_uri=%s\n", uri);
+
+ if (xdg_vfs_getCustomEndSeparator())
+ fprintf(stdout, "\n%s\n", xdg_vfs_getCustomEndSeparator());
+ }
+
+ gtk_widget_destroy (dialog);
+ if (opts & XDGVFS_OPT_INSTANT_PUT) return xdg_vfs_put(uri, perms, opts | XDGVFS_OPT_OVERWRITE);
+ return XDGVFS_ERRORCODE_OK;
+ }
+ else
+ {
+ gtk_widget_destroy (dialog);
+ fprintf(stderr, "ERROR: Dialog canceled\n");
+ return XDGVFS_ERRORCODE_CANCELED;
+ }
+}
+
+int xdg_vfs_backend(int opts)
+{
+ if (opts & XDGVFS_OPT_TAGGED)
+ {
+ puts(XDGVFS_TAG_BACKEND);
+ }
+ xdg_vfs_ppair_str(stdout, "backend_id", "gnome", opts);
+ xdg_vfs_ppair_str(stdout, "system_uri", "vfsroot://", opts);
+ xdg_vfs_ppair_str(stdout, "file_icon_theme", "gnome", opts);
+ return XDGVFS_ERRORCODE_OK;
+}
+
+
+int xdg_vfs_mount(const char * mountpoint_id, int opts)
+{
+ return _xdg_vfs_gnome_mount(mountpoint_id, opts & XDGVFS_OPT_TAGGED);
+
+
+}
+
+/**
+* main()
+*/
+int main(int argc, char ** argv)
+{
+ return xdg_vfs_main(argc, argv);
+}
diff --git a/xdg-vfs-gnome/src/xdg_vfs_gnome.h b/xdg-vfs-gnome/src/xdg_vfs_gnome.h
new file mode 100644
index 0000000..d8d1f95
--- /dev/null
+++ b/xdg-vfs-gnome/src/xdg_vfs_gnome.h
@@ -0,0 +1,39 @@
+/*
+# xdg_vfs_gnome.h
+#
+# Copyright 2006, Norbert Frese
+#
+# LICENSE:
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#---------------------------------------------*/
+
+#ifndef XDG_VFS_GNOME_H
+#define XDG_VFS_GNOME_H
+
+/* private decls */
+
+int _xdg_vfs_gnome_mount(char * mountpoint_id, int tagged);
+
+int _xdg_vfs_gnome_ls_vfsroot(int tagged);
+
+int print_and_translate_result(GnomeVFSResult result);
+
+#endif
diff --git a/xdg-vfs-gnome/src/xdg_vfs_gnome_monitor.c b/xdg-vfs-gnome/src/xdg_vfs_gnome_monitor.c
new file mode 100644
index 0000000..0729a94
--- /dev/null
+++ b/xdg-vfs-gnome/src/xdg_vfs_gnome_monitor.c
@@ -0,0 +1,238 @@
+/*
+# xdg_vfs_gnome_monitor.c
+#
+# Copyright 2006, Norbert Frese
+#
+# LICENSE:
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#---------------------------------------------*/
+
+#include <string.h>
+
+#include <gtk/gtk.h>
+#include <libgnomevfs/gnome-vfs.h>
+#include <libgnomeui/libgnomeui.h>
+#include <time.h>
+
+#include "xdg_vfs_common.h"
+#include "xdg_vfs.h"
+#include "xdg_vfs_gnome.h"
+
+typedef struct
+{
+ char * monitor_uri;
+ GnomeVFSMonitorHandle * handle;
+ int has_events;
+} XdgVfsGnomeMonitor;
+
+int global_event_count=0;
+
+GList * monitor_list = NULL;
+
+void myGnomeVFSMonitorCallback(GnomeVFSMonitorHandle *handle,
+ const gchar *monitor_uri,
+ const gchar *info_uri,
+ GnomeVFSMonitorEventType event_type,
+ gpointer user_data)
+{
+ GList *current_monitor;
+ int found = 0;
+ /*fprintf(stderr, "monitor event monitor_uri=%s info_uri=%s event_type=%d\n",
+ monitor_uri,
+ info_uri,
+ event_type);*/
+
+ for (current_monitor = monitor_list; current_monitor != NULL; current_monitor = current_monitor->next)
+ {
+
+ XdgVfsGnomeMonitor *monitor = (XdgVfsGnomeMonitor*)current_monitor->data;
+ if (monitor->handle == handle)
+ {
+ monitor->has_events++;
+ global_event_count++;
+ found = 1;
+ }
+ }
+ if (found==0) fprintf(stderr,
+ "Warning: got event for unregistered handle monitor_uri=%s\n", monitor_uri);
+}
+
+XdgVfsGnomeMonitor * new_xdg_vfs_gnome_monitor()
+{
+ XdgVfsGnomeMonitor * monitor = calloc(1,sizeof(XdgVfsGnomeMonitor));
+ return monitor;
+}
+
+
+int xdg_vfs_monitor(char * uri, int is_directory, int opts)
+{
+ GnomeVFSResult r;
+ GnomeVFSMonitorHandle *handle;
+ char * full_uri = gnome_vfs_make_uri_from_input(uri);
+
+ GList *current_monitor;
+ for (current_monitor = monitor_list; current_monitor != NULL; current_monitor = current_monitor->next)
+ {
+ XdgVfsGnomeMonitor *monitor = (XdgVfsGnomeMonitor*)current_monitor->data;
+ if( strcmp(uri, monitor->monitor_uri) ==0)
+ return XDGVFS_ERRORCODE_ALREADY_EXISTS; // monitor exists
+ }
+
+ /* dirty hack: watch computer:// for drive changes */
+ char * watch_uri = strcmp(uri, "vfsroot://")==0 ? "computer://" : full_uri;
+
+ r = gnome_vfs_monitor_add(&handle,
+ watch_uri,
+ is_directory ? GNOME_VFS_MONITOR_DIRECTORY : GNOME_VFS_MONITOR_FILE,
+ myGnomeVFSMonitorCallback,
+ NULL /* user_data */);
+
+ if (r==GNOME_VFS_OK)
+ {
+ XdgVfsGnomeMonitor * monitor = new_xdg_vfs_gnome_monitor();
+ monitor->handle = handle;
+ monitor->monitor_uri = strdup(full_uri);
+ monitor_list = g_list_append(monitor_list, monitor);
+ }
+
+ g_free(full_uri);
+ if (r!=GNOME_VFS_OK) return print_and_translate_result(r);
+ return XDGVFS_ERRORCODE_OK;
+}
+
+
+int xdg_vfs_monitor_cancel(char * uri, int opts)
+{
+ char * full_uri = gnome_vfs_make_uri_from_input(uri);
+ GList *current_monitor;
+ int found = 0;
+ for (current_monitor = monitor_list; current_monitor != NULL; current_monitor = current_monitor->next)
+ {
+ XdgVfsGnomeMonitor *monitor = (XdgVfsGnomeMonitor*)current_monitor->data;
+ if( strcmp(full_uri, monitor->monitor_uri) == 0)
+ {
+ GnomeVFSResult r = gnome_vfs_monitor_cancel (monitor->handle);
+ if (r!=GNOME_VFS_OK)
+ print_and_translate_result(r);
+ g_free(monitor->monitor_uri);
+ monitor_list = g_list_remove(monitor_list, monitor);
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found)
+ {
+ fprintf(stderr, "monitor with uri=%s not found!\n", full_uri);
+ g_free(full_uri);
+ return XDGVFS_ERRORCODE_NOT_FOUND;
+ }
+ g_free(full_uri);
+ return XDGVFS_ERRORCODE_OK;
+}
+
+int xdg_vfs_monitor_list_events(int opts)
+{
+ GList *current_monitor;
+ int save_count = global_event_count;
+ int found = 0;
+ for (current_monitor = monitor_list; current_monitor != NULL; current_monitor = current_monitor->next)
+ {
+ XdgVfsGnomeMonitor *monitor = (XdgVfsGnomeMonitor*)current_monitor->data;
+ if (monitor->has_events)
+ {
+ fprintf(stdout, "%s %s\n", XDGVFS_TAG_MONITOREVENT, monitor->monitor_uri);
+ monitor->has_events = 0;
+ }
+ }
+ fflush(stdout);
+ global_event_count = 0;
+ return save_count;
+}
+
+/* ======================== loop and wait for fd =============== */
+
+typedef struct {
+ GSource gs;
+ GPollFD * gpoll;
+ gboolean done;
+} WaitGSource;
+
+
+gboolean wait_gs_prepare(GSource *source, gint *timeout_)
+{
+ WaitGSource * wsource = (WaitGSource*)source;
+ //fprintf(stderr, "hi1\n");
+ wsource->gpoll->events = G_IO_IN | G_IO_HUP | G_IO_ERR;
+ *timeout_ = -1;
+ return FALSE;
+}
+
+gboolean wait_gs_check(GSource *source)
+{
+ WaitGSource * wsource = (WaitGSource*)source;
+ //fprintf(stderr, "hi2 %d\n", wsource->gpoll->fd);
+ if (wsource->gpoll->revents & (G_IO_IN | G_IO_HUP | G_IO_ERR))
+ {
+ //fprintf(stderr, "hi3\n");
+ return TRUE;
+ }
+ return FALSE;
+}
+
+gboolean wait_gs_dispatch(GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ WaitGSource * wsource = (WaitGSource*)source;
+ wsource->done = TRUE;
+ return TRUE;
+}
+
+GSourceFuncs wait_gs_funcs = {
+ .prepare = wait_gs_prepare,
+ .check = wait_gs_check,
+ .dispatch = wait_gs_dispatch
+};
+
+int xdg_vfs_iterate_mainloop_until_incoming_data(int fd)
+{
+ GPollFD gpoll={0};
+ gpoll.fd = fd;
+
+ GSource* source = g_source_new(&wait_gs_funcs, sizeof(WaitGSource));
+ WaitGSource * wsource = (WaitGSource*)source;
+ wsource->gpoll = &gpoll;
+ wsource->done = FALSE;
+ g_source_add_poll(source, &gpoll);
+ g_source_set_can_recurse(source,TRUE);
+
+ g_source_attach(source,NULL);
+
+ //while (!(wsource->done)){
+ //fprintf(stderr, "loop\n");
+ g_main_context_iteration(NULL,TRUE);
+ //}
+ int done = wsource->done;
+ g_source_destroy (source);
+ return done;
+}
+
diff --git a/xdg-vfs-gnome/src/xdg_vfs_gnome_volumes.c b/xdg-vfs-gnome/src/xdg_vfs_gnome_volumes.c
new file mode 100644
index 0000000..fc2fc93
--- /dev/null
+++ b/xdg-vfs-gnome/src/xdg_vfs_gnome_volumes.c
@@ -0,0 +1,521 @@
+/*
+# xdg_vfs_gnome_volumes.c
+#
+# Copyright 2006, Norbert Frese
+#
+# LICENSE:
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included
+# in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+#---------------------------------------------*/
+
+#include <glib.h>
+#include <libgnomevfs/gnome-vfs.h>
+
+#include "xdg_vfs_common.h"
+#include "xdg_vfs.h"
+
+#define DEBUG_VOLUMES 1
+
+/* =============== print entries =============== */
+
+
+void _print_filesystem()
+{
+ fprintf(stdout,
+ "basename=Filesystem\n"
+ "uri=file:///\n"
+ "filetype=DIRECTORY\n"
+ "iconname=gnome-dev-harddisk\n"
+ );
+}
+
+void _print_network()
+{
+ fprintf(stdout,
+ "basename=Network\n"
+ "uri=network://\n"
+ "filetype=DIRECTORY\n"
+ "iconname=gnome-fs-network\n"
+ );
+}
+
+void _print_home()
+{
+ char * home_uri = gnome_vfs_get_uri_from_local_path (g_get_home_dir ());
+ fprintf(stdout,
+ "basename=Home\n"
+ "uri=%s\n"
+ "filetype=DIRECTORY\n"
+ "iconname=gnome-fs-home\n"
+ , home_uri
+ );
+}
+
+
+int _print_volume(GnomeVFSVolume *volume)
+{
+ char* activation_uri = gnome_vfs_volume_get_activation_uri
+ (volume);
+ char* display_name = gnome_vfs_volume_get_display_name
+ (volume);
+ GnomeVFSDeviceType device_type = gnome_vfs_volume_get_device_type
+ (volume);
+
+ char* filesystem_type = gnome_vfs_volume_get_filesystem_type
+ (volume);
+ GnomeVFSVolumeType volume_type = gnome_vfs_volume_get_volume_type
+ (volume);
+
+ char* icon = gnome_vfs_volume_get_icon(volume);
+
+ char* device_path = gnome_vfs_volume_get_device_path
+ (volume);
+
+ gboolean is_mounted = gnome_vfs_volume_is_mounted(volume);
+
+ gboolean user_visible = gnome_vfs_volume_is_user_visible
+ (volume);
+
+ gboolean read_only = gnome_vfs_volume_is_read_only (volume);
+
+ if (DEBUG_VOLUMES)
+ {
+ fprintf(stdout, "# (VOLUME)\n");
+ fprintf(stdout, "# activation_uri=%s\n", activation_uri);
+ fprintf(stdout, "# display_name=%s\n", display_name);
+ fprintf(stdout, "# icon=%s\n", icon);
+ fprintf(stdout, "# volume_type=%d\n", volume_type);
+ fprintf(stdout, "# device_type=%d\n", device_type);
+ fprintf(stdout, "# filesystem_type=%s\n", filesystem_type);
+ fprintf(stdout, "# device_path=%s\n", device_path);
+ fprintf(stdout, "# is_mounted=%d\n", is_mounted);
+ fprintf(stdout, "# user_visible=%d\n", user_visible);
+ fprintf(stdout, "# read_only=%d\n", read_only);
+ }
+
+ if (is_mounted)
+ {
+ fprintf(stdout, "uri=%s\n", activation_uri);
+ fprintf(stdout, "is_mounted=1\n");
+ /* fprintf(stdout, "filetype=DIRECTORY\n"); */
+ }
+ else
+ fprintf(stdout, "is_mounted=0\n");
+ {
+ GnomeVFSDrive * drive = gnome_vfs_volume_get_drive(volume);
+ if (drive)
+ fprintf(stdout, "mountpoint_id=%d\n", gnome_vfs_drive_get_id (drive));
+ gnome_vfs_drive_unref(drive);
+
+ fprintf(stdout, "filetype=VFSMOUNTPOINT\n");
+ }
+ fprintf(stdout, "basename=%s\n", display_name);
+ fprintf(stdout, "iconname=%s\n", icon);
+
+ fprintf(stdout, "\n");
+
+ g_free(activation_uri);
+ g_free(display_name);
+ g_free(filesystem_type);
+ g_free(icon);
+ g_free(device_path);
+
+}
+
+int _print_drive(GnomeVFSDrive *drive)
+{
+
+ char * icon= gnome_vfs_drive_get_icon(drive);
+ int drive_id=gnome_vfs_drive_get_id (drive);
+ gboolean is_mounted= gnome_vfs_drive_is_mounted(drive);
+ gboolean is_user_visible=gnome_vfs_drive_is_user_visible (drive);
+ char * device_path=gnome_vfs_drive_get_device_path (drive);
+ char * activation_uri=gnome_vfs_drive_get_activation_uri(drive);
+ char * display_name=gnome_vfs_drive_get_display_name(drive);
+
+ if (DEBUG_VOLUMES)
+ {
+ fprintf(stdout, "# (DRIVE)\n");
+ fprintf(stdout, "# drive_icon=%s\n", icon);
+ fprintf(stdout, "# drive_id=%d\n", drive_id);
+ fprintf(stdout, "# is_mounted=%d\n", is_mounted);
+ fprintf(stdout, "# is_user_visible=%d\n", is_user_visible);
+ fprintf(stdout, "# device_path=%s\n", device_path);
+ fprintf(stdout, "# activation_uri=%s\n", activation_uri);
+ fprintf(stdout, "# display_name=%s\n", display_name);
+ }
+ fprintf(stdout, "iconname=%s\n", icon);
+ fprintf(stdout, "basename=%s\n", display_name);
+ if (is_mounted)
+ fprintf(stdout, "uri=%s\n", activation_uri);
+ fprintf(stdout, "mountpoint_id=%d\n", drive_id);
+ fprintf(stdout, "is_mounted=%d\n", is_mounted);
+
+ fprintf(stdout, "filetype=VFSMOUNTPOINT\n");
+
+ fprintf(stdout, "\n");
+
+ g_free(icon);
+ g_free(device_path);
+ g_free(activation_uri);
+ g_free(display_name);
+
+}
+
+
+/* =================== implementation ================ */
+
+
+GList * _xdg_vfs_gnome_vfsroot_list() {
+
+ GList* entries=NULL;
+
+ GnomeVFSVolumeMonitor * volume_monitor = gnome_vfs_get_volume_monitor();
+
+ GList* drive_list = gnome_vfs_volume_monitor_get_connected_drives
+ (volume_monitor);
+
+
+
+ GList *current_drive;
+
+ for (current_drive = drive_list; current_drive != NULL; current_drive = current_drive->next)
+ {
+
+ GnomeVFSDrive *drive = GNOME_VFS_DRIVE(current_drive->data);
+
+ //_print_drive(drive);
+ //printf("drive\n");
+
+ char* drive_activation_uri = gnome_vfs_drive_get_activation_uri(drive);
+
+ /* don't list root filesystem, because it's included by hand */
+ if (drive_activation_uri && strcmp(drive_activation_uri, "file:///")==0)
+ {
+ g_free(drive_activation_uri);
+ gnome_vfs_drive_unref(drive);
+ continue;
+ }
+
+
+
+ GList* vol_list = gnome_vfs_drive_get_mounted_volumes(drive);
+
+ GList *current_vol;
+ int visible_volumes_count = 0; // count the visible volumes on this drive
+
+ for (current_vol = vol_list; current_vol != NULL; current_vol = current_vol->next)
+ {
+ GnomeVFSVolume *volume;
+ volume = GNOME_VFS_VOLUME (current_vol->data);
+
+ char * device_path = gnome_vfs_volume_get_device_path(volume);
+ char* activation_uri = gnome_vfs_volume_get_activation_uri(volume);
+
+ /*
+ if (device_path &&
+ (strcmp(device_path, "/dev/root")==0
+ || strcmp(device_path, "rootfs")==0
+ ))*/
+ /* don't list root filesystem, because it's included by hand */
+ if (activation_uri && strcmp(activation_uri, "file:///")==0)
+ {
+ g_free(device_path);
+ g_free(activation_uri);
+ gnome_vfs_volume_unref(volume);
+ continue;
+ }
+ g_free(device_path);
+ g_free(activation_uri);
+
+ if (TRUE || gnome_vfs_volume_is_user_visible(volume))
+ {
+ // printf("volume\n");
+ entries = g_list_append(entries, volume);
+ visible_volumes_count++;/* fprintf(stdout, "\n"); */
+ }
+ else
+ {
+ gnome_vfs_volume_unref (volume);
+ }
+
+ }
+
+ /* if there is no volumes, append the drive object */
+ if (visible_volumes_count<1 /* && gnome_vfs_drive_is_user_visible (drive)*/)
+ {
+ entries = g_list_append(entries, drive);
+ }
+ else
+ {
+ gnome_vfs_drive_unref(drive);
+
+ }
+ g_list_free(vol_list);
+
+ }
+
+ /* read the remote shares */
+
+ //fprintf(stderr, "\nand now the network shares #####\n");
+
+ {
+ GList *vol_list;
+ GList *current_vol;
+
+ GnomeVFSVolumeMonitor * volume_monitor = gnome_vfs_get_volume_monitor();
+
+ vol_list = gnome_vfs_volume_monitor_get_mounted_volumes(volume_monitor);
+
+ for (current_vol = vol_list; current_vol != NULL; current_vol = current_vol->next)
+ {
+ GnomeVFSVolume *volume = GNOME_VFS_VOLUME (current_vol->data);
+
+ if (gnome_vfs_volume_get_volume_type(volume) == GNOME_VFS_VOLUME_TYPE_CONNECTED_SERVER)
+ {
+ entries = g_list_append(entries, volume);
+ }
+ else
+ {
+ gnome_vfs_volume_unref (volume);
+ }
+ }
+ g_list_free(vol_list);
+ }
+
+ return entries;
+
+}
+
+int _xdg_vfs_gnome_ls_vfsroot(int tagged)
+{
+
+ GList* entries=_xdg_vfs_gnome_vfsroot_list();
+
+ GList* current_entry;
+
+ if (tagged) puts(XDGVFS_TAG_DIRENTRY);
+ _print_home();
+ puts("");
+ if (tagged) puts(XDGVFS_TAG_DIRENTRY);
+ _print_filesystem();
+ puts("");
+ if (tagged) puts(XDGVFS_TAG_DIRENTRY);
+ _print_network();
+ puts("");
+
+ for (current_entry = entries; current_entry!=NULL; current_entry = current_entry->next)
+ {
+
+ if (tagged) puts(XDGVFS_TAG_DIRENTRY);
+ if (GNOME_IS_VFS_VOLUME(current_entry->data))
+ {
+ GnomeVFSVolume *volume = GNOME_VFS_VOLUME (current_entry->data);
+ _print_volume(volume);
+ gnome_vfs_volume_unref (volume);
+ }
+ else if (GNOME_IS_VFS_DRIVE(current_entry->data))
+ {
+ GnomeVFSDrive *drive = GNOME_VFS_DRIVE(current_entry->data);
+ _print_drive(drive);
+ gnome_vfs_drive_unref(drive);
+ }
+ else
+ fprintf(stdout, "# unexpected list item!\n");
+ }
+ g_list_free(entries);
+ return 1;
+}
+
+
+/* ==================== mounting =================== */
+
+int mount_stoploop;
+int mount_tagged;
+
+void volume_monitor_mount_handler(GnomeVFSVolumeMonitor *vfsvolumemonitor,
+ GnomeVFSVolume *arg1, gpointer user_data)
+{
+
+ int drive_id = *((int*)user_data);
+
+ GnomeVFSDrive * drive = gnome_vfs_volume_get_drive(arg1);
+ if (gnome_vfs_drive_get_id(drive) == drive_id)
+ {
+ /* ha! we got the right drive */
+ mount_stoploop|=2;
+
+ GList* vol_list = gnome_vfs_drive_get_mounted_volumes(drive);
+
+ GList *current_vol;
+ int visible_volumes_count = 0; // count the visible volumes on this drive
+
+ if (mount_tagged) puts(XDGVFS_TAG_MOUNT);
+ for (current_vol = vol_list; current_vol != NULL; current_vol = current_vol->next)
+ {
+ GnomeVFSVolume * volume = GNOME_VFS_VOLUME (current_vol->data);
+ if (mount_tagged) puts(XDGVFS_TAG_DIRENTRY);
+ _print_volume(volume);
+ }
+
+
+
+ }
+}
+
+void myGnomeVFSVolumeOpCallback(gboolean succeeded,
+ char *error,
+ char *detailed_error,
+ gpointer data)
+{
+ int * r = (int*)data;
+
+ if (succeeded)
+ {
+ fprintf(stderr, "VolumeOpCallback: mount succeeded\n");
+ mount_stoploop|=1; /* wait for volume monitor callback before stopping loop */
+ *r = XDGVFS_ERRORCODE_OK;
+ }
+ else
+ {
+ fprintf(stderr, "VolumeOpCallback: mount failed: %s %s\n", error, detailed_error);
+ *r = XDGVFS_ERRORCODE_COULD_NOT_MOUNT;
+ mount_stoploop=3; /* stop loop instantly*/
+ }
+
+}
+
+
+int _xdg_vfs_gnome_mount(char * mountpoint_id, int tagged)
+{
+ int mount_drive_id = atoi(mountpoint_id);
+ mount_tagged = tagged;
+
+ GnomeVFSVolumeMonitor * volume_monitor = gnome_vfs_get_volume_monitor();
+
+ GList* drive_list = gnome_vfs_volume_monitor_get_connected_drives
+ (volume_monitor);
+
+ GList *current_drive;
+
+ for (current_drive = drive_list; current_drive != NULL; current_drive = current_drive->next)
+ {
+
+ GnomeVFSDrive *drive = GNOME_VFS_DRIVE(current_drive->data);
+
+
+
+ if (gnome_vfs_drive_get_id (drive) == mount_drive_id)
+ {
+ int r;
+ fprintf(stderr, "mounting drive with drive_id=%d!\n", mount_drive_id);
+
+ gulong handler_id = g_signal_connect(volume_monitor, "volume-mounted",
+ G_CALLBACK(volume_monitor_mount_handler), &mount_drive_id);
+
+ gnome_vfs_drive_mount (drive, myGnomeVFSVolumeOpCallback, &r);
+
+ /* wait for both callbacks to occur */
+ mount_stoploop=0;
+ while (!(mount_stoploop==3))
+ {
+ // fprintf(stderr, "looping\n");
+ g_main_context_iteration(NULL, TRUE);
+ }
+
+ g_signal_handler_disconnect (volume_monitor, handler_id);
+ g_list_free(drive_list);
+ return r;
+ }
+
+ }
+ g_list_free(drive_list);
+ fprintf(stderr, "mount-problem drive with drive_id=%d not found!\n", mount_drive_id);
+ return XDGVFS_ERRORCODE_GENERIC;
+
+}
+
+/* =============== tests =============== */
+
+int test_drive_list() {
+
+ GnomeVFSVolumeMonitor * volume_monitor = gnome_vfs_get_volume_monitor();
+
+ GList* drive_list = gnome_vfs_volume_monitor_get_connected_drives
+ (volume_monitor);
+
+ printf("%p\n", drive_list);
+
+ GList *current_drive;
+
+ for (current_drive = drive_list; current_drive != NULL; current_drive = current_drive->next)
+ {
+
+ GnomeVFSDrive *drive = GNOME_VFS_DRIVE(current_drive->data);
+
+ _print_drive(drive);
+
+ GList* vol_list = gnome_vfs_drive_get_mounted_volumes(drive);
+
+ GList *current_vol;
+
+ for (current_vol = vol_list; current_vol != NULL; current_vol = current_vol->next)
+ {
+ GnomeVFSVolume *volume;
+ volume = GNOME_VFS_VOLUME (current_vol->data);
+
+ _print_volume(volume);
+
+ }
+
+ }
+
+
+}
+
+int test_volume_list() {
+
+ GList *vol_list;
+ GList *current_vol;
+
+ GnomeVFSVolumeMonitor * volume_monitor = gnome_vfs_get_volume_monitor();
+
+ vol_list = gnome_vfs_volume_monitor_get_mounted_volumes(volume_monitor);
+
+ for (current_vol = vol_list; current_vol != NULL; current_vol = current_vol->next)
+ {
+ GnomeVFSVolume *volume;
+ volume = GNOME_VFS_VOLUME (current_vol->data);
+
+ _print_volume(volume);
+ /* g_free(activation_uri);
+ g_free(display_name);
+ g_free(filesystem_type);
+ g_free(device_path);
+ g_free(is_mounted); */
+ }
+
+}
+
+
+
+
+
+