diff -Nru phodav-2.3/avahi-common.c phodav-2.4/avahi-common.c --- phodav-2.3/avahi-common.c 1970-01-01 00:00:00.000000000 +0000 +++ phodav-2.4/avahi-common.c 2020-03-05 11:15:02.000000000 +0000 @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2019 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "config.h" +#include "avahi-common.h" + +#include +#include + +#include +#include +#include +#include + +static GaClient *mdns_client; +static GaEntryGroup *mdns_group; + +static const gchar *s_name; +static guint s_port; +static gboolean s_local; + +static gboolean +ifaddr_is_loopback (struct ifaddrs *ifa) +{ + union { + struct sockaddr_in *in; + struct sockaddr_in6 *in6; + } sa; + + if (!(ifa->ifa_flags & IFF_LOOPBACK)) + return FALSE; + + if (!ifa->ifa_addr) + return FALSE; + + switch (ifa->ifa_addr->sa_family) + { + case AF_INET: + sa.in = (struct sockaddr_in *)(ifa->ifa_addr); + return sa.in->sin_addr.s_addr == g_htonl (0x7f000001); // 127.0.0.1 + case AF_INET6: + sa.in6 = (struct sockaddr_in6 *)(ifa->ifa_addr); + return IN6_IS_ADDR_LOOPBACK (&sa.in6->sin6_addr); + } + return FALSE; +} + +static guint +get_loopback_if_id () +{ + struct ifaddrs *ifaddr, *ifa; + guint id = AVAHI_IF_UNSPEC; + + if (getifaddrs (&ifaddr) == -1) + { + g_warning ("getifaddrs failed, using AVAHI_IF_UNSPEC: %s", g_strerror(errno)); + return id; + } + + for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) + { + if (ifaddr_is_loopback (ifa)) + { + id = if_nametoindex (ifa->ifa_name); + break; + } + } + + freeifaddrs (ifaddr); + return id; +} + +static void +mdns_register_service (void) +{ + GaEntryGroupService *mdns_service; + GError *error = NULL; + + if (!mdns_group) + { + mdns_group = ga_entry_group_new (); + + if (!ga_entry_group_attach (mdns_group, mdns_client, &error)) + { + g_warning ("Could not attach MDNS group to client: %s", error->message); + g_clear_error (&error); + return; + } + } + + mdns_service = + ga_entry_group_add_service_full (mdns_group, + s_local ? get_loopback_if_id () : AVAHI_IF_UNSPEC, + AVAHI_PROTO_UNSPEC, + 0, + s_name, "_webdav._tcp", + NULL, NULL, + s_port, &error, + NULL); + if (!mdns_service) + { + g_warning ("Could not create service: %s", error->message); + g_clear_error (&error); + return; + } + + ga_entry_group_service_freeze (mdns_service); + if (!ga_entry_group_service_set (mdns_service, "u", "", &error) || + !ga_entry_group_service_set (mdns_service, "p", "", &error) || + !ga_entry_group_service_set (mdns_service, "path", "/", &error) || + !ga_entry_group_service_thaw (mdns_service, &error)) + { + g_warning ("Could not update TXT: %s", error->message); + g_clear_error (&error); + } + + if (!ga_entry_group_commit (mdns_group, &error)) + { + g_warning ("Could not announce MDNS service: %s", error->message); + g_clear_error (&error); + } +} + +static void +mdns_unregister_service (void) +{ + GError *error = NULL; + + if (mdns_group) + { + if (!ga_entry_group_reset (mdns_group, &error)) + { + g_warning ("Could not disconnect MDNS service: %s", error->message); + g_clear_error (&error); + } + g_debug ("MDNS client disconected"); + } +} + +static void +mdns_state_changed (GaClient *client, GaClientState state, gpointer user_data) +{ + switch (state) + { + case GA_CLIENT_STATE_FAILURE: + g_warning ("MDNS client state failure"); + break; + + case GA_CLIENT_STATE_S_RUNNING: + g_debug ("MDNS client found server running"); + mdns_register_service (); + break; + + case GA_CLIENT_STATE_S_COLLISION: + case GA_CLIENT_STATE_S_REGISTERING: + g_message ("MDNS collision"); + mdns_unregister_service (); + break; + + default: + // Do nothing + break; + } +} + +gboolean +avahi_client_start (const gchar *name, guint port, gboolean local, GError **error) +{ + g_return_val_if_fail (mdns_client == NULL, FALSE); + + mdns_client = ga_client_new (GA_CLIENT_FLAG_NO_FLAGS); + s_name = name; + s_port = port; + s_local = local; + + g_signal_connect (mdns_client, "state-changed", G_CALLBACK (mdns_state_changed), NULL); + return ga_client_start (mdns_client, error); +} + +void +avahi_client_stop () +{ + mdns_unregister_service (); + g_clear_object (&mdns_group); + g_clear_object (&mdns_client); +} diff -Nru phodav-2.3/avahi-common.h phodav-2.4/avahi-common.h --- phodav-2.3/avahi-common.h 1970-01-01 00:00:00.000000000 +0000 +++ phodav-2.4/avahi-common.h 2020-03-05 11:15:02.000000000 +0000 @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2019 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include + +gboolean avahi_client_start (const gchar *name, guint port, gboolean local, GError **error); +void avahi_client_stop (); diff -Nru phodav-2.3/debian/changelog phodav-2.4/debian/changelog --- phodav-2.3/debian/changelog 2019-09-15 01:01:04.000000000 +0000 +++ phodav-2.4/debian/changelog 2020-03-15 10:38:05.000000000 +0000 @@ -1,3 +1,14 @@ +phodav (2.4-1) unstable; urgency=medium + + * New upstream release + * debian/control.in: Bump Standards-Version to 4.5.0 (no further changes) + * debian/control.in: Set Rules-Requires-Root: no + * debian/control.in: Add libglib2.0-doc and libsoup2.4-doc to the build-deps + * Only require systemd and udev on linux architectures and adjust installed + files on non-linux ones + + -- Laurent Bigonville Sun, 15 Mar 2020 11:38:05 +0100 + phodav (2.3-2) unstable; urgency=medium * Build-Depend on debhelper-compat 12 and drop debian/compat diff -Nru phodav-2.3/debian/control phodav-2.4/debian/control --- phodav-2.3/debian/control 2019-09-15 01:01:04.000000000 +0000 +++ phodav-2.4/debian/control 2020-03-15 10:38:05.000000000 +0000 @@ -15,13 +15,16 @@ libavahi-client-dev, libavahi-gobject-dev, libglib2.0-dev (>= 2.51), + libglib2.0-doc, libsoup2.4-dev (>= 2.48.0), + libsoup2.4-doc, libxml2-dev, meson (>= 0.49), - systemd, - udev, + systemd [linux-any], + udev [linux-any], xmlto -Standards-Version: 4.4.0 +Standards-Version: 4.5.0 +Rules-Requires-Root: no Vcs-Browser: https://salsa.debian.org/gnome-team/phodav Vcs-Git: https://salsa.debian.org/gnome-team/phodav.git Homepage: https://wiki.gnome.org/phodav diff -Nru phodav-2.3/debian/control.in phodav-2.4/debian/control.in --- phodav-2.3/debian/control.in 2019-09-15 01:01:04.000000000 +0000 +++ phodav-2.4/debian/control.in 2020-03-15 10:38:05.000000000 +0000 @@ -11,13 +11,16 @@ libavahi-client-dev, libavahi-gobject-dev, libglib2.0-dev (>= 2.51), + libglib2.0-doc, libsoup2.4-dev (>= 2.48.0), + libsoup2.4-doc, libxml2-dev, meson (>= 0.49), - systemd, - udev, + systemd [linux-any], + udev [linux-any], xmlto -Standards-Version: 4.4.0 +Standards-Version: 4.5.0 +Rules-Requires-Root: no Vcs-Browser: https://salsa.debian.org/gnome-team/phodav Vcs-Git: https://salsa.debian.org/gnome-team/phodav.git Homepage: https://wiki.gnome.org/phodav diff -Nru phodav-2.3/debian/rules phodav-2.4/debian/rules --- phodav-2.3/debian/rules 2019-09-15 01:01:04.000000000 +0000 +++ phodav-2.4/debian/rules 2020-03-15 10:38:05.000000000 +0000 @@ -3,14 +3,28 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all export DEB_LDFLAGS_MAINT_APPEND = -Wl,-O1 -Wl,-z,defs -Wl,--as-needed +ifneq ($(DEB_HOST_ARCH_OS),linux) + DISABLE_SYSTEMD=-Dsystemd=disabled -Dudev=disabled +endif + %: dh $@ override_dh_auto_configure: - dh_auto_configure -- -Dauto_features=enabled + dh_auto_configure -- -Dauto_features=enabled $(DISABLE_SYSTEMD) override_dh_makeshlibs: dh_makeshlibs -- -c4 override_dh_missing: dh_missing --fail-missing + +override_dh_install: + grep -E -v 'lib/systemd|lib/udev' debian/spice-webdavd.install > debian/spice-webdavd.install.kfreebsd + grep -E -v 'lib/systemd|lib/udev' debian/spice-webdavd.install > debian/spice-webdavd.install.hurd + dh_install + +override_dh_clean: + rm -f debian/spice-webdavd.install.kfreebsd + rm -f debian/spice-webdavd.install.hurd + dh_clean diff -Nru phodav-2.3/libphodav/chezdav.c phodav-2.4/libphodav/chezdav.c --- phodav-2.3/libphodav/chezdav.c 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/libphodav/chezdav.c 2020-03-05 11:15:02.000000000 +0000 @@ -27,12 +27,7 @@ #endif #ifdef WITH_AVAHI -#include -#include - -static GaClient *mdns_client; -static GaEntryGroup *mdns_group; -static GaEntryGroupService *mdns_service; +#include "avahi-common.h" #endif #include "libphodav/phodav.h" @@ -77,88 +72,6 @@ return g_strdup_printf ("%s\'s public share", g_get_user_name ()); } -#ifdef WITH_AVAHI -static void -mdns_register_service (void) -{ - GError *error = NULL; - gchar *name = NULL; - - if (!mdns_group) - { - mdns_group = ga_entry_group_new (); - - if (!ga_entry_group_attach (mdns_group, mdns_client, &error)) - { - g_warning ("Could not attach MDNS group to client: %s", error->message); - g_clear_error (&error); - return; - } - } - - name = get_realm (); - mdns_service = ga_entry_group_add_service (mdns_group, - name, "_webdav._tcp", - port, &error, - NULL); - if (!mdns_service) - { - g_warning ("Could not create service: %s", error->message); - g_clear_error (&error); - goto end; - } - - ga_entry_group_service_freeze (mdns_service); - if (!ga_entry_group_service_set (mdns_service, "u", "", &error) || - !ga_entry_group_service_set (mdns_service, "p", "", &error) || - !ga_entry_group_service_set (mdns_service, "path", "/", &error) || - !ga_entry_group_service_thaw (mdns_service, &error)) - { - g_warning ("Could not update TXT: %s", error->message); - g_clear_error (&error); - } - - if (!ga_entry_group_commit (mdns_group, &error)) - { - g_warning ("Could not announce MDNS service: %s", error->message); - g_clear_error (&error); - } - -end: - g_free (name); -} - -static void -mdns_state_changed (GaClient *client, GaClientState state, gpointer user_data) -{ - switch (state) - { - case GA_CLIENT_STATE_FAILURE: - g_warning ("MDNS client state failure"); - break; - - case GA_CLIENT_STATE_S_RUNNING: - g_debug ("MDNS client found server running"); - mdns_register_service (); - break; - - case GA_CLIENT_STATE_S_COLLISION: - case GA_CLIENT_STATE_S_REGISTERING: - g_message ("MDNS collision"); - if (mdns_group) - { - ga_entry_group_reset (mdns_group, NULL); - mdns_service = 0; - } - break; - - default: - // Do nothing - break; - } -} -#endif // WITH_AVAHI - gchar *htdigest = NULL; static gchar * @@ -216,9 +129,6 @@ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR); bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); -#if !GLIB_CHECK_VERSION (2, 35, 1) - g_type_init (); -#endif g_set_prgname ("chezdav"); context = g_option_context_new (_ ("- simple WebDAV server")); @@ -282,9 +192,8 @@ #ifdef WITH_AVAHI - mdns_client = ga_client_new (GA_CLIENT_FLAG_NO_FLAGS); - g_signal_connect (mdns_client, "state-changed", G_CALLBACK (mdns_state_changed), NULL); - if (!ga_client_start (mdns_client, &error)) + gchar *name = get_realm (); + if (!avahi_client_start (name, port, local, &error)) my_error (_ ("mDNS failed: %s\n"), error->message); #endif @@ -306,7 +215,8 @@ g_main_loop_unref (mainloop); #ifdef WITH_AVAHI - g_object_unref (mdns_client); + avahi_client_stop (); + g_free (name); #endif g_object_unref (dav); diff -Nru phodav-2.3/libphodav/meson.build phodav-2.4/libphodav/meson.build --- phodav-2.3/libphodav/meson.build 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/libphodav/meson.build 2020-03-05 11:15:02.000000000 +0000 @@ -53,7 +53,7 @@ executable( 'chezdav', - [ 'chezdav.c' ], + [ 'chezdav.c' ] + avahi_common, include_directories : incdir, dependencies : avahi_deps + deps, link_with : [ libphodav ], diff -Nru phodav-2.3/libphodav/phodav-method-propfind.c phodav-2.4/libphodav/phodav-method-propfind.c --- phodav-2.3/libphodav/phodav-method-propfind.c 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/libphodav/phodav-method-propfind.c 2020-03-05 11:15:02.000000000 +0000 @@ -327,6 +327,7 @@ prop_quota_available (PathHandler *handler, PropFind *pf, const gchar *path, GFileInfo *_info, xmlNsPtr ns) { + GFile *file; GFileInfo *info = NULL; gint status = SOUP_STATUS_OK; xmlNodePtr node = xmlNewNode (ns, BAD_CAST "quota-available-bytes"); @@ -338,8 +339,11 @@ if (pf->type == PROPFIND_PROPNAME) goto end; - info = g_file_query_filesystem_info (handler_get_file (handler), "filesystem::*", + file = g_file_get_child (handler_get_file (handler), path + 1); + info = g_file_query_filesystem_info (file, "filesystem::*", cancellable, &error); + g_object_unref (file); + if (error) { g_warning ("Filesystem info error: %s", error->message); @@ -361,11 +365,11 @@ return node; } -#if GLIB_CHECK_VERSION (2, 38, 0) static xmlNodePtr prop_quota_used (PathHandler *handler, PropFind *pf, const gchar *path, GFileInfo *info, xmlNsPtr ns) { + GFile *file = NULL; gint status = SOUP_STATUS_OK; GCancellable *cancellable = handler_get_cancellable(handler); xmlNodePtr node = xmlNewNode (ns, BAD_CAST "quota-used-bytes"); @@ -376,7 +380,8 @@ if (pf->type == PROPFIND_PROPNAME) goto end; - if (!g_file_measure_disk_usage (handler_get_file (handler), + file = g_file_get_child (handler_get_file (handler), path + 1); + if (!g_file_measure_disk_usage (file, G_FILE_MEASURE_NONE, cancellable, NULL, NULL, @@ -392,11 +397,11 @@ xmlAddChild (node, xmlNewText (BAD_CAST tmp)); end: + g_clear_object (&file); g_free (tmp); PROP_SET_STATUS (node, status); return node; } -#endif static gint node_compare_int (xmlNodePtr a, @@ -431,9 +436,7 @@ PROP (supportedlock, 0), PROP (lockdiscovery, 0), { "quota-available-bytes", prop_quota_available, }, -#if GLIB_CHECK_VERSION (2, 38, 0) { "quota-used-bytes", prop_quota_used, FALSE, TRUE, } -#endif }; static xmlNodePtr diff -Nru phodav-2.3/meson.build phodav-2.4/meson.build --- phodav-2.3/meson.build 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/meson.build 2020-03-05 11:15:02.000000000 +0000 @@ -6,7 +6,7 @@ check : true ).stdout().strip(), license : 'LGPLv2.1', - meson_version : '>= 0.49', + meson_version : '>= 0.50', ) meson.add_dist_script('sh', '-c', 'echo @0@>"$MESON_DIST_ROOT/.tarball-version"'.format(meson.project_version())) @@ -29,9 +29,9 @@ deps = [] if host_machine.system() == 'windows' - deps += dependency('gio-windows-2.0') + deps += dependency('gio-windows-2.0', version : '>= 2.44') else - deps += dependency('gio-unix-2.0') + deps += dependency('gio-unix-2.0', version : '>= 2.44') endif deps += dependency('libsoup-2.4', version : '>= 2.48.0') @@ -40,8 +40,10 @@ d1 = dependency('avahi-gobject', required : get_option('avahi')) d2 = dependency('avahi-client', required : get_option('avahi')) avahi_deps = [] +avahi_common = [] if d1.found() and d2.found() avahi_deps += [ d1, d2 ] + avahi_common += [ '../avahi-common.c', ] conf.set('WITH_AVAHI', 1) endif @@ -53,7 +55,7 @@ ) endif -udev = dependency('udev', required : get_option('systemd')) +udev = dependency('udev', required : get_option('udev')) if udev.found() install_data( 'data/70-spice-webdavd.rules', diff -Nru phodav-2.3/meson_options.txt phodav-2.4/meson_options.txt --- phodav-2.3/meson_options.txt 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/meson_options.txt 2020-03-05 11:15:02.000000000 +0000 @@ -10,6 +10,10 @@ type : 'feature', description : 'Install systemd units/configuration') +option('udev', + type : 'feature', + description : 'Install udev rules') + option('build-id', type : 'integer', value : 0, diff -Nru phodav-2.3/NEWS phodav-2.4/NEWS --- phodav-2.3/NEWS 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/NEWS 2020-03-05 11:15:02.000000000 +0000 @@ -1,3 +1,20 @@ +v2.4 +==== + +- Requires GIO >= 2.44 +- !2 - Added udev option to meson +- spice-webdavd: + - !3 : several improvements and fixes including some leaks + - !4 : disconnect the client gracefully + - !5 : code refcatory to improve performance and error handling + - !6 : avahi fixes on registering and unregistering service + - !7 : Fixes DAV:quota-used-bytes in resource is not in root fs + +- Translations + - Added Basque + - Added Dutch + - Added Finnish + v2.3 ==== diff -Nru phodav-2.3/po/eu.po phodav-2.4/po/eu.po --- phodav-2.3/po/eu.po 1970-01-01 00:00:00.000000000 +0000 +++ phodav-2.4/po/eu.po 2020-03-05 11:15:02.000000000 +0000 @@ -0,0 +1,90 @@ +# Basque translation for phodav. +# Copyright (C) 2019 phodav's COPYRIGHT HOLDER +# This file is distributed under the same license as the phodav package. +# Asier Sarasua Garmendia , 2019. +# +msgid "" +msgstr "Project-Id-Version: phodav master\n" +"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/phodav/issues\n" +"POT-Creation-Date: 2019-08-22 15:18+0000\n" +"PO-Revision-Date: 2019-10-18 10:00+0100\n" +"Last-Translator: Asier Sarasua Garmendia \n" +"Language-Team: Basque \n" +"Language: eu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: libphodav/chezdav.c:203 +msgid "Print program version" +msgstr "Erakutsi programaren bertsioa" + +#: libphodav/chezdav.c:204 +msgid "Be verbose" +msgstr "Eman xehetasunak" + +#: libphodav/chezdav.c:205 +msgid "Port to listen to" +msgstr "Entzungo den ataka" + +#: libphodav/chezdav.c:206 +msgid "Listen on loopback only" +msgstr "Entzun atzera-begiztan soilik" + +#: libphodav/chezdav.c:207 +msgid "Listen on all interfaces" +msgstr "Entzun interfaze guztietan" + +#: libphodav/chezdav.c:208 +msgid "Path to export" +msgstr "Esportaziorako bide-izena" + +#: libphodav/chezdav.c:209 +msgid "Path to htdigest file" +msgstr "htdigest fitxategiaren bide-izena" + +#: libphodav/chezdav.c:210 +msgid "Read-only access" +msgstr "Irakurtzeko soilik den sarbidea" + +#: libphodav/chezdav.c:221 +msgid "- simple WebDAV server" +msgstr "- WebDAV zerbitzari sinplea" + +#: libphodav/chezdav.c:222 +#, c-format +msgid "Report bugs to <%s>" +msgstr "Bidali erroreei buruzko informazioa hona: <%s>" + +#: libphodav/chezdav.c:229 +#, c-format +msgid "Option parsing failed: %s\n" +msgstr "Huts egin du aukera aztertzean: %s\n" + +#: libphodav/chezdav.c:233 +#, c-format +msgid "Unsupported extra arguments: %s ...\n" +msgstr "Onartzen ez diren argumentu gehigarriak: %s …\n" + +#: libphodav/chezdav.c:242 +msgid "--local and --public are mutually exclusive\n" +msgstr "--local and --public elkarrekiko esklusiboak dira\n" + +#: libphodav/chezdav.c:266 +#, c-format +msgid "Failed to open htdigest: %s\n" +msgstr "Huts egin du htdigest irekitzeak: %s\n" + +#: libphodav/chezdav.c:285 +#, c-format +msgid "mDNS failed: %s\n" +msgstr "mDNS-k huts egin du: %s\n" + +#: libphodav/chezdav.c:296 +msgid "Internal error, should not happen\n" +msgstr "Barneko errorea, ez litzateke gertatu beharko\n" + +#: libphodav/chezdav.c:299 +#, c-format +msgid "Listen failed: %s\n" +msgstr "Entzuteak huts egin du: %s\n" diff -Nru phodav-2.3/po/fi.po phodav-2.4/po/fi.po --- phodav-2.3/po/fi.po 1970-01-01 00:00:00.000000000 +0000 +++ phodav-2.4/po/fi.po 2020-03-05 11:15:02.000000000 +0000 @@ -0,0 +1,93 @@ +# Finnish translation for phodav. +# Copyright (C) 2019 phodav's COPYRIGHT HOLDER +# This file is distributed under the same license as the phodav package. +# Jiri Grönroos , 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: phodav master\n" +"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/phodav/issues\n" +"POT-Creation-Date: 2019-11-30 10:34+0000\n" +"PO-Revision-Date: 2020-02-23 14:59+0200\n" +"Last-Translator: Jiri Grönroos \n" +"Language-Team: Finnish \n" +"Language: fi\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"X-Generator: Poedit 2.3\n" + +#: libphodav/chezdav.c:203 +msgid "Print program version" +msgstr "Tulosta ohjelman versio" + +#: libphodav/chezdav.c:204 +msgid "Be verbose" +msgstr "Ole runsassanainen" + +#: libphodav/chezdav.c:205 +msgid "Port to listen to" +msgstr "Kuunneltava portti" + +#: libphodav/chezdav.c:206 +msgid "Listen on loopback only" +msgstr "Kuuntele vain loopback-osoitetta" + +#: libphodav/chezdav.c:207 +msgid "Listen on all interfaces" +msgstr "Kuuntele kaikissa liitännöissä" + +#: libphodav/chezdav.c:208 +msgid "Path to export" +msgstr "Tuotava polku" + +#: libphodav/chezdav.c:209 +msgid "Path to htdigest file" +msgstr "Polku htdigest-tiedostoon" + +#: libphodav/chezdav.c:210 +msgid "Read-only access" +msgstr "Vain lukuoikeus" + +#: libphodav/chezdav.c:221 +msgid "- simple WebDAV server" +msgstr "- yksinkertainen WebDAV-palvelin" + +#: libphodav/chezdav.c:222 +#, c-format +msgid "Report bugs to <%s>" +msgstr "Ilmoita bugeista <%s>" + +#: libphodav/chezdav.c:229 +#, c-format +msgid "Option parsing failed: %s\n" +msgstr "Valinnan jäsentäminen epäonnistui: %s\n" + +#: libphodav/chezdav.c:233 +#, c-format +msgid "Unsupported extra arguments: %s ...\n" +msgstr "Ei-tuetut lisäargumentit: %s ...\n" + +#: libphodav/chezdav.c:242 +msgid "--local and --public are mutually exclusive\n" +msgstr "--local ja --public eivät ole samanaikaisesti käytettävissä\n" + +#: libphodav/chezdav.c:266 +#, c-format +msgid "Failed to open htdigest: %s\n" +msgstr "Htdigestin avaaminen epäonnistui: %s\n" + +#: libphodav/chezdav.c:285 +#, c-format +msgid "mDNS failed: %s\n" +msgstr "mDNS epäonnistui: %s\n" + +#: libphodav/chezdav.c:296 +msgid "Internal error, should not happen\n" +msgstr "Sisäinen virhe, ei pitäisi tapahtua\n" + +#: libphodav/chezdav.c:299 +#, c-format +msgid "Listen failed: %s\n" +msgstr "Kuuntelu epäonnistui: %s\n" diff -Nru phodav-2.3/po/LINGUAS phodav-2.4/po/LINGUAS --- phodav-2.3/po/LINGUAS 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/po/LINGUAS 2020-03-05 11:15:02.000000000 +0000 @@ -5,10 +5,13 @@ de el es +eu +fi fur hr hu id +nl pl pt pt_BR diff -Nru phodav-2.3/po/nl.po phodav-2.4/po/nl.po --- phodav-2.3/po/nl.po 1970-01-01 00:00:00.000000000 +0000 +++ phodav-2.4/po/nl.po 2020-03-05 11:15:02.000000000 +0000 @@ -0,0 +1,93 @@ +# Dutch translation for phodav. +# Copyright (C) 2019 phodav's COPYRIGHT HOLDER +# This file is distributed under the same license as the phodav package. +# Nathan Follens , 2019. +# +msgid "" +msgstr "" +"Project-Id-Version: phodav master\n" +"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/phodav/issues\n" +"POT-Creation-Date: 2019-02-27 16:59+0000\n" +"PO-Revision-Date: 2019-03-04 16:20+0100\n" +"Language-Team: Dutch \n" +"Language: nl\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" +"Last-Translator: Nathan Follens \n" +"X-Generator: Poedit 2.2.1\n" + +#: libphodav/chezdav.c:203 +msgid "Print program version" +msgstr "Programmaversie tonen" + +#: libphodav/chezdav.c:204 +msgid "Be verbose" +msgstr "Uitgebreide uitvoer" + +#: libphodav/chezdav.c:205 +msgid "Port to listen to" +msgstr "Poort om op te luisteren" + +#: libphodav/chezdav.c:206 +msgid "Listen on loopback only" +msgstr "Enkel op loopback luisteren" + +#: libphodav/chezdav.c:207 +msgid "Listen on all interfaces" +msgstr "Op alle interfaces luisteren" + +#: libphodav/chezdav.c:208 +msgid "Path to export" +msgstr "Pad naar export" + +#: libphodav/chezdav.c:209 +msgid "Path to htdigest file" +msgstr "Pad naar htdigest-bestand" + +#: libphodav/chezdav.c:210 +msgid "Read-only access" +msgstr "Alleen-lezen-toegang" + +#: libphodav/chezdav.c:224 +msgid "- simple WebDAV server" +msgstr "- eenvoudige WebDAV-server" + +#: libphodav/chezdav.c:225 +#, c-format +msgid "Report bugs to <%s>" +msgstr "Rapporteer fouten aan <%s>" + +#: libphodav/chezdav.c:232 +#, c-format +msgid "Option parsing failed: %s\n" +msgstr "Ontleden van optie mislukt: %s\n" + +#: libphodav/chezdav.c:236 +#, c-format +msgid "Unsupported extra arguments: %s ...\n" +msgstr "Niet-ondersteunde extra parameters: %s …\n" + +#: libphodav/chezdav.c:245 +msgid "--local and --public are mutually exclusive\n" +msgstr "--local en --public sluiten elkaar onderling uit\n" + +#: libphodav/chezdav.c:269 +#, c-format +msgid "Failed to open htdigest: %s\n" +msgstr "Openen van htdigest mislukt: %s\n" + +#: libphodav/chezdav.c:288 +#, c-format +msgid "mDNS failed: %s\n" +msgstr "mDNS mislukt: %s\n" + +#: libphodav/chezdav.c:299 +msgid "Internal error, should not happen\n" +msgstr "Interne fout, dit zou niet mogen gebeuren\n" + +#: libphodav/chezdav.c:302 +#, c-format +msgid "Listen failed: %s\n" +msgstr "Luisteren mislukt: %s\n" diff -Nru phodav-2.3/README phodav-2.4/README --- phodav-2.3/README 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/README 1970-01-01 00:00:00.000000000 +0000 @@ -1,31 +0,0 @@ -phởdav -====== - -= About - -phởdav is a WebDav server implementation using libsoup (RFC 4918). - - Releases: http://ftp.gnome.org/pub/GNOME/sources/phodav/ - -= Tools - - chezdav, allows to share a particual directory (with optional - digest authentication) - -= Notes - -phởdav was initially developped as a filesharing mechanism for Spice, -but it is generic enough to be reused in other projects, in particular -in the GNOME desktop. Further integration work would be a welcome -contribution! - -= Contributing - - git clone git://git.gnome.org/phodav - - http://lists.freedesktop.org/mailman/listinfo/spice-devel - -Please report bug there: -https://bugzilla.gnome.org/enter_bug.cgi?product=phodav - -Forking and sending github pull requests is also welcome. \ No newline at end of file diff -Nru phodav-2.3/README.md phodav-2.4/README.md --- phodav-2.3/README.md 1970-01-01 00:00:00.000000000 +0000 +++ phodav-2.4/README.md 2020-03-05 11:15:02.000000000 +0000 @@ -0,0 +1,31 @@ +# phởdav + +## About + +phởdav is a WebDav server implementation using libsoup (RFC 4918). + +Releases: http://ftp.gnome.org/pub/GNOME/sources/phodav/ + +## Tools + +* chezdav, allows to share a particual directory (with optional + digest authentication) + +## Notes + +phởdav was initially developped as a filesharing mechanism for Spice, +but it is generic enough to be reused in other projects, in particular +in the GNOME desktop. Further integration work would be a welcome +contribution! + +## Contributing + + git clone https://gitlab.gnome.org/GNOME/phodav.git + +Mailing list: +http://lists.freedesktop.org/mailman/listinfo/spice-devel + +Please report bugs on gitlab: +https://gitlab.gnome.org/GNOME/phodav/issues + +Forking on gitlab and making pull requests is recommended, as it runs CI test. \ No newline at end of file diff -Nru phodav-2.3/spice/meson.build phodav-2.4/spice/meson.build --- phodav-2.3/spice/meson.build 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/spice/meson.build 2020-03-05 11:15:02.000000000 +0000 @@ -4,9 +4,15 @@ win32_deps += compiler.find_library('mpr') endif +sources = [ + 'spice-webdavd.c', + 'output-queue.c', + 'output-queue.h' +] + executable( 'spice-webdavd', - [ 'spice-webdavd.c' ], + sources + avahi_common, install_dir : sbindir, include_directories : incdir, dependencies : win32_deps + avahi_deps + deps, diff -Nru phodav-2.3/spice/output-queue.c phodav-2.4/spice/output-queue.c --- phodav-2.3/spice/output-queue.c 1970-01-01 00:00:00.000000000 +0000 +++ phodav-2.4/spice/output-queue.c 2020-03-05 11:15:02.000000000 +0000 @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2019 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include + +#include "output-queue.h" + +typedef struct _OutputQueueElem +{ + const guint8 *buf; + gsize size; + PushedCb cb; + gpointer user_data; +} OutputQueueElem; + +struct _OutputQueue +{ + GObject parent_instance; + GOutputStream *output; + gboolean writing; + GQueue *queue; + GCancellable *cancel; +}; + +G_DEFINE_TYPE (OutputQueue, output_queue, G_TYPE_OBJECT); + +static void output_queue_kick (OutputQueue *q); + +static void output_queue_init (OutputQueue *self) +{ + self->queue = g_queue_new (); +} + +static void output_queue_finalize (GObject *obj) +{ + OutputQueue *self = OUTPUT_QUEUE (obj); + + g_queue_free_full (self->queue, g_free); + g_object_unref (self->output); + g_object_unref (self->cancel); + + G_OBJECT_CLASS (output_queue_parent_class)->finalize (obj); +} + +static void output_queue_class_init (OutputQueueClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + gobject_class->finalize = output_queue_finalize; +} + +OutputQueue* output_queue_new (GOutputStream *output, GCancellable *cancel) +{ + OutputQueue *self = g_object_new (OUTPUT_TYPE_QUEUE, NULL); + self->output = g_object_ref (output); + self->cancel = g_object_ref (cancel); + return self; +} + +static void +write_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + OutputQueue *q = user_data; + OutputQueueElem *e; + GError *err = NULL; + + e = g_queue_pop_head (q->queue); + g_output_stream_write_all_finish (G_OUTPUT_STREAM (source_object), res, NULL, &err); + + if (e->cb) + e->cb (q, e->user_data, err); + + g_free (e); + q->writing = FALSE; + if (!err) + output_queue_kick (q); + g_clear_error (&err); + g_object_unref (q); +} + +static void +output_queue_kick (OutputQueue *q) +{ + OutputQueueElem *e; + + if (!q || q->writing || g_queue_is_empty (q->queue)) + return; + + e = g_queue_peek_head (q->queue); + q->writing = TRUE; + g_output_stream_write_all_async (q->output, e->buf, e->size, + G_PRIORITY_DEFAULT, q->cancel, write_cb, g_object_ref (q)); +} + +void +output_queue_push (OutputQueue *q, const guint8 *buf, gsize size, + PushedCb pushed_cb, gpointer user_data) +{ + OutputQueueElem *e; + + g_return_if_fail (q != NULL); + + e = g_new (OutputQueueElem, 1); + e->buf = buf; + e->size = size; + e->cb = pushed_cb; + e->user_data = user_data; + g_queue_push_tail (q->queue, e); + + output_queue_kick (q); +} diff -Nru phodav-2.3/spice/output-queue.h phodav-2.4/spice/output-queue.h --- phodav-2.3/spice/output-queue.h 1970-01-01 00:00:00.000000000 +0000 +++ phodav-2.4/spice/output-queue.h 2020-03-05 11:15:02.000000000 +0000 @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2019 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef __OUTPUT_QUEUE_H +#define __OUTPUT_QUEUE_H + +#include +#include + +G_BEGIN_DECLS + +#define OUTPUT_TYPE_QUEUE output_queue_get_type () +G_DECLARE_FINAL_TYPE (OutputQueue, output_queue, OUTPUT, QUEUE, GObject); + +OutputQueue* output_queue_new (GOutputStream *output, GCancellable *cancel); + +typedef void (*PushedCb) (OutputQueue *q, gpointer user_data, GError *error); + +void output_queue_push (OutputQueue *q, const guint8 *buf, gsize size, + PushedCb pushed_cb, gpointer user_data); + +G_END_DECLS + +#endif diff -Nru phodav-2.3/spice/spice-webdavd.c phodav-2.4/spice/spice-webdavd.c --- phodav-2.3/spice/spice-webdavd.c 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/spice/spice-webdavd.c 2020-03-05 11:15:02.000000000 +0000 @@ -24,38 +24,22 @@ #include #include #include +#include +#include #endif #ifdef G_OS_WIN32 #include #include #include +#define SERVICE_NAME "spice-webdavd" #endif #ifdef WITH_AVAHI -#include -#include +#include "avahi-common.h" #endif -typedef struct _OutputQueue -{ - guint refs; - GOutputStream *output; - gboolean flushing; - guint idle_id; - GQueue *queue; -} OutputQueue; - -typedef void (*PushedCb) (OutputQueue *q, gpointer user_data, GError *error); - -typedef struct _OutputQueueElem -{ - OutputQueue *queue; - const guint8 *buf; - gsize size; - PushedCb cb; - gpointer user_data; -} OutputQueueElem; +#include "output-queue.h" typedef struct _ServiceData { @@ -67,139 +51,6 @@ static GCancellable *cancel; -static OutputQueue* -output_queue_new (GOutputStream *output) -{ - OutputQueue *queue = g_new0 (OutputQueue, 1); - - queue->output = g_object_ref (output); - queue->queue = g_queue_new (); - queue->refs = 1; - - return queue; -} - -static -void -output_queue_free (OutputQueue *queue) -{ - g_warn_if_fail (g_queue_get_length (queue->queue) == 0); - g_warn_if_fail (!queue->flushing); - g_warn_if_fail (!queue->idle_id); - - g_queue_free_full (queue->queue, g_free); - g_clear_object (&queue->output); - g_free (queue); -} - -static OutputQueue* -output_queue_ref (OutputQueue *q) -{ - q->refs++; - return q; -} - -static void -output_queue_unref (OutputQueue *q) -{ - g_return_if_fail (q != NULL); - - q->refs--; - if (q->refs == 0) - output_queue_free (q); -} - -static gboolean output_queue_idle (gpointer user_data); - -static void -output_queue_flush_cb (GObject *source_object, - GAsyncResult *res, - gpointer user_data) -{ - GError *error = NULL; - OutputQueueElem *e = user_data; - OutputQueue *q = e->queue; - - g_debug ("flushed"); - q->flushing = FALSE; - g_output_stream_flush_finish (G_OUTPUT_STREAM (source_object), - res, &error); - if (error) - g_warning ("error: %s", error->message); - - g_clear_error (&error); - - if (!q->idle_id) - q->idle_id = g_idle_add (output_queue_idle, output_queue_ref (q)); - - g_free (e); - output_queue_unref (q); -} - -static gboolean -output_queue_idle (gpointer user_data) -{ - OutputQueue *q = user_data; - OutputQueueElem *e = NULL; - GError *error = NULL; - - if (q->flushing) - { - g_debug ("already flushing"); - goto end; - } - - e = g_queue_pop_head (q->queue); - if (!e) - { - g_debug ("No more data to flush"); - goto end; - } - - g_debug ("flushing %" G_GSIZE_FORMAT, e->size); - g_output_stream_write_all (q->output, e->buf, e->size, NULL, cancel, &error); - if (e->cb) - e->cb (q, e->user_data, error); - - if (error) - goto end; - - q->flushing = TRUE; - g_output_stream_flush_async (q->output, G_PRIORITY_DEFAULT, cancel, output_queue_flush_cb, e); - - q->idle_id = 0; - return FALSE; - -end: - g_clear_error (&error); - q->idle_id = 0; - g_free (e); - output_queue_unref (q); - - return FALSE; -} - -static void -output_queue_push (OutputQueue *q, const guint8 *buf, gsize size, - PushedCb pushed_cb, gpointer user_data) -{ - OutputQueueElem *e; - - g_return_if_fail (q != NULL); - - e = g_new (OutputQueueElem, 1); - e->buf = buf; - e->size = size; - e->cb = pushed_cb; - e->user_data = user_data; - e->queue = q; - g_queue_push_tail (q->queue, e); - - if (!q->idle_id && !q->flushing) - q->idle_id = g_idle_add (output_queue_idle, output_queue_ref (q)); -} - - static struct _DemuxData { gint64 client; @@ -209,14 +60,17 @@ typedef struct _Client { - gint64 id; - guint8 buf[G_MAXUINT16]; - guint16 size; + guint ref_count; + struct + { + gint64 id; + guint16 size; + guint8 buf[G_MAXUINT16]; + } mux; GSocketConnection *client_connection; - OutputQueue *queue; } Client; -static gboolean quit_service; +static volatile gboolean quit_service; static GMainLoop *loop; static GInputStream *mux_istream; static GOutputStream *mux_ostream; @@ -230,9 +84,6 @@ #endif static void start_mux_read (GInputStream *istream); -#ifdef WITH_AVAHI -static void mdns_unregister_service (void); -#endif static void quit (int sig) @@ -242,144 +93,80 @@ if (sig == SIGINT || sig == SIGTERM) quit_service = TRUE; - g_main_loop_quit (loop); + if (loop) + g_main_loop_quit (loop); } +#ifdef G_OS_UNIX +static gboolean +signal_handler (gpointer user_data) +{ + quit(SIGINT); + return G_SOURCE_REMOVE; +} +#endif + static Client * add_client (GSocketConnection *client_connection) { - GIOStream *iostream = G_IO_STREAM (client_connection); - GOutputStream *ostream = g_io_stream_get_output_stream (iostream); - GOutputStream *bostream; Client *client; - - bostream = g_buffered_output_stream_new (ostream); - g_buffered_output_stream_set_auto_grow (G_BUFFERED_OUTPUT_STREAM (bostream), TRUE); - client = g_new0 (Client, 1); + client->ref_count = 1; client->client_connection = g_object_ref (client_connection); // TODO: check if usage of this idiom is portable, or if we need to check collisions - client->id = GPOINTER_TO_INT (client_connection); - client->queue = output_queue_new (bostream); - g_object_unref (bostream); - - g_hash_table_insert (clients, &client->id, client); - g_warn_if_fail (g_hash_table_lookup (clients, &client->id)); + client->mux.id = GPOINTER_TO_INT (client_connection); + g_hash_table_insert (clients, &client->mux.id, client); + g_warn_if_fail (g_hash_table_lookup (clients, &client->mux.id)); return client; } +static Client * +client_ref (Client *c) +{ + c->ref_count++; + return c; +} + static void -client_free (Client *c) +client_unref (gpointer user_data) { - g_debug ("Free client %p", c); + Client *c = user_data; + if (--c->ref_count > 0) + return; + + g_debug ("Free client %" G_GINT64_FORMAT, c->mux.id); g_io_stream_close (G_IO_STREAM (c->client_connection), NULL, NULL); g_object_unref (c->client_connection); - output_queue_unref (c->queue); g_free (c); } static void remove_client (Client *client) { - g_debug ("remove client %p", client); + g_debug ("remove client %" G_GINT64_FORMAT, client->mux.id); - g_hash_table_remove (clients, &client->id); + g_hash_table_remove (clients, &client->mux.id); } -typedef struct ReadData -{ - void *buffer; - gsize count; -} ReadData; - static void -read_thread (GTask *task, - gpointer source_object, - gpointer task_data, - GCancellable *cancellable) +mux_pushed_client_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) { + Client *client = user_data; GError *error = NULL; - GInputStream *stream = G_INPUT_STREAM (source_object); - ReadData *data; - gsize bread; - - data = g_task_get_task_data (task); - - g_debug ("my read %" G_GSIZE_FORMAT, data->count); - g_input_stream_read_all (stream, - data->buffer, data->count, &bread, - cancellable, &error); - g_debug ("my read result %" G_GSIZE_FORMAT, bread); + g_output_stream_write_all_finish (G_OUTPUT_STREAM (source_object), res, NULL, &error); if (error) { - g_debug ("error: %s", error->message); - g_task_return_error (task, error); - } - if (bread != data->count) - { - g_task_return_int (task, -1); - } - else - { - g_task_return_int (task, bread); + g_warning ("error pushing to client %" G_GINT64_FORMAT ": %s", + client->mux.id, error->message); + g_error_free (error); + remove_client (client); } -} - -static void -my_input_stream_read_async (GInputStream *stream, - void *buffer, - gsize count, - int io_priority, - GCancellable *cancellable, - GAsyncReadyCallback callback, - gpointer user_data) -{ - GTask *task; - ReadData *data = g_new (ReadData, 1); - - data->buffer = buffer; - data->count = count; - - task = g_task_new (stream, cancellable, callback, user_data); - g_task_set_task_data (task, data, g_free); - g_task_run_in_thread (task, read_thread); - - g_object_unref (task); -} - -static gssize -my_input_stream_read_finish (GInputStream *stream, - GAsyncResult *result, - GError **error) -{ - g_return_val_if_fail (g_task_is_valid (result, stream), -1); - - return g_task_propagate_int (G_TASK (result), error); -} - -static void -handle_push_error (OutputQueue *q, gpointer user_data, GError *error) -{ - Client *client = user_data; - - if (!error) - return; - - g_warning ("push error: %s", error->message); - remove_client (client); - return; -} - -static void -mux_pushed_client_cb (OutputQueue *q, gpointer user_data, GError *error) -{ - if (error) { - handle_push_error (q, user_data, error); - return; - } + client_unref (client); start_mux_read (mux_istream); } @@ -390,25 +177,31 @@ gpointer user_data) { GError *error = NULL; - gssize size; + gsize size; - size = my_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error); - g_return_if_fail (size == demux.size); + g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &size, &error); + g_debug ("read %" G_GSIZE_FORMAT " bytes from mux", size); if (error) { - g_warning ("error: %s", error->message); + g_warning ("%s: error: %s", __FUNCTION__, error->message); g_clear_error (&error); + } + if (size != demux.size) + { quit (-1); return; } Client *c = g_hash_table_lookup (clients, &demux.client); - g_debug ("looked up client: %p", c); - g_warn_if_fail(c != NULL); + g_debug ("looked up client %" G_GINT64_FORMAT ": %p", demux.client, c); if (c) - output_queue_push (c->queue, (guint8 *) demux.buf, demux.size, - mux_pushed_client_cb, c); + { + GOutputStream *out; + out = g_io_stream_get_output_stream (G_IO_STREAM (c->client_connection)); + g_output_stream_write_all_async (out, demux.buf, demux.size, + G_PRIORITY_DEFAULT, cancel, mux_pushed_client_cb, client_ref (c)); + } else start_mux_read (mux_istream); } @@ -420,21 +213,21 @@ { GInputStream *istream = G_INPUT_STREAM (source_object); GError *error = NULL; - gssize size; + gsize size; - size = my_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error); + g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &size, &error); if (error || size != sizeof (guint16)) goto end; - my_input_stream_read_async (istream, - &demux.buf, demux.size, G_PRIORITY_DEFAULT, - cancel, mux_data_read_cb, NULL); + g_input_stream_read_all_async (istream, + &demux.buf, demux.size, G_PRIORITY_DEFAULT, + cancel, mux_data_read_cb, NULL); return; end: if (error) { - g_warning ("error: %s", error->message); + g_warning ("%s: error: %s", __FUNCTION__, error->message); g_clear_error (&error); } @@ -448,36 +241,33 @@ { GInputStream *istream = G_INPUT_STREAM (source_object); GError *error = NULL; - gssize size; + gsize size; - size = my_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error); - g_debug ("read %" G_GSSIZE_FORMAT, size); + g_input_stream_read_all_finish (G_INPUT_STREAM (source_object), res, &size, &error); if (error || size != sizeof (gint64)) goto end; - my_input_stream_read_async (istream, - &demux.size, sizeof (guint16), G_PRIORITY_DEFAULT, - cancel, mux_size_read_cb, NULL); + g_input_stream_read_all_async (istream, + &demux.size, sizeof (guint16), G_PRIORITY_DEFAULT, + cancel, mux_size_read_cb, NULL); return; end: if (error) { - g_warning ("error: %s", error->message); + g_warning ("%s: error: %s", __FUNCTION__, error->message); g_clear_error (&error); } -#ifdef WITH_AVAHI - mdns_unregister_service (); -#endif quit (-3); } static void start_mux_read (GInputStream *istream) { - my_input_stream_read_async (istream, - &demux.client, sizeof (gint64), G_PRIORITY_DEFAULT, - cancel, mux_client_read_cb, NULL); + g_debug ("start reading mux"); + g_input_stream_read_all_async (istream, + &demux.client, sizeof (gint64), G_PRIORITY_DEFAULT, + cancel, mux_client_read_cb, NULL); } static void client_start_read (Client *client); @@ -487,18 +277,23 @@ { Client *client = user_data; - if (error) { - handle_push_error (q, client, error); - return; - } + if (error) + { + g_warning ("error pushing to mux from client %" G_GINT64_FORMAT ": %s", + client->mux.id, error->message); + remove_client (client); + goto end; + } - if (client->size == 0) + if (client->mux.size == 0) { remove_client (client); - return; + goto end; } client_start_read (client); +end: + client_unref (client); } static void @@ -511,24 +306,23 @@ gssize size; size = g_input_stream_read_finish (G_INPUT_STREAM (source_object), res, &error); - g_debug ("end read %" G_GSSIZE_FORMAT, size); + g_debug ("read %" G_GSSIZE_FORMAT " bytes from client %" G_GINT64_FORMAT, size, client->mux.id); if (error) { - g_warning ("error: %s", error->message); + g_warning ("%s: error for client %" G_GINT64_FORMAT ": %s", + __FUNCTION__, client->mux.id, error->message); g_clear_error (&error); remove_client (client); + client_unref (client); return; } g_return_if_fail (size <= G_MAXUINT16); g_return_if_fail (size >= 0); - client->size = size; - - output_queue_push (mux_queue, (guint8 *) &client->id, sizeof (gint64), handle_push_error, client); - output_queue_push (mux_queue, (guint8 *) &client->size, sizeof (guint16), handle_push_error, client); - output_queue_push (mux_queue, (guint8 *) client->buf, size, mux_pushed_cb, client); + client->mux.size = size; - return; + output_queue_push (mux_queue, (guint8 *) &client->mux, + sizeof (gint64) + sizeof (guint16) + size, mux_pushed_cb, client); } static void @@ -537,10 +331,10 @@ GIOStream *iostream = G_IO_STREAM (client->client_connection); GInputStream *istream = g_io_stream_get_input_stream (iostream); - g_debug ("start read client %p", client); + g_debug ("start read client %" G_GINT64_FORMAT, client->mux.id); g_input_stream_read_async (istream, - client->buf, G_MAXUINT16, G_PRIORITY_DEFAULT, - NULL, client_read_cb, client); + client->mux.buf, G_MAXUINT16, G_PRIORITY_DEFAULT, + cancel, client_read_cb, client_ref (client)); } static gboolean @@ -551,8 +345,8 @@ { Client *client; - g_debug ("new client!"); client = add_client (client_connection); + g_debug ("new client %" G_GINT64_FORMAT, client->mux.id); client_start_read (client); return FALSE; @@ -564,114 +358,6 @@ static gboolean no_service; #endif -#ifdef WITH_AVAHI -static GaClient *mdns_client; -static GaEntryGroup *mdns_group; -static GaEntryGroupService *mdns_service; - -static void -mdns_register_service (void) -{ - GError *error = NULL; - gchar *name = NULL; - - if (!mdns_group) - { - mdns_group = ga_entry_group_new (); - - if (!ga_entry_group_attach (mdns_group, mdns_client, &error)) - { - g_warning ("Could not attach MDNS group to client: %s", error->message); - g_clear_error (&error); - goto end; - } - } - - name = g_strdup_printf ("Spice client folder"); - mdns_service = ga_entry_group_add_service (mdns_group, - name, "_webdav._tcp", - port, &error, - NULL); - if (!mdns_service) - { - g_warning ("Could not create service: %s", error->message); - g_clear_error (&error); - goto end; - - } - - ga_entry_group_service_freeze (mdns_service); - if (!ga_entry_group_service_set (mdns_service, "u", "", &error) || - !ga_entry_group_service_set (mdns_service, "p", "", &error) || - !ga_entry_group_service_set (mdns_service, "path", "/", &error) || - !ga_entry_group_service_thaw (mdns_service, &error)) - { - g_warning ("Could not update TXT: %s", error->message); - g_clear_error (&error); - } - - if (!ga_entry_group_commit (mdns_group, &error)) - { - g_warning ("Could not announce MDNS service: %s", error->message); - g_clear_error (&error); - } - -end: - g_free (name); -} - -static void -mdns_unregister_service (void) -{ - GError *error = NULL; - - if (mdns_group) - { - if (!ga_entry_group_reset (mdns_group, &error)) - { - g_warning ("Could not disconnect MDNS service: %s", error->message); - g_clear_error (&error); - } - - mdns_service = 0; - g_debug ("MDNS client disconected"); - } -} - -static void -mdns_state_changed (GaClient *client, GaClientState state, gpointer user_data) -{ - switch (state) - { - case GA_CLIENT_STATE_FAILURE: - g_warning ("MDNS client state failure"); - break; - - case GA_CLIENT_STATE_S_RUNNING: - g_debug ("MDNS client found server running"); - mdns_register_service (); - break; - - case GA_CLIENT_STATE_S_COLLISION: - case GA_CLIENT_STATE_S_REGISTERING: - g_message ("MDNS collision"); - mdns_unregister_service (); - break; - - default: - // Do nothing - break; - } -} -#endif - -#ifndef G_SOURCE_REMOVE -#define G_SOURCE_REMOVE FALSE -#endif -#ifndef G_SOURCE_CONTINUE -#define G_SOURCE_CONTINUE TRUE -#endif - #ifdef G_OS_UNIX static void wait_for_virtio_host (gint fd) @@ -708,8 +394,12 @@ g_debug ("Open %s", path); #ifdef G_OS_UNIX port_fd = g_open (path, O_RDWR); + gint errsv = errno; if (port_fd == -1) + { + g_printerr("Failed to open %s: %s\n", path, g_strerror(errsv)); exit (1); + } wait_for_virtio_host (port_fd); @@ -731,18 +421,12 @@ mux_istream = G_INPUT_STREAM (g_win32_input_stream_new (port_handle, TRUE)); #endif - mux_queue = output_queue_new (G_OUTPUT_STREAM (mux_ostream)); + mux_queue = output_queue_new (G_OUTPUT_STREAM (mux_ostream), cancel); } #ifdef G_OS_WIN32 #define MAX_SHARED_FOLDER_NAME_SIZE 64 #define MAX_DRIVE_LETTER_SIZE 3 -typedef enum _MapDriveEnum -{ - MAP_DRIVE_OK, - MAP_DRIVE_TRY_AGAIN, - MAP_DRIVE_ERROR -} MapDriveEnum; typedef struct _MapDriveData { @@ -827,7 +511,7 @@ g_free(net_resource->lpRemoteName); } -static MapDriveEnum +static guint32 map_drive(const gchar drive_letter) { NETRESOURCE net_resource; @@ -840,16 +524,17 @@ if (errn == NO_ERROR) { g_debug ("Shared folder mapped to %c succesfully", drive_letter); - return MAP_DRIVE_OK; } else if (errn == ERROR_ALREADY_ASSIGNED) { g_debug ("Drive letter %c is already assigned", drive_letter); - return MAP_DRIVE_TRY_AGAIN; + } + else + { + g_warning ("map_drive error %d", errn); } - g_warning ("map_drive error %d", errn); - return MAP_DRIVE_ERROR; + return errn; } static void @@ -876,7 +561,6 @@ } g_mutex_unlock(&service_data->mutex); - return; } static void @@ -914,14 +598,20 @@ break; } - if (map_drive (drive_letter) != MAP_DRIVE_TRY_AGAIN) + ret = map_drive (drive_letter); + if (ret == ERROR_ALREADY_ASSIGNED) { - break; + /* try again with another letter */ + continue; } + if (ret != NO_ERROR) + { + drive_letter = 0; + } + break; //TODO: After mapping, rename network drive from \\localhost@PORT\DavWWWRoot // to something like SPICE Shared Folder } - g_mutex_lock(&map_drive_data->service_data->mutex); map_drive_data->service_data->drive_letter = drive_letter; g_mutex_unlock(&map_drive_data->service_data->mutex); @@ -929,11 +619,15 @@ #endif -static void +/* returns FALSE if the service should quit */ +static gboolean run_service (ServiceData *service_data) { g_debug ("Run service"); + if (quit_service) + return FALSE; + #ifdef G_OS_WIN32 MapDriveData map_drive_data; map_drive_data.cancel_map = g_cancellable_new (); @@ -957,7 +651,7 @@ cancel = g_cancellable_new (); clients = g_hash_table_new_full (g_int64_hash, g_int64_equal, - NULL, (GDestroyNotify) client_free); + NULL, client_unref); loop = g_main_loop_new (NULL, TRUE); #ifdef G_OS_UNIX @@ -972,10 +666,7 @@ #ifdef WITH_AVAHI GError *error = NULL; - - mdns_client = ga_client_new (GA_CLIENT_FLAG_NO_FLAGS); - g_signal_connect (mdns_client, "state-changed", G_CALLBACK (mdns_state_changed), NULL); - if (!ga_client_start (mdns_client, &error)) + if (!avahi_client_start ("Spice client folder", port, TRUE, &error)) { g_printerr ("%s\n", error->message); exit (1); @@ -984,7 +675,7 @@ start_mux_read (mux_istream); g_main_loop_run (loop); - g_main_loop_unref (loop); + g_clear_pointer (&loop, g_main_loop_unref); #ifdef G_OS_WIN32 g_cancellable_cancel (map_drive_data.cancel_map); @@ -996,12 +687,14 @@ g_clear_object (&mux_istream); g_clear_object (&mux_ostream); - output_queue_unref (mux_queue); + g_clear_object (&mux_queue); g_hash_table_unref (clients); +#ifdef WITH_AVAHI + avahi_client_stop (); +#endif g_socket_service_stop (socket_service); - mux_queue = NULL; g_clear_object (&cancel); #ifdef G_OS_WIN32 @@ -1009,6 +702,7 @@ #else close (port_fd); #endif + return !quit_service; } #ifdef G_OS_WIN32 @@ -1057,7 +751,7 @@ g_mutex_init(&service_data.mutex); service_status_handle = - RegisterServiceCtrlHandlerEx ("spice-webdavd", service_ctrl_handler, &service_data); + RegisterServiceCtrlHandlerEx (SERVICE_NAME, service_ctrl_handler, &service_data); g_return_if_fail (service_status_handle != 0); @@ -1070,9 +764,8 @@ service_status.dwWaitHint = 0; SetServiceStatus (service_status_handle, &service_status); - while (!quit_service) { - run_service (&service_data); - g_usleep (G_USEC_PER_SEC); + while (run_service(&service_data)) { + g_usleep(G_USEC_PER_SEC); } service_status.dwCurrentState = SERVICE_STOPPED; @@ -1116,7 +809,11 @@ } g_option_context_free (opts); +#ifdef G_OS_UNIX + g_unix_signal_add (SIGINT, signal_handler, NULL); +#else signal (SIGINT, quit); +#endif /* run socket service once at beginning, there seems to be a bug on windows, and it can't accept new connections if cleanup and @@ -1133,6 +830,7 @@ NULL, NULL, &error); + g_object_unref (saddr); if (error) { g_printerr ("%s\n", error->message); @@ -1149,7 +847,7 @@ SERVICE_TABLE_ENTRY service_table[] = { - { (char *)"spice-webdavd", service_main }, { NULL, NULL } + { SERVICE_NAME, service_main }, { NULL, NULL } }; if (!no_service && !getenv("DEBUG")) { @@ -1160,8 +858,7 @@ } } else #endif - while (!quit_service) { - run_service (&service_data); + while (run_service(&service_data)) { g_usleep (G_USEC_PER_SEC); } diff -Nru phodav-2.3/.tarball-version phodav-2.4/.tarball-version --- phodav-2.3/.tarball-version 2019-02-26 18:12:17.000000000 +0000 +++ phodav-2.4/.tarball-version 2020-03-05 11:15:02.000000000 +0000 @@ -1 +1 @@ -2.3 +2.4