aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Gabriel <mike.gabriel@das-netzwerkteam.de>2014-11-02 20:44:45 +0100
committerMike Gabriel <mike.gabriel@das-netzwerkteam.de>2014-11-02 20:44:45 +0100
commitfdc39509763f7d60429b903474916684da6653eb (patch)
treea44e03a9935392ea693088f25a37332cfffa9cb6 /src
downloadremote-logon-service-fdc39509763f7d60429b903474916684da6653eb.tar.gz
remote-logon-service-fdc39509763f7d60429b903474916684da6653eb.tar.bz2
remote-logon-service-fdc39509763f7d60429b903474916684da6653eb.zip
Imported Upstream version 1.0.0upstream/1.0.0
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am69
-rw-r--r--src/Makefile.in775
-rw-r--r--src/citrix-server.c225
-rw-r--r--src/citrix-server.h57
-rw-r--r--src/com.canonical.RemoteLogin.xml81
-rw-r--r--src/crypt.c153
-rw-r--r--src/crypt.h24
-rw-r--r--src/defines.h47
-rw-r--r--src/main.c453
-rw-r--r--src/rdp-server.c225
-rw-r--r--src/rdp-server.h57
-rw-r--r--src/remote-login.c2244
-rw-r--r--src/remote-login.h344
-rw-r--r--src/server.c292
-rw-r--r--src/server.h77
-rw-r--r--src/uccs-server.c949
-rw-r--r--src/uccs-server.h80
17 files changed, 6152 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..a402870
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,69 @@
+
+pkglibexec_PROGRAMS = \
+ remote-login-service
+
+EXTRA_DIST = \
+ com.canonical.RemoteLogin.xml
+
+noinst_LTLIBRARIES = \
+ libservers.la \
+ libgenerated.la
+
+################################
+# libgenerated
+################################
+
+libgenerated_la_SOURCES = \
+ remote-login.c \
+ remote-login.h
+libgenerated_la_CFLAGS = \
+ $(SERVICE_CFLAGS)
+$(libgenerated_la_SOURCES): com.canonical.RemoteLogin.xml
+ gdbus-codegen \
+ --interface-prefix com.canonical \
+ --generate-c remote-login \
+ $^
+
+BUILT_SOURCES = $(libgenerated_la_SOURCES)
+CLEANFILES = $(BUILT_SOURCES)
+
+################################
+# libservers
+################################
+
+libservers_la_SOURCES = \
+ citrix-server.c \
+ citrix-server.h \
+ rdp-server.c \
+ rdp-server.h \
+ uccs-server.c \
+ uccs-server.h \
+ defines.h \
+ server.c \
+ server.h \
+ crypt.c \
+ crypt.h
+libservers_la_CFLAGS = \
+ -DUCCS_QUERY_TOOL="\"thin-client-config-agent\"" \
+ $(SERVICE_CFLAGS) \
+ $(COVERAGE_CFLAGS)
+libservers_la_LDFLAGS = \
+ $(COVERAGE_LDFLAGS) $(GCRYPT_LIBS) -lm
+
+################################
+# remote-login-service
+################################
+
+remote_login_service_CFLAGS = \
+ -DDEFAULT_CONFIG_FILE="\"$(sysconfdir)/remote-login-service.conf\"" \
+ $(SERVICE_CFLAGS) \
+ $(COVERAGE_CFLAGS)
+remote_login_service_LDADD = \
+ $(builddir)/libservers.la \
+ $(builddir)/libgenerated.la \
+ $(SERVICE_LIBS)
+remote_login_service_LDFLAGS = \
+ $(COVERAGE_LDFLAGS)
+remote_login_service_SOURCES = \
+ main.c
+
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..7896286
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,775 @@
+# Makefile.in generated by automake 1.11.5 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+# Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+
+VPATH = @srcdir@
+am__make_dryrun = \
+ { \
+ am__dry=no; \
+ case $$MAKEFLAGS in \
+ *\\[\ \ ]*) \
+ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+ *) \
+ for am__flg in $$MAKEFLAGS; do \
+ case $$am__flg in \
+ *=*|--*) ;; \
+ *n*) am__dry=yes; break;; \
+ esac; \
+ done;; \
+ esac; \
+ test $$am__dry = yes; \
+ }
+pkgdatadir = $(datadir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkglibexecdir = $(libexecdir)/@PACKAGE@
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+pkglibexec_PROGRAMS = remote-login-service$(EXEEXT)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/m4/gcov.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+CONFIG_CLEAN_VPATH_FILES =
+LTLIBRARIES = $(noinst_LTLIBRARIES)
+libgenerated_la_LIBADD =
+am_libgenerated_la_OBJECTS = libgenerated_la-remote-login.lo
+libgenerated_la_OBJECTS = $(am_libgenerated_la_OBJECTS)
+AM_V_lt = $(am__v_lt_@AM_V@)
+am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+am__v_lt_0 = --silent
+libgenerated_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(libgenerated_la_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \
+ -o $@
+libservers_la_LIBADD =
+am_libservers_la_OBJECTS = libservers_la-citrix-server.lo \
+ libservers_la-rdp-server.lo libservers_la-uccs-server.lo \
+ libservers_la-server.lo libservers_la-crypt.lo
+libservers_la_OBJECTS = $(am_libservers_la_OBJECTS)
+libservers_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libservers_la_CFLAGS) \
+ $(CFLAGS) $(libservers_la_LDFLAGS) $(LDFLAGS) -o $@
+am__installdirs = "$(DESTDIR)$(pkglibexecdir)"
+PROGRAMS = $(pkglibexec_PROGRAMS)
+am_remote_login_service_OBJECTS = remote_login_service-main.$(OBJEXT)
+remote_login_service_OBJECTS = $(am_remote_login_service_OBJECTS)
+am__DEPENDENCIES_1 =
+remote_login_service_DEPENDENCIES = $(builddir)/libservers.la \
+ $(builddir)/libgenerated.la $(am__DEPENDENCIES_1)
+remote_login_service_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+ $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+ $(remote_login_service_CFLAGS) $(CFLAGS) \
+ $(remote_login_service_LDFLAGS) $(LDFLAGS) -o $@
+DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+am__mv = mv -f
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+AM_V_CC = $(am__v_CC_@AM_V@)
+am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+am__v_CC_0 = @echo " CC " $@;
+AM_V_at = $(am__v_at_@AM_V@)
+am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+am__v_at_0 = @
+CCLD = $(CC)
+LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+am__v_CCLD_0 = @echo " CCLD " $@;
+AM_V_GEN = $(am__v_GEN_@AM_V@)
+am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+am__v_GEN_0 = @echo " GEN " $@;
+SOURCES = $(libgenerated_la_SOURCES) $(libservers_la_SOURCES) \
+ $(remote_login_service_SOURCES)
+DIST_SOURCES = $(libgenerated_la_SOURCES) $(libservers_la_SOURCES) \
+ $(remote_login_service_SOURCES)
+am__can_run_installinfo = \
+ case $$AM_UPDATE_INFO_DIR in \
+ n|no|NO) false;; \
+ *) (install-info --version) >/dev/null 2>&1;; \
+ esac
+ETAGS = etags
+CTAGS = ctags
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMTAR = @AMTAR@
+AM_CFLAGS = @AM_CFLAGS@
+AM_CPPFLAGS = @AM_CPPFLAGS@
+AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+COVERAGE_CFLAGS = @COVERAGE_CFLAGS@
+COVERAGE_LDFLAGS = @COVERAGE_LDFLAGS@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIRNAME = @DATADIRNAME@
+DBUSSERVICEDIR = @DBUSSERVICEDIR@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+DLLTOOL = @DLLTOOL@
+DSYMUTIL = @DSYMUTIL@
+DUMPBIN = @DUMPBIN@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+FGREP = @FGREP@
+GCOVR = @GCOVR@
+GCRYPT_LIBS = @GCRYPT_LIBS@
+GENHTML = @GENHTML@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+GREP = @GREP@
+INSTALL = @INSTALL@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+LCOV = @LCOV@
+LD = @LD@
+LDFLAGS = @LDFLAGS@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LIPO = @LIPO@
+LN_S = @LN_S@
+LOCALEDIR = @LOCALEDIR@
+LTLIBOBJS = @LTLIBOBJS@
+MAKEINFO = @MAKEINFO@
+MANIFEST_TOOL = @MANIFEST_TOOL@
+MKDIR_P = @MKDIR_P@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+MSGFMT_OPTS = @MSGFMT_OPTS@
+MSGMERGE = @MSGMERGE@
+NM = @NM@
+NMEDIT = @NMEDIT@
+OBJDUMP = @OBJDUMP@
+OBJEXT = @OBJEXT@
+OTOOL = @OTOOL@
+OTOOL64 = @OTOOL64@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_URL = @PACKAGE_URL@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+RANLIB = @RANLIB@
+SED = @SED@
+SERVICE_CFLAGS = @SERVICE_CFLAGS@
+SERVICE_LIBS = @SERVICE_LIBS@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+SHTOOL = @SHTOOL@
+STRIP = @STRIP@
+TEST_CFLAGS = @TEST_CFLAGS@
+TEST_LIBS = @TEST_LIBS@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+XGETTEXT = @XGETTEXT@
+abs_builddir = @abs_builddir@
+abs_srcdir = @abs_srcdir@
+abs_top_builddir = @abs_top_builddir@
+abs_top_srcdir = @abs_top_srcdir@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+builddir = @builddir@
+datadir = @datadir@
+datarootdir = @datarootdir@
+docdir = @docdir@
+dvidir = @dvidir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+htmldir = @htmldir@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+intltool__v_merge_options_ = @intltool__v_merge_options_@
+intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localedir = @localedir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+pdfdir = @pdfdir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+psdir = @psdir@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+srcdir = @srcdir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+top_build_prefix = @top_build_prefix@
+top_builddir = @top_builddir@
+top_srcdir = @top_srcdir@
+EXTRA_DIST = \
+ com.canonical.RemoteLogin.xml
+
+noinst_LTLIBRARIES = \
+ libservers.la \
+ libgenerated.la
+
+
+################################
+# libgenerated
+################################
+libgenerated_la_SOURCES = \
+ remote-login.c \
+ remote-login.h
+
+libgenerated_la_CFLAGS = \
+ $(SERVICE_CFLAGS)
+
+BUILT_SOURCES = $(libgenerated_la_SOURCES)
+CLEANFILES = $(BUILT_SOURCES)
+
+################################
+# libservers
+################################
+libservers_la_SOURCES = \
+ citrix-server.c \
+ citrix-server.h \
+ rdp-server.c \
+ rdp-server.h \
+ uccs-server.c \
+ uccs-server.h \
+ defines.h \
+ server.c \
+ server.h \
+ crypt.c \
+ crypt.h
+
+libservers_la_CFLAGS = \
+ -DUCCS_QUERY_TOOL="\"thin-client-config-agent\"" \
+ $(SERVICE_CFLAGS) \
+ $(COVERAGE_CFLAGS)
+
+libservers_la_LDFLAGS = \
+ $(COVERAGE_LDFLAGS) $(GCRYPT_LIBS) -lm
+
+
+################################
+# remote-login-service
+################################
+remote_login_service_CFLAGS = \
+ -DDEFAULT_CONFIG_FILE="\"$(sysconfdir)/remote-login-service.conf\"" \
+ $(SERVICE_CFLAGS) \
+ $(COVERAGE_CFLAGS)
+
+remote_login_service_LDADD = \
+ $(builddir)/libservers.la \
+ $(builddir)/libgenerated.la \
+ $(SERVICE_LIBS)
+
+remote_login_service_LDFLAGS = \
+ $(COVERAGE_LDFLAGS)
+
+remote_login_service_SOURCES = \
+ main.c
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-am
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+ && { if test -f $@; then exit 0; else break; fi; }; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ $(am__cd) $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(am__aclocal_m4_deps):
+
+clean-noinstLTLIBRARIES:
+ -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+ @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+ dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+ test "$$dir" != "$$p" || dir=.; \
+ echo "rm -f \"$${dir}/so_locations\""; \
+ rm -f "$${dir}/so_locations"; \
+ done
+libgenerated.la: $(libgenerated_la_OBJECTS) $(libgenerated_la_DEPENDENCIES) $(EXTRA_libgenerated_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libgenerated_la_LINK) $(libgenerated_la_OBJECTS) $(libgenerated_la_LIBADD) $(LIBS)
+libservers.la: $(libservers_la_OBJECTS) $(libservers_la_DEPENDENCIES) $(EXTRA_libservers_la_DEPENDENCIES)
+ $(AM_V_CCLD)$(libservers_la_LINK) $(libservers_la_OBJECTS) $(libservers_la_LIBADD) $(LIBS)
+install-pkglibexecPROGRAMS: $(pkglibexec_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ @list='$(pkglibexec_PROGRAMS)'; test -n "$(pkglibexecdir)" || list=; \
+ if test -n "$$list"; then \
+ echo " $(MKDIR_P) '$(DESTDIR)$(pkglibexecdir)'"; \
+ $(MKDIR_P) "$(DESTDIR)$(pkglibexecdir)" || exit 1; \
+ fi; \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed 's/$(EXEEXT)$$//' | \
+ while read p p1; do if test -f $$p || test -f $$p1; \
+ then echo "$$p"; echo "$$p"; else :; fi; \
+ done | \
+ sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \
+ -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \
+ sed 'N;N;N;s,\n, ,g' | \
+ $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \
+ { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \
+ if ($$2 == $$4) files[d] = files[d] " " $$1; \
+ else { print "f", $$3 "/" $$4, $$1; } } \
+ END { for (d in files) print "f", d, files[d] }' | \
+ while read type dir files; do \
+ if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \
+ test -z "$$files" || { \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(pkglibexecdir)$$dir'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(pkglibexecdir)$$dir" || exit $$?; \
+ } \
+ ; done
+
+uninstall-pkglibexecPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(pkglibexec_PROGRAMS)'; test -n "$(pkglibexecdir)" || list=; \
+ files=`for p in $$list; do echo "$$p"; done | \
+ sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \
+ -e 's/$$/$(EXEEXT)/' `; \
+ test -n "$$list" || exit 0; \
+ echo " ( cd '$(DESTDIR)$(pkglibexecdir)' && rm -f" $$files ")"; \
+ cd "$(DESTDIR)$(pkglibexecdir)" && rm -f $$files
+
+clean-pkglibexecPROGRAMS:
+ @list='$(pkglibexec_PROGRAMS)'; test -n "$$list" || exit 0; \
+ echo " rm -f" $$list; \
+ rm -f $$list || exit $$?; \
+ test -n "$(EXEEXT)" || exit 0; \
+ list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f" $$list; \
+ rm -f $$list
+remote-login-service$(EXEEXT): $(remote_login_service_OBJECTS) $(remote_login_service_DEPENDENCIES) $(EXTRA_remote_login_service_DEPENDENCIES)
+ @rm -f remote-login-service$(EXEEXT)
+ $(AM_V_CCLD)$(remote_login_service_LINK) $(remote_login_service_OBJECTS) $(remote_login_service_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgenerated_la-remote-login.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libservers_la-citrix-server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libservers_la-crypt.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libservers_la-rdp-server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libservers_la-server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libservers_la-uccs-server.Plo@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remote_login_service-main.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+
+libgenerated_la-remote-login.lo: remote-login.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgenerated_la_CFLAGS) $(CFLAGS) -MT libgenerated_la-remote-login.lo -MD -MP -MF $(DEPDIR)/libgenerated_la-remote-login.Tpo -c -o libgenerated_la-remote-login.lo `test -f 'remote-login.c' || echo '$(srcdir)/'`remote-login.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgenerated_la-remote-login.Tpo $(DEPDIR)/libgenerated_la-remote-login.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='remote-login.c' object='libgenerated_la-remote-login.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgenerated_la_CFLAGS) $(CFLAGS) -c -o libgenerated_la-remote-login.lo `test -f 'remote-login.c' || echo '$(srcdir)/'`remote-login.c
+
+libservers_la-citrix-server.lo: citrix-server.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libservers_la_CFLAGS) $(CFLAGS) -MT libservers_la-citrix-server.lo -MD -MP -MF $(DEPDIR)/libservers_la-citrix-server.Tpo -c -o libservers_la-citrix-server.lo `test -f 'citrix-server.c' || echo '$(srcdir)/'`citrix-server.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libservers_la-citrix-server.Tpo $(DEPDIR)/libservers_la-citrix-server.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='citrix-server.c' object='libservers_la-citrix-server.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libservers_la_CFLAGS) $(CFLAGS) -c -o libservers_la-citrix-server.lo `test -f 'citrix-server.c' || echo '$(srcdir)/'`citrix-server.c
+
+libservers_la-rdp-server.lo: rdp-server.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libservers_la_CFLAGS) $(CFLAGS) -MT libservers_la-rdp-server.lo -MD -MP -MF $(DEPDIR)/libservers_la-rdp-server.Tpo -c -o libservers_la-rdp-server.lo `test -f 'rdp-server.c' || echo '$(srcdir)/'`rdp-server.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libservers_la-rdp-server.Tpo $(DEPDIR)/libservers_la-rdp-server.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rdp-server.c' object='libservers_la-rdp-server.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libservers_la_CFLAGS) $(CFLAGS) -c -o libservers_la-rdp-server.lo `test -f 'rdp-server.c' || echo '$(srcdir)/'`rdp-server.c
+
+libservers_la-uccs-server.lo: uccs-server.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libservers_la_CFLAGS) $(CFLAGS) -MT libservers_la-uccs-server.lo -MD -MP -MF $(DEPDIR)/libservers_la-uccs-server.Tpo -c -o libservers_la-uccs-server.lo `test -f 'uccs-server.c' || echo '$(srcdir)/'`uccs-server.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libservers_la-uccs-server.Tpo $(DEPDIR)/libservers_la-uccs-server.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='uccs-server.c' object='libservers_la-uccs-server.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libservers_la_CFLAGS) $(CFLAGS) -c -o libservers_la-uccs-server.lo `test -f 'uccs-server.c' || echo '$(srcdir)/'`uccs-server.c
+
+libservers_la-server.lo: server.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libservers_la_CFLAGS) $(CFLAGS) -MT libservers_la-server.lo -MD -MP -MF $(DEPDIR)/libservers_la-server.Tpo -c -o libservers_la-server.lo `test -f 'server.c' || echo '$(srcdir)/'`server.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libservers_la-server.Tpo $(DEPDIR)/libservers_la-server.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='server.c' object='libservers_la-server.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libservers_la_CFLAGS) $(CFLAGS) -c -o libservers_la-server.lo `test -f 'server.c' || echo '$(srcdir)/'`server.c
+
+libservers_la-crypt.lo: crypt.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libservers_la_CFLAGS) $(CFLAGS) -MT libservers_la-crypt.lo -MD -MP -MF $(DEPDIR)/libservers_la-crypt.Tpo -c -o libservers_la-crypt.lo `test -f 'crypt.c' || echo '$(srcdir)/'`crypt.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libservers_la-crypt.Tpo $(DEPDIR)/libservers_la-crypt.Plo
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='crypt.c' object='libservers_la-crypt.lo' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libservers_la_CFLAGS) $(CFLAGS) -c -o libservers_la-crypt.lo `test -f 'crypt.c' || echo '$(srcdir)/'`crypt.c
+
+remote_login_service-main.o: main.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(remote_login_service_CFLAGS) $(CFLAGS) -MT remote_login_service-main.o -MD -MP -MF $(DEPDIR)/remote_login_service-main.Tpo -c -o remote_login_service-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/remote_login_service-main.Tpo $(DEPDIR)/remote_login_service-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='remote_login_service-main.o' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(remote_login_service_CFLAGS) $(CFLAGS) -c -o remote_login_service-main.o `test -f 'main.c' || echo '$(srcdir)/'`main.c
+
+remote_login_service-main.obj: main.c
+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(remote_login_service_CFLAGS) $(CFLAGS) -MT remote_login_service-main.obj -MD -MP -MF $(DEPDIR)/remote_login_service-main.Tpo -c -o remote_login_service-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/remote_login_service-main.Tpo $(DEPDIR)/remote_login_service-main.Po
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='main.c' object='remote_login_service-main.obj' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(remote_login_service_CFLAGS) $(CFLAGS) -c -o remote_login_service-main.obj `if test -f 'main.c'; then $(CYGPATH_W) 'main.c'; else $(CYGPATH_W) '$(srcdir)/main.c'; fi`
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ set x; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ shift; \
+ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ if test $$# -gt 0; then \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ "$$@" $$unique; \
+ else \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$unique; \
+ fi; \
+ fi
+ctags: CTAGS
+CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+ END { if (nonempty) { for (i in files) print i; }; }'`; \
+ test -z "$(CTAGS_ARGS)$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && $(am__cd) $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) "$$here"
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+ list='$(DISTFILES)'; \
+ dist_files=`for file in $$list; do echo $$file; done | \
+ sed -e "s|^$$srcdirstrip/||;t" \
+ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+ case $$dist_files in \
+ */*) $(MKDIR_P) `echo "$$dist_files" | \
+ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+ sort -u` ;; \
+ esac; \
+ for file in $$dist_files; do \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ if test -d $$d/$$file; then \
+ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test -d "$(distdir)/$$file"; then \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+ fi; \
+ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+ else \
+ test -f "$(distdir)/$$file" \
+ || cp -p $$d/$$file "$(distdir)/$$file" \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-am
+all-am: Makefile $(LTLIBRARIES) $(PROGRAMS)
+installdirs:
+ for dir in "$(DESTDIR)$(pkglibexecdir)"; do \
+ test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-am
+install-exec: install-exec-am
+install-data: install-data-am
+uninstall: uninstall-am
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-am
+install-strip:
+ if test -z '$(STRIP)'; then \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ install; \
+ else \
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+ fi
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+ -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+clean: clean-am
+
+clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+ clean-pkglibexecPROGRAMS mostlyclean-am
+
+distclean: distclean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-tags
+
+dvi: dvi-am
+
+dvi-am:
+
+html: html-am
+
+html-am:
+
+info: info-am
+
+info-am:
+
+install-data-am:
+
+install-dvi: install-dvi-am
+
+install-dvi-am:
+
+install-exec-am: install-pkglibexecPROGRAMS
+
+install-html: install-html-am
+
+install-html-am:
+
+install-info: install-info-am
+
+install-info-am:
+
+install-man:
+
+install-pdf: install-pdf-am
+
+install-pdf-am:
+
+install-ps: install-ps-am
+
+install-ps-am:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-am
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-am
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-am
+
+pdf-am:
+
+ps: ps-am
+
+ps-am:
+
+uninstall-am: uninstall-pkglibexecPROGRAMS
+
+.MAKE: all check install install-am install-strip
+
+.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+ clean-libtool clean-noinstLTLIBRARIES clean-pkglibexecPROGRAMS \
+ ctags distclean distclean-compile distclean-generic \
+ distclean-libtool distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-dvi install-dvi-am install-exec \
+ install-exec-am install-html install-html-am install-info \
+ install-info-am install-man install-pdf install-pdf-am \
+ install-pkglibexecPROGRAMS install-ps install-ps-am \
+ install-strip installcheck installcheck-am installdirs \
+ maintainer-clean maintainer-clean-generic mostlyclean \
+ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
+ pdf pdf-am ps ps-am tags uninstall uninstall-am \
+ uninstall-pkglibexecPROGRAMS
+
+$(libgenerated_la_SOURCES): com.canonical.RemoteLogin.xml
+ gdbus-codegen \
+ --interface-prefix com.canonical \
+ --generate-c remote-login \
+ $^
+
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/citrix-server.c b/src/citrix-server.c
new file mode 100644
index 0000000..6837ad6
--- /dev/null
+++ b/src/citrix-server.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/mman.h>
+
+#include <glib/gi18n.h>
+
+#include <string.h>
+
+#include "citrix-server.h"
+#include "defines.h"
+
+static void citrix_server_class_init (CitrixServerClass *klass);
+static void citrix_server_init (CitrixServer *self);
+static void citrix_server_dispose (GObject *object);
+static void citrix_server_finalize (GObject *object);
+static GVariant * get_properties (Server * server);
+
+G_DEFINE_TYPE (CitrixServer, citrix_server, SERVER_TYPE);
+
+static void
+citrix_server_class_init (CitrixServerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = citrix_server_dispose;
+ object_class->finalize = citrix_server_finalize;
+
+ ServerClass * server_class = SERVER_CLASS(klass);
+
+ server_class->get_properties = get_properties;
+
+ return;
+}
+
+static void
+citrix_server_init (CitrixServer *self)
+{
+ self->username = NULL;
+ self->password = NULL;
+ self->domain = NULL;
+ self->domain_required = FALSE;
+
+ return;
+}
+
+static void
+citrix_server_dispose (GObject *object)
+{
+
+ G_OBJECT_CLASS (citrix_server_parent_class)->dispose (object);
+ return;
+}
+
+/* Unlocks the memory before freeing */
+static void
+password_clear (gpointer data)
+{
+ char * pass = (char *)data;
+ munlock(pass, strlen(pass));
+ g_free(pass);
+ return;
+}
+
+static void
+citrix_server_finalize (GObject *object)
+{
+ CitrixServer * server = CITRIX_SERVER(object);
+
+ g_clear_pointer(&server->username, g_free);
+ g_clear_pointer(&server->password, password_clear);
+ g_clear_pointer(&server->domain, g_free);
+
+ G_OBJECT_CLASS (citrix_server_parent_class)->finalize (object);
+ return;
+}
+
+static GVariant *
+get_properties (Server * server)
+{
+ CitrixServer * cserver = CITRIX_SERVER(server);
+
+ GVariantBuilder propbuilder;
+ g_variant_builder_init(&propbuilder, G_VARIANT_TYPE_ARRAY);
+
+ GVariantBuilder namebuilder;
+ g_variant_builder_init(&namebuilder, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_add_value(&namebuilder, g_variant_new_string("username"));
+ g_variant_builder_add_value(&namebuilder, g_variant_new_boolean(TRUE));
+ if (cserver->username == NULL) {
+ g_variant_builder_add_value(&namebuilder, g_variant_new_variant(g_variant_new_string("")));
+ } else {
+ g_variant_builder_add_value(&namebuilder, g_variant_new_variant(g_variant_new_string(cserver->username)));
+ }
+ g_variant_builder_add_value(&namebuilder, g_variant_parse(G_VARIANT_TYPE_VARDICT, "{}", NULL, NULL, NULL));
+ g_variant_builder_add_value(&propbuilder, g_variant_builder_end(&namebuilder));
+
+ GVariantBuilder passbuilder;
+ g_variant_builder_init(&passbuilder, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_add_value(&passbuilder, g_variant_new_string("password"));
+ g_variant_builder_add_value(&passbuilder, g_variant_new_boolean(TRUE));
+ if (cserver->password == NULL) {
+ g_variant_builder_add_value(&passbuilder, g_variant_new_variant(g_variant_new_string("")));
+ } else {
+ g_variant_builder_add_value(&passbuilder, g_variant_new_variant(g_variant_new_string(cserver->password)));
+ }
+ g_variant_builder_add_value(&passbuilder, g_variant_parse(G_VARIANT_TYPE_VARDICT, "{}", NULL, NULL, NULL));
+ g_variant_builder_add_value(&propbuilder, g_variant_builder_end(&passbuilder));
+
+ GVariantBuilder domainbuilder;
+ g_variant_builder_init(&domainbuilder, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_add_value(&domainbuilder, g_variant_new_string("domain"));
+ g_variant_builder_add_value(&domainbuilder, g_variant_new_boolean(cserver->domain_required));
+ if (cserver->domain == NULL) {
+ g_variant_builder_add_value(&domainbuilder, g_variant_new_variant(g_variant_new_string("")));
+ } else {
+ g_variant_builder_add_value(&domainbuilder, g_variant_new_variant(g_variant_new_string(cserver->domain)));
+ }
+ g_variant_builder_add_value(&domainbuilder, g_variant_parse(G_VARIANT_TYPE_VARDICT, "{}", NULL, NULL, NULL));
+ g_variant_builder_add_value(&propbuilder, g_variant_builder_end(&domainbuilder));
+
+ return g_variant_builder_end(&propbuilder);
+}
+
+Server *
+citrix_server_new_from_keyfile (GKeyFile * keyfile, const gchar * groupname)
+{
+ g_return_val_if_fail(keyfile != NULL, NULL); /* NOTE: No way to check if that's really a keyfile :-( */
+ g_return_val_if_fail(groupname != NULL, NULL);
+
+ if (!g_key_file_has_group(keyfile, groupname)) {
+ g_warning("Server specified but group '%s' was not found", groupname);
+ return NULL;
+ }
+
+ CitrixServer * server = g_object_new(CITRIX_SERVER_TYPE, NULL);
+
+ if (g_key_file_has_key(keyfile, groupname, CONFIG_SERVER_NAME, NULL)) {
+ gchar * keyname = g_key_file_get_string(keyfile, groupname, CONFIG_SERVER_NAME, NULL);
+ server->parent.name = g_strdup(_(keyname));
+ g_free(keyname);
+ }
+
+ if (g_key_file_has_key(keyfile, groupname, CONFIG_SERVER_URI, NULL)) {
+ server->parent.uri = g_key_file_get_string(keyfile, groupname, CONFIG_SERVER_URI, NULL);
+ }
+
+ return SERVER(server);
+}
+
+/* Build the Citrix server from information in the JSON object */
+Server *
+citrix_server_new_from_json (JsonObject * object)
+{
+ CitrixServer * server = g_object_new(CITRIX_SERVER_TYPE, NULL);
+
+ if (json_object_has_member(object, JSON_SERVER_NAME)) {
+ JsonNode * node = json_object_get_member(object, JSON_SERVER_NAME);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_STRING) {
+ const gchar * name = json_node_get_string(node);
+ server->parent.name = g_strdup(name);
+ }
+ }
+
+ if (json_object_has_member(object, JSON_URI)) {
+ JsonNode * node = json_object_get_member(object, JSON_URI);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_STRING) {
+ const gchar * uri = json_node_get_string(node);
+ server->parent.uri = g_strdup(uri);
+ }
+ }
+
+ if (json_object_has_member(object, JSON_USERNAME)) {
+ JsonNode * node = json_object_get_member(object, JSON_USERNAME);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_STRING) {
+ const gchar * username = json_node_get_string(node);
+ server->username = g_strdup(username);
+ }
+ }
+
+ if (json_object_has_member(object, JSON_PASSWORD)) {
+ JsonNode * node = json_object_get_member(object, JSON_PASSWORD);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_STRING) {
+ const gchar * password = json_node_get_string(node);
+ server->password = g_strdup(password);
+ mlock(server->password, strlen(server->password));
+ }
+ }
+
+ if (json_object_has_member(object, JSON_DOMAIN)) {
+ JsonNode * node = json_object_get_member(object, JSON_DOMAIN);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_STRING) {
+ const gchar * domain = json_node_get_string(node);
+ server->domain = g_strdup(domain);
+ }
+ }
+
+ if (json_object_has_member(object, JSON_DOMAIN_REQ)) {
+ JsonNode * node = json_object_get_member(object, JSON_DOMAIN_REQ);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_BOOLEAN) {
+ server->domain_required = json_node_get_boolean(node);
+ }
+ }
+
+ return SERVER(server);
+}
diff --git a/src/citrix-server.h b/src/citrix-server.h
new file mode 100644
index 0000000..058b663
--- /dev/null
+++ b/src/citrix-server.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#ifndef __CITRIX_SERVER_H__
+#define __CITRIX_SERVER_H__
+
+#include <glib-object.h>
+#include <json-glib/json-glib.h>
+#include "server.h"
+
+G_BEGIN_DECLS
+
+#define CITRIX_SERVER_TYPE (citrix_server_get_type ())
+#define CITRIX_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), CITRIX_SERVER_TYPE, CitrixServer))
+#define CITRIX_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), CITRIX_SERVER_TYPE, CitrixServerClass))
+#define IS_CITRIX_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), CITRIX_SERVER_TYPE))
+#define IS_CITRIX_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), CITRIX_SERVER_TYPE))
+#define CITRIX_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), CITRIX_SERVER_TYPE, CitrixServerClass))
+
+typedef struct _CitrixServer CitrixServer;
+typedef struct _CitrixServerClass CitrixServerClass;
+
+struct _CitrixServerClass {
+ ServerClass parent_class;
+};
+
+struct _CitrixServer {
+ Server parent;
+
+ gchar * username;
+ gchar * password;
+ gchar * domain;
+ gboolean domain_required;
+};
+
+GType citrix_server_get_type (void);
+Server * citrix_server_new_from_keyfile (GKeyFile * keyfile, const gchar * name);
+Server * citrix_server_new_from_json (JsonObject * object);
+
+G_END_DECLS
+
+#endif
diff --git a/src/com.canonical.RemoteLogin.xml b/src/com.canonical.RemoteLogin.xml
new file mode 100644
index 0000000..0fec355
--- /dev/null
+++ b/src/com.canonical.RemoteLogin.xml
@@ -0,0 +1,81 @@
+<?xml version="1.0"?>
+<node name="/">
+ <interface name="com.canonical.RemoteLogin">
+ <!-- SERVER LIST DOCS - it's in a few places :-)
+ s: server type: "ica", "freerdp", "uccs"
+ s: server name
+ s: server uri
+ b: last used server
+ a(sbva{sv}): properties for the server
+ s: type: "username", "password", "domain", "email"
+ b: required
+ v: default value
+ a{sv}: properties for the value, currently only used for domains
+ that have a list of possible domains
+ "domains": a(s)
+ and domains that are read only
+ "read-only": b
+ a(si): applications pinned for the server
+ s: ID of the application (desktop file)
+ i: position the application is pinned in
+ -->
+
+<!-- Methods -->
+ <method name="GetServers">
+ <!-- Get the servers that are available on the local network
+ that don't need a login to get -->
+ <arg type="a(sssba(sbva{sv})a(si))" name="serverList" direction="out" />
+ </method>
+ <method name="GetServersForLogin">
+ <arg type="s" name="uri" direction="in" />
+ <arg type="s" name="emailAddress" direction="in" />
+ <arg type="s" name="password" direction="in" />
+ <arg type="b" name="allowCache" direction="in" />
+
+ <arg type="b" name="loginSuccess" direction="out" />
+ <arg type="s" name="dataType" direction="out">
+ <!-- Should be either "cached" or "network" depending on where the data
+ was gotten from -->
+ </arg>
+ <arg type="a(sssba(sbva{sv})a(si))" name="serverList" direction="out" />
+ </method>
+ <method name="GetCachedDomainsForServer">
+ <arg type="s" name="uri" direction="in" />
+ <arg type="as" name="domains" direction="out" />
+ </method>
+ <method name="SetApplicationsForServer">
+ <arg type="s" name="uccsUri" direction="in" />
+ <!-- UCCS URI is optional and only needed for servers that
+ are under a UCCS account. NULL string if not used. -->
+ <arg type="s" name="serverUri" direction="in" />
+ <arg type="a(si)" name="applications" direction="in" />
+ </method>
+ <method name="SetLastUsedServer">
+ <arg type="s" name="uccsUri" direction="in" />
+ <arg type="s" name="serverUri" direction="in" />
+ </method>
+
+<!-- Signals -->
+ <signal name="ServersUpdated">
+ <arg type="a(sssba(sbva{sv})a(si))" name="serverList" direction="out" />
+ </signal>
+ <signal name="LoginServersUpdated">
+ <!-- Note: This IS NOT a broadcast signal, it will only be
+ signaled to folks who have previously called 'GetServersForLogin'
+ with a valid password -->
+ <arg type="s" name="uri" direction="out" />
+ <arg type="s" name="emailAddress" direction="out" />
+ <arg type="s" name="dataType" direction="out" />
+
+ <arg type="a(sssba(sbva{sv})a(si))" name="serverList" direction="out" />
+ </signal>
+ <signal name="LoginChanged">
+ <!-- This is sent if, for some reason, we think that the folks who
+ had previously called GetServersForLogin need to recall it. Those
+ who do not will not be sent 'LoginServersUpdated' signals. -->
+ <arg type="s" name="uri" direction="out" />
+ <arg type="s" name="emailAddress" direction="out" />
+ </signal>
+
+ </interface>
+</node>
diff --git a/src/crypt.c b/src/crypt.c
new file mode 100644
index 0000000..21355d4
--- /dev/null
+++ b/src/crypt.c
@@ -0,0 +1,153 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <glib.h>
+
+#include <gcrypt.h>
+#include <math.h>
+
+#include "crypt.h"
+
+static gcry_cipher_hd_t
+setup_cipher (const gchar * password)
+{
+ gcry_error_t gcryError;
+ gcry_cipher_hd_t gcryHandle;
+
+ const size_t keyLength = gcry_cipher_get_algo_keylen(GCRY_CIPHER_AES);
+ const size_t blkLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER_AES);
+
+ // We are assuming keyLength and blkLength are the same, check it
+ if (keyLength != blkLength)
+ return NULL;
+
+ char * aesSymKey = malloc(blkLength);
+ const size_t passwordLength = strlen(password);
+ strncpy(aesSymKey, password, blkLength);
+ size_t i;
+ for (i = passwordLength; i < blkLength; ++i)
+ aesSymKey[i] = 0;
+
+ gcryError = gcry_cipher_open(&gcryHandle, GCRY_CIPHER_AES, GCRY_CIPHER_MODE_CBC, 0);
+ if (gcryError) {
+ g_warning("gcry_cipher_open failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError));
+ return NULL;
+ }
+
+ gcryError = gcry_cipher_setkey(gcryHandle, aesSymKey, keyLength);
+ if (gcryError) {
+ g_warning("gcry_cipher_setkey failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError));
+ gcry_cipher_close(gcryHandle);
+ return NULL;
+ }
+
+ // Use the key as IV too
+ gcryError = gcry_cipher_setiv(gcryHandle, aesSymKey, blkLength);
+ if (gcryError) {
+ g_warning("gcry_cipher_setiv failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError));
+ gcry_cipher_close(gcryHandle);
+ return NULL;
+ }
+
+ return gcryHandle;
+}
+
+/**
+ * do_aes_encrypt:
+ * @origBuffer: text to encrypt. Needs to be null terminated
+ * @password: password to use. Will be cut/padded with 0 if it exceeds/does not reach the needed length
+ * @outBufferLength: (out) On success contains the length of the returned buffer
+ *
+ * Returns the AES encrypted version of the text. It is responsability of the caller to free it
+ */
+gchar *
+do_aes_encrypt(const gchar *origBuffer, const gchar * password, size_t *outBufferLength)
+{
+ gcry_error_t gcryError;
+ gcry_cipher_hd_t gcryHandle;
+
+ gcryHandle = setup_cipher (password);
+ if (gcryHandle == NULL) {
+ return NULL;
+ }
+
+ const size_t blkLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER_AES);
+ const size_t origBufferLength = strlen(origBuffer);
+ const size_t bufferLength = ceil((double)origBufferLength / blkLength) * blkLength;
+ gchar *buffer = malloc(bufferLength);
+ memcpy(buffer, origBuffer, origBufferLength);
+ int i;
+ for (i = origBufferLength; i < bufferLength; ++i)
+ buffer[i] = 0;
+
+ char * encBuffer = malloc(bufferLength);
+ size_t lengthDone = 0;
+ while (lengthDone < bufferLength) {
+ gcryError = gcry_cipher_encrypt(gcryHandle, &encBuffer[lengthDone], blkLength, &buffer[lengthDone], blkLength);
+ if (gcryError) {
+ g_warning("gcry_cipher_encrypt failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError));
+ gcry_cipher_close(gcryHandle);
+ free(encBuffer);
+ return NULL;
+ }
+ lengthDone += blkLength;
+ }
+
+ gcry_cipher_close(gcryHandle);
+
+ *outBufferLength = bufferLength;
+ return encBuffer;
+}
+
+/**
+ * do_aes_encrypt:
+ * @encBuffer: encrypted data
+ * @password: password to use. Will be cut/padded with 0 if it exceeds/does not reach the needed length
+ * @encBufferLength: Length of encBuffer
+ *
+ * Returns the AES decrypted version of the data. It is null terminated. It is responsability of the caller to free it
+ */
+gchar *
+do_aes_decrypt(const gchar *encBuffer, const gchar * password, const size_t encBufferLength)
+{
+ gcry_error_t gcryError;
+ gcry_cipher_hd_t gcryHandle;
+
+ gcryHandle = setup_cipher (password);
+ if (gcryHandle == NULL) {
+ return NULL;
+ }
+
+ const size_t blkLength = gcry_cipher_get_algo_blklen(GCRY_CIPHER_AES128);
+ const size_t bufferLength = encBufferLength;
+ char * outBuffer = malloc(bufferLength);
+ size_t lengthDone = 0;
+ while (lengthDone < bufferLength) {
+ gcryError = gcry_cipher_decrypt(gcryHandle, &outBuffer[lengthDone], 16, &encBuffer[lengthDone], 16);
+ if (gcryError)
+ {
+ g_warning("gcry_cipher_decrypt failed: %s/%s\n", gcry_strsource(gcryError), gcry_strerror(gcryError));
+ return NULL;
+ }
+ lengthDone += blkLength;
+ }
+
+ gcry_cipher_close(gcryHandle);
+ char *result = g_strndup(outBuffer, bufferLength);
+ free(outBuffer);
+ return result;
+}
diff --git a/src/crypt.h b/src/crypt.h
new file mode 100644
index 0000000..fd26e9e
--- /dev/null
+++ b/src/crypt.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef __CRYPT_H__
+#define __CRYPT_H__
+
+gchar * do_aes_encrypt(const gchar * buffer, const gchar * password, size_t *outBufferLength);
+gchar * do_aes_decrypt(const gchar * encBuffer, const gchar * password, const size_t encBufferLength);
+
+#endif
diff --git a/src/defines.h b/src/defines.h
new file mode 100644
index 0000000..e815ca5
--- /dev/null
+++ b/src/defines.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#ifndef __DEFINES_H__
+#define __DEFINES_H__
+
+#define CONFIG_MAIN_GROUP "Remote Login Service"
+#define CONFIG_MAIN_SERVERS "Servers"
+#define CONFIG_SERVER_PREFIX "Server"
+#define CONFIG_SERVER_NAME "Name"
+#define CONFIG_SERVER_URI "URI"
+
+#define CONFIG_UCCS_EXEC "Exec"
+#define CONFIG_UCCS_NETWORK "NetworkRequired"
+#define CONFIG_UCCS_NETWORK_NONE "None"
+#define CONFIG_UCCS_NETWORK_GLOBAL "Global"
+#define CONFIG_UCCS_VERIFY "VerifyServer"
+
+#define CONFIG_SERVER_TYPE "Type"
+#define CONFIG_SERVER_TYPE_RDP "RDP"
+#define CONFIG_SERVER_TYPE_ICA "ICA"
+#define CONFIG_SERVER_TYPE_UCCS "UCCS"
+
+#define JSON_PROTOCOL "Protocol"
+#define JSON_SERVER_NAME "Name"
+#define JSON_URI "URL"
+#define JSON_USERNAME "Username"
+#define JSON_PASSWORD "Password"
+#define JSON_DOMAIN_REQ "DomainRequired"
+#define JSON_DOMAIN "WindowsDomain"
+
+#endif /* __DEFINES_H__ */
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..b6d56d4
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,453 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib.h>
+#include <glib/gi18n.h>
+
+/* NOTE: Required to build without optimizations */
+#include <locale.h>
+
+#include "remote-login.h"
+#include "defines.h"
+
+#include "server.h"
+#include "rdp-server.h"
+#include "citrix-server.h"
+#include "uccs-server.h"
+#include "crypt.h"
+
+gint server_list_to_array (GVariantBuilder * builder, GList * items);
+
+enum {
+ ERROR_SERVER_URI,
+ ERROR_LOGIN
+};
+
+GList * config_file_servers = NULL;
+
+/* Get the error domain for this module */
+static GQuark
+error_domain (void)
+{
+ static GQuark value = 0;
+ if (value == 0) {
+ value = g_quark_from_static_string("remote-login-service");
+ }
+ return value;
+}
+
+/* When one of the state changes on the server emit that so that everone knows there
+ might be a new server available. */
+static void
+server_status_updated (Server * server, ServerState newstate, RemoteLogin * rl)
+{
+ GVariant * array = NULL;
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+
+ if (server_list_to_array(&builder, config_file_servers) > 0) {
+ array = g_variant_builder_end(&builder);
+ } else {
+ g_variant_builder_clear(&builder);
+ array = g_variant_new_array(G_VARIANT_TYPE("(sssba(sbva{sv})a(si))"), NULL, 0);
+ }
+
+ remote_login_emit_servers_updated(rl, array);
+ return;
+}
+
+/* Looks for the config file and does some basic parsing to pull out the UCCS servers
+ that are configured in it */
+static void
+find_config_file (GKeyFile * parsed, const gchar * cmnd_line, RemoteLogin * rl)
+{
+ GError * error = NULL;
+ const gchar * file = DEFAULT_CONFIG_FILE;
+
+ if (cmnd_line != NULL) {
+ file = cmnd_line;
+ }
+
+ if (!g_key_file_load_from_file(parsed, file, G_KEY_FILE_NONE, &error)) {
+ g_warning("Unable to parse config file '%s': %s", file, error->message);
+ g_error_free(error);
+ return;
+ }
+
+ if (!g_key_file_has_group(parsed, CONFIG_MAIN_GROUP)) {
+ g_warning("Config file '%s' doesn't have group '" CONFIG_MAIN_GROUP "'", file);
+ /* Probably should clear the keyfile, but there doesn't seem to be a way to do that */
+ return;
+ }
+
+ if (g_key_file_has_key(parsed, CONFIG_MAIN_GROUP, CONFIG_MAIN_SERVERS, NULL)) {
+ gchar ** grouplist = g_key_file_get_string_list(parsed, CONFIG_MAIN_GROUP, CONFIG_MAIN_SERVERS, NULL, NULL);
+ int i = 0;
+ gchar * groupsuffix;
+
+ for (groupsuffix = grouplist[0], i = 0; groupsuffix != NULL; groupsuffix = grouplist[++i]) {
+ gchar * groupname = g_strdup_printf("%s %s", CONFIG_SERVER_PREFIX, groupsuffix);
+ Server * server = server_new_from_keyfile(parsed, groupname);
+ g_free(groupname);
+
+ if (server == NULL) {
+ /* Assume a relevant error is printed above */
+ continue;
+ }
+
+ config_file_servers = g_list_append(config_file_servers, server);
+ g_signal_connect(server, SERVER_SIGNAL_STATE_CHANGED, G_CALLBACK(server_status_updated), rl);
+ }
+
+ g_strfreev(grouplist);
+ }
+
+ /* Signal the list of servers so that we're sure everyone's got them. This is to
+ solve a possible race where someone could ask while we're configuring these. */
+ server_status_updated(NULL, SERVER_STATE_ALLGOOD, rl);
+ return;
+}
+
+gint
+server_list_to_array (GVariantBuilder * builder, GList * items)
+{
+ gint servercnt = 0;
+ GList * head = NULL;
+ for (head = items; head != NULL; head = g_list_next(head)) {
+ Server * server = SERVER(head->data);
+
+ /* We only want servers that are all good */
+ if (server->state != SERVER_STATE_ALLGOOD) {
+ continue;
+ }
+
+ servercnt++;
+ GVariant * variant = server_get_variant(server);
+ g_variant_builder_add_value(builder, variant);
+ }
+
+ return servercnt;
+}
+
+static gboolean
+handle_get_servers (RemoteLogin * rl, GDBusMethodInvocation * invocation, gpointer user_data)
+{
+ GVariant * array = NULL;
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
+
+ if (server_list_to_array(&builder, config_file_servers) > 0) {
+ array = g_variant_builder_end(&builder);
+ } else {
+ g_variant_builder_clear(&builder);
+ array = g_variant_new_array(G_VARIANT_TYPE("(sssba(sbva{sv})a(si))"), NULL, 0);
+ }
+
+ g_dbus_method_invocation_return_value(invocation, g_variant_new_tuple(&array, 1));
+
+ return TRUE;
+}
+
+/* Handle the situation of whether we unlock or not and respond over
+ DBus with either an error or the list of servers. */
+static void
+handle_get_servers_login_cb (UccsServer * server, gboolean unlocked, gpointer user_data)
+{
+ GDBusMethodInvocation * invocation = (GDBusMethodInvocation *)user_data;
+ const gchar * sender = g_dbus_method_invocation_get_sender(invocation);
+
+ GVariantBuilder builder;
+ g_variant_builder_init(&builder, G_VARIANT_TYPE_TUPLE);
+
+ /* Signal whether we're unlocked */
+ g_variant_builder_add_value(&builder, g_variant_new_boolean(unlocked));
+
+ /* Only network, no caching yet */
+ g_variant_builder_add_value(&builder, g_variant_new_string("network"));
+
+ /* Get the array of servers */
+ GVariant * array = uccs_server_get_servers(server, sender);
+ g_variant_builder_add_value(&builder, array);
+
+ g_dbus_method_invocation_return_value(invocation, g_variant_builder_end(&builder));
+ return;
+}
+
+/* Handle the GetServerForLogin DBus call */
+static gboolean
+handle_get_servers_login (RemoteLogin * rl, GDBusMethodInvocation * invocation, gpointer user_data)
+{
+ GVariant * params = g_dbus_method_invocation_get_parameters(invocation);
+ const gchar * sender = g_dbus_method_invocation_get_sender(invocation);
+
+ GVariant * child = NULL;
+ const gchar * uri = NULL;
+
+ child = g_variant_get_child_value(params, 0);
+ uri = g_variant_get_string(child, NULL);
+ g_variant_unref(child); /* fine as we know params is still ref'd */
+
+ GList * lserver = NULL;
+ Server * server = NULL;
+ for (lserver = config_file_servers; lserver != NULL; lserver = g_list_next(lserver)) {
+ server = SERVER(lserver->data);
+
+ if (server == NULL) {
+ continue;
+ }
+
+ if (!IS_UCCS_SERVER(server)) {
+ continue;
+ }
+
+ if (g_strcmp0(server->uri, uri) == 0) {
+ break;
+ }
+ }
+
+ if (lserver == NULL) {
+ /* Couldn't find something with that URI, we're done, thanks. */
+ g_dbus_method_invocation_return_error(invocation,
+ error_domain(),
+ ERROR_SERVER_URI,
+ "Unable to find a server with the URI: '%s'",
+ uri);
+
+ return TRUE;
+ }
+
+ /* Unlock the Server */
+ const gchar * username = NULL;
+ const gchar * password = NULL;
+ gboolean allowcache = FALSE;
+
+ child = g_variant_get_child_value(params, 1);
+ username = g_variant_get_string(child, NULL);
+ g_variant_unref(child); /* fine as we know params is still ref'd */
+
+ child = g_variant_get_child_value(params, 2);
+ password = g_variant_get_string(child, NULL);
+ g_variant_unref(child); /* fine as we know params is still ref'd */
+
+ child = g_variant_get_child_value(params, 3);
+ allowcache = g_variant_get_boolean(child);
+ g_variant_unref(child);
+
+ /* Try to login and mark us as servicing the message */
+ uccs_server_unlock(UCCS_SERVER(server), sender, username, password, allowcache, handle_get_servers_login_cb, invocation);
+ return TRUE;
+}
+
+/* Look through a list of servers to see if one matches a URL */
+static Server *
+handle_get_domains_list_helper (GList * list, const gchar * uri)
+{
+ if (list == NULL) return NULL;
+
+ Server * inserver = SERVER(list->data);
+
+ if (inserver == NULL) {
+ return handle_get_domains_list_helper(g_list_next(list), uri);
+ }
+
+ Server * outserver = server_find_uri(inserver, uri);
+
+ if (outserver != NULL) {
+ return outserver;
+ }
+
+ return handle_get_domains_list_helper(g_list_next(list), uri);
+}
+
+/* Get the cached domains for a server */
+static gboolean
+handle_get_domains (RemoteLogin * rl, GDBusMethodInvocation * invocation, gpointer user_data)
+{
+ GVariant * params = g_dbus_method_invocation_get_parameters(invocation);
+
+ GVariant * child = NULL;
+ const gchar * uri = NULL;
+
+ child = g_variant_get_child_value(params, 0);
+ uri = g_variant_get_string(child, NULL);
+ g_variant_unref(child); /* fine as we know params is still ref'd */
+
+ Server * server = handle_get_domains_list_helper(config_file_servers, uri);
+
+ GVariant * domains = NULL;
+ if (server != NULL) {
+ domains = server_cached_domains(server);
+ } else {
+ domains = g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0);
+ }
+
+ if (domains == NULL) {
+ /* Couldn't find something with that URI, we're done, thanks. */
+ g_dbus_method_invocation_return_error(invocation,
+ error_domain(),
+ ERROR_SERVER_URI,
+ "Unable to find a server with the URI: '%s'",
+ uri);
+
+ return TRUE;
+ }
+
+ g_dbus_method_invocation_return_value(invocation, g_variant_new_tuple(&domains, 1));
+
+ return TRUE;
+}
+
+/* Set a given server as last used */
+static gboolean
+handle_set_last_used_server (RemoteLogin * rl, GDBusMethodInvocation * invocation, gpointer user_data)
+{
+ GVariant * params = g_dbus_method_invocation_get_parameters(invocation);
+
+ GVariant * child = NULL;
+ const gchar * uccsUri = NULL;
+ const gchar * serverUri = NULL;
+
+ child = g_variant_get_child_value(params, 0);
+ uccsUri = g_variant_get_string(child, NULL);
+ g_variant_unref(child); /* fine as we know params is still ref'd */
+
+ child = g_variant_get_child_value(params, 1);
+ serverUri = g_variant_get_string(child, NULL);
+ g_variant_unref(child); /* fine as we know params is still ref'd */
+
+ GList * lserver = NULL;
+ Server * server = NULL;
+ for (lserver = config_file_servers; lserver != NULL; lserver = g_list_next(lserver)) {
+ server = SERVER(lserver->data);
+
+ if (server == NULL) {
+ continue;
+ }
+
+ if (!IS_UCCS_SERVER(server)) {
+ continue;
+ }
+
+ if (g_strcmp0(server->uri, uccsUri) == 0) {
+ break;
+ }
+ }
+
+ if (server != NULL) {
+ server_set_last_used_server (server, serverUri);
+ }
+
+ g_dbus_method_invocation_return_value(invocation, NULL);
+
+ return TRUE;
+}
+
+/* If we loose the name, tell the world and there's not much we can do */
+static void
+name_lost (GDBusConnection * connection, const gchar * name, gpointer user_data)
+{
+ GMainLoop * mainloop = (GMainLoop *)user_data;
+
+ g_warning("Unable to get name '%s'. Exiting.", name);
+ g_main_loop_quit(mainloop);
+
+ return;
+}
+
+static gchar * cmnd_line_config = NULL;
+
+static GOptionEntry general_options[] = {
+ {"config-file", 'c', 0, G_OPTION_ARG_FILENAME, &cmnd_line_config, N_("Configuration file for the remote login service. Defaults to '/etc/remote-login-service.conf'."), N_("key_file")},
+ {NULL}
+};
+
+int
+main (int argc, char * argv[])
+{
+ GError * error = NULL;
+
+ /* Init the GTypes */
+ g_type_init();
+
+ /* Setup i18n */
+ setlocale (LC_ALL, "");
+ bindtextdomain (GETTEXT_PACKAGE, LOCALEDIR);
+ textdomain (GETTEXT_PACKAGE);
+
+ /* Create our global variables */
+ GKeyFile * config = g_key_file_new();
+ GMainLoop * mainloop = g_main_loop_new(NULL, FALSE);
+
+ /* Handle command line parameters */
+ GOptionContext * context;
+ context = g_option_context_new(_("- Determine the remote servers that can be logged into"));
+ g_option_context_add_main_entries(context, general_options, "remote-login-service");
+
+ if (!g_option_context_parse(context, &argc, &argv, &error)) {
+ g_print("option parsing failed: %s\n", error->message);
+ g_error_free(error);
+ return 1;
+ }
+
+ /* Start up D' Bus */
+ GDBusConnection * session_bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL /* cancel */, &error);
+ if (error != NULL) {
+ g_error("Unable to get session bus: %s", error->message);
+ g_error_free(error);
+ return -1;
+ }
+
+ /* Build Dbus Interface */
+ RemoteLogin * skel = remote_login_skeleton_new();
+ /* Export it */
+ g_dbus_interface_skeleton_export(G_DBUS_INTERFACE_SKELETON(skel),
+ session_bus,
+ "/com/canonical/RemoteLogin",
+ NULL);
+ g_signal_connect(skel, "handle-get-servers", G_CALLBACK(handle_get_servers), NULL);
+ g_signal_connect(skel, "handle-get-servers-for-login", G_CALLBACK(handle_get_servers_login), NULL);
+ g_signal_connect(skel, "handle-get-cached-domains-for-server", G_CALLBACK(handle_get_domains), NULL);
+ g_signal_connect(skel, "handle-set-last-used-server", G_CALLBACK(handle_set_last_used_server), NULL);
+
+ g_bus_own_name_on_connection(session_bus,
+ "com.canonical.RemoteLogin",
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ NULL, /* aquired handler */
+ name_lost,
+ mainloop,
+ NULL); /* mainloop free */
+
+ /* Parse config file */
+ find_config_file(config, cmnd_line_config, skel);
+
+ /* Loop forever */
+ g_main_loop_run(mainloop);
+
+ g_main_loop_unref(mainloop);
+ g_object_unref(config);
+
+ g_free(cmnd_line_config);
+
+ return 0;
+}
diff --git a/src/rdp-server.c b/src/rdp-server.c
new file mode 100644
index 0000000..f0bd87b
--- /dev/null
+++ b/src/rdp-server.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <sys/mman.h>
+
+#include <glib/gi18n.h>
+
+#include <string.h>
+
+#include "rdp-server.h"
+#include "defines.h"
+
+static void rdp_server_class_init (RdpServerClass *klass);
+static void rdp_server_init (RdpServer *self);
+static void rdp_server_dispose (GObject *object);
+static void rdp_server_finalize (GObject *object);
+static GVariant * get_properties (Server * server);
+
+G_DEFINE_TYPE (RdpServer, rdp_server, SERVER_TYPE);
+
+static void
+rdp_server_class_init (RdpServerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = rdp_server_dispose;
+ object_class->finalize = rdp_server_finalize;
+
+ ServerClass * server_class = SERVER_CLASS(klass);
+
+ server_class->get_properties = get_properties;
+
+ return;
+}
+
+static void
+rdp_server_init (RdpServer *self)
+{
+ self->username = NULL;
+ self->password = NULL;
+ self->domain = NULL;
+ self->domain_required = FALSE;
+
+ return;
+}
+
+static void
+rdp_server_dispose (GObject *object)
+{
+
+ G_OBJECT_CLASS (rdp_server_parent_class)->dispose (object);
+ return;
+}
+
+/* Unlocks the memory before freeing */
+static void
+password_clear (gpointer data)
+{
+ char * pass = (char *)data;
+ munlock(pass, strlen(pass));
+ g_free(pass);
+ return;
+}
+
+static void
+rdp_server_finalize (GObject *object)
+{
+ RdpServer * server = RDP_SERVER(object);
+
+ g_clear_pointer(&server->username, g_free);
+ g_clear_pointer(&server->password, password_clear);
+ g_clear_pointer(&server->domain, g_free);
+
+ G_OBJECT_CLASS (rdp_server_parent_class)->finalize (object);
+ return;
+}
+
+static GVariant *
+get_properties (Server * server)
+{
+ RdpServer * rserver = RDP_SERVER(server);
+
+ GVariantBuilder propbuilder;
+ g_variant_builder_init(&propbuilder, G_VARIANT_TYPE_ARRAY);
+
+ GVariantBuilder namebuilder;
+ g_variant_builder_init(&namebuilder, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_add_value(&namebuilder, g_variant_new_string("username"));
+ g_variant_builder_add_value(&namebuilder, g_variant_new_boolean(TRUE));
+ if (rserver->username == NULL) {
+ g_variant_builder_add_value(&namebuilder, g_variant_new_variant(g_variant_new_string("")));
+ } else {
+ g_variant_builder_add_value(&namebuilder, g_variant_new_variant(g_variant_new_string(rserver->username)));
+ }
+ g_variant_builder_add_value(&namebuilder, g_variant_parse(G_VARIANT_TYPE_VARDICT, "{}", NULL, NULL, NULL));
+ g_variant_builder_add_value(&propbuilder, g_variant_builder_end(&namebuilder));
+
+ GVariantBuilder passbuilder;
+ g_variant_builder_init(&passbuilder, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_add_value(&passbuilder, g_variant_new_string("password"));
+ g_variant_builder_add_value(&passbuilder, g_variant_new_boolean(TRUE));
+ if (rserver->password == NULL) {
+ g_variant_builder_add_value(&passbuilder, g_variant_new_variant(g_variant_new_string("")));
+ } else {
+ g_variant_builder_add_value(&passbuilder, g_variant_new_variant(g_variant_new_string(rserver->password)));
+ }
+ g_variant_builder_add_value(&passbuilder, g_variant_parse(G_VARIANT_TYPE_VARDICT, "{}", NULL, NULL, NULL));
+ g_variant_builder_add_value(&propbuilder, g_variant_builder_end(&passbuilder));
+
+ GVariantBuilder domainbuilder;
+ g_variant_builder_init(&domainbuilder, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_add_value(&domainbuilder, g_variant_new_string("domain"));
+ g_variant_builder_add_value(&domainbuilder, g_variant_new_boolean(rserver->domain_required));
+ if (rserver->domain == NULL) {
+ g_variant_builder_add_value(&domainbuilder, g_variant_new_variant(g_variant_new_string("")));
+ } else {
+ g_variant_builder_add_value(&domainbuilder, g_variant_new_variant(g_variant_new_string(rserver->domain)));
+ }
+ g_variant_builder_add_value(&domainbuilder, g_variant_parse(G_VARIANT_TYPE_VARDICT, "{}", NULL, NULL, NULL));
+ g_variant_builder_add_value(&propbuilder, g_variant_builder_end(&domainbuilder));
+
+ return g_variant_builder_end(&propbuilder);
+}
+
+Server *
+rdp_server_new_from_keyfile (GKeyFile * keyfile, const gchar * groupname)
+{
+ g_return_val_if_fail(keyfile != NULL, NULL); /* NOTE: No way to check if that's really a keyfile :-( */
+ g_return_val_if_fail(groupname != NULL, NULL);
+
+ if (!g_key_file_has_group(keyfile, groupname)) {
+ g_warning("Server specified but group '%s' was not found", groupname);
+ return NULL;
+ }
+
+ RdpServer * server = g_object_new(RDP_SERVER_TYPE, NULL);
+
+ if (g_key_file_has_key(keyfile, groupname, CONFIG_SERVER_NAME, NULL)) {
+ gchar * keyname = g_key_file_get_string(keyfile, groupname, CONFIG_SERVER_NAME, NULL);
+ server->parent.name = g_strdup(_(keyname));
+ g_free(keyname);
+ }
+
+ if (g_key_file_has_key(keyfile, groupname, CONFIG_SERVER_URI, NULL)) {
+ server->parent.uri = g_key_file_get_string(keyfile, groupname, CONFIG_SERVER_URI, NULL);
+ }
+
+ return SERVER(server);
+}
+
+/* Build the RDP server from information in the JSON object */
+Server *
+rdp_server_new_from_json (JsonObject * object)
+{
+ RdpServer * server = g_object_new(RDP_SERVER_TYPE, NULL);
+
+ if (json_object_has_member(object, JSON_SERVER_NAME)) {
+ JsonNode * node = json_object_get_member(object, JSON_SERVER_NAME);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_STRING) {
+ const gchar * name = json_node_get_string(node);
+ server->parent.name = g_strdup(name);
+ }
+ }
+
+ if (json_object_has_member(object, JSON_URI)) {
+ JsonNode * node = json_object_get_member(object, JSON_URI);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_STRING) {
+ const gchar * uri = json_node_get_string(node);
+ server->parent.uri = g_strdup(uri);
+ }
+ }
+
+ if (json_object_has_member(object, JSON_USERNAME)) {
+ JsonNode * node = json_object_get_member(object, JSON_USERNAME);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_STRING) {
+ const gchar * username = json_node_get_string(node);
+ server->username = g_strdup(username);
+ }
+ }
+
+ if (json_object_has_member(object, JSON_PASSWORD)) {
+ JsonNode * node = json_object_get_member(object, JSON_PASSWORD);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_STRING) {
+ const gchar * password = json_node_get_string(node);
+ server->password = g_strdup(password);
+ mlock(server->password, strlen(server->password));
+ }
+ }
+
+ if (json_object_has_member(object, JSON_DOMAIN)) {
+ JsonNode * node = json_object_get_member(object, JSON_DOMAIN);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_STRING) {
+ const gchar * domain = json_node_get_string(node);
+ server->domain = g_strdup(domain);
+ }
+ }
+
+ if (json_object_has_member(object, JSON_DOMAIN_REQ)) {
+ JsonNode * node = json_object_get_member(object, JSON_DOMAIN_REQ);
+ if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE && json_node_get_value_type(node) == G_TYPE_BOOLEAN) {
+ server->domain_required = json_node_get_boolean(node);
+ }
+ }
+
+ return SERVER(server);
+}
diff --git a/src/rdp-server.h b/src/rdp-server.h
new file mode 100644
index 0000000..297c8ef
--- /dev/null
+++ b/src/rdp-server.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#ifndef __RDP_SERVER_H__
+#define __RDP_SERVER_H__
+
+#include <glib-object.h>
+#include <json-glib/json-glib.h>
+#include "server.h"
+
+G_BEGIN_DECLS
+
+#define RDP_SERVER_TYPE (rdp_server_get_type ())
+#define RDP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), RDP_SERVER_TYPE, RdpServer))
+#define RDP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), RDP_SERVER_TYPE, RdpServerClass))
+#define IS_RDP_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), RDP_SERVER_TYPE))
+#define IS_RDP_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), RDP_SERVER_TYPE))
+#define RDP_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), RDP_SERVER_TYPE, RdpServerClass))
+
+typedef struct _RdpServer RdpServer;
+typedef struct _RdpServerClass RdpServerClass;
+
+struct _RdpServerClass {
+ ServerClass parent_class;
+};
+
+struct _RdpServer {
+ Server parent;
+
+ gchar * username;
+ gchar * password;
+ gchar * domain;
+ gboolean domain_required;
+};
+
+GType rdp_server_get_type (void);
+Server * rdp_server_new_from_keyfile (GKeyFile * keyfile, const gchar * name);
+Server * rdp_server_new_from_json (JsonObject * object);
+
+G_END_DECLS
+
+#endif
diff --git a/src/remote-login.c b/src/remote-login.c
new file mode 100644
index 0000000..35a85d1
--- /dev/null
+++ b/src/remote-login.c
@@ -0,0 +1,2244 @@
+/*
+ * Generated by gdbus-codegen 2.33.12. DO NOT EDIT.
+ *
+ * The license of this code is the same as for the source it was derived from.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "remote-login.h"
+
+#include <string.h>
+#ifdef G_OS_UNIX
+# include <gio/gunixfdlist.h>
+#endif
+
+typedef struct
+{
+ GDBusArgInfo parent_struct;
+ gboolean use_gvariant;
+} _ExtendedGDBusArgInfo;
+
+typedef struct
+{
+ GDBusMethodInfo parent_struct;
+ const gchar *signal_name;
+ gboolean pass_fdlist;
+} _ExtendedGDBusMethodInfo;
+
+typedef struct
+{
+ GDBusSignalInfo parent_struct;
+ const gchar *signal_name;
+} _ExtendedGDBusSignalInfo;
+
+typedef struct
+{
+ GDBusPropertyInfo parent_struct;
+ const gchar *hyphen_name;
+ gboolean use_gvariant;
+} _ExtendedGDBusPropertyInfo;
+
+typedef struct
+{
+ GDBusInterfaceInfo parent_struct;
+ const gchar *hyphen_name;
+} _ExtendedGDBusInterfaceInfo;
+
+typedef struct
+{
+ const _ExtendedGDBusPropertyInfo *info;
+ guint prop_id;
+ GValue orig_value; /* the value before the change */
+} ChangedProperty;
+
+static void
+_changed_property_free (ChangedProperty *data)
+{
+ g_value_unset (&data->orig_value);
+ g_free (data);
+}
+
+static gboolean
+_g_strv_equal0 (gchar **a, gchar **b)
+{
+ gboolean ret = FALSE;
+ guint n;
+ if (a == NULL && b == NULL)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ if (a == NULL || b == NULL)
+ goto out;
+ if (g_strv_length (a) != g_strv_length (b))
+ goto out;
+ for (n = 0; a[n] != NULL; n++)
+ if (g_strcmp0 (a[n], b[n]) != 0)
+ goto out;
+ ret = TRUE;
+out:
+ return ret;
+}
+
+static gboolean
+_g_variant_equal0 (GVariant *a, GVariant *b)
+{
+ gboolean ret = FALSE;
+ if (a == NULL && b == NULL)
+ {
+ ret = TRUE;
+ goto out;
+ }
+ if (a == NULL || b == NULL)
+ goto out;
+ ret = g_variant_equal (a, b);
+out:
+ return ret;
+}
+
+G_GNUC_UNUSED static gboolean
+_g_value_equal (const GValue *a, const GValue *b)
+{
+ gboolean ret = FALSE;
+ g_assert (G_VALUE_TYPE (a) == G_VALUE_TYPE (b));
+ switch (G_VALUE_TYPE (a))
+ {
+ case G_TYPE_BOOLEAN:
+ ret = (g_value_get_boolean (a) == g_value_get_boolean (b));
+ break;
+ case G_TYPE_UCHAR:
+ ret = (g_value_get_uchar (a) == g_value_get_uchar (b));
+ break;
+ case G_TYPE_INT:
+ ret = (g_value_get_int (a) == g_value_get_int (b));
+ break;
+ case G_TYPE_UINT:
+ ret = (g_value_get_uint (a) == g_value_get_uint (b));
+ break;
+ case G_TYPE_INT64:
+ ret = (g_value_get_int64 (a) == g_value_get_int64 (b));
+ break;
+ case G_TYPE_UINT64:
+ ret = (g_value_get_uint64 (a) == g_value_get_uint64 (b));
+ break;
+ case G_TYPE_DOUBLE:
+ {
+ /* Avoid -Wfloat-equal warnings by doing a direct bit compare */
+ gdouble da = g_value_get_double (a);
+ gdouble db = g_value_get_double (b);
+ ret = memcmp (&da, &db, sizeof (gdouble)) == 0;
+ }
+ break;
+ case G_TYPE_STRING:
+ ret = (g_strcmp0 (g_value_get_string (a), g_value_get_string (b)) == 0);
+ break;
+ case G_TYPE_VARIANT:
+ ret = _g_variant_equal0 (g_value_get_variant (a), g_value_get_variant (b));
+ break;
+ default:
+ if (G_VALUE_TYPE (a) == G_TYPE_STRV)
+ ret = _g_strv_equal0 (g_value_get_boxed (a), g_value_get_boxed (b));
+ else
+ g_critical ("_g_value_equal() does not handle type %s", g_type_name (G_VALUE_TYPE (a)));
+ break;
+ }
+ return ret;
+}
+
+/* ------------------------------------------------------------------------
+ * Code for interface com.canonical.RemoteLogin
+ * ------------------------------------------------------------------------
+ */
+
+/**
+ * SECTION:RemoteLogin
+ * @title: RemoteLogin
+ * @short_description: Generated C code for the com.canonical.RemoteLogin D-Bus interface
+ *
+ * This section contains code for working with the <link linkend="gdbus-interface-com-canonical-RemoteLogin.top_of_page">com.canonical.RemoteLogin</link> D-Bus interface in C.
+ */
+
+/* ---- Introspection data for com.canonical.RemoteLogin ---- */
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_get_servers_OUT_ARG_serverList =
+{
+ {
+ -1,
+ (gchar *) "serverList",
+ (gchar *) "a(sssba(sbva{sv})a(si))",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _remote_login_method_info_get_servers_OUT_ARG_pointers[] =
+{
+ &_remote_login_method_info_get_servers_OUT_ARG_serverList,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _remote_login_method_info_get_servers =
+{
+ {
+ -1,
+ (gchar *) "GetServers",
+ NULL,
+ (GDBusArgInfo **) &_remote_login_method_info_get_servers_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-get-servers",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_get_servers_for_login_IN_ARG_uri =
+{
+ {
+ -1,
+ (gchar *) "uri",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_get_servers_for_login_IN_ARG_emailAddress =
+{
+ {
+ -1,
+ (gchar *) "emailAddress",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_get_servers_for_login_IN_ARG_password =
+{
+ {
+ -1,
+ (gchar *) "password",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_get_servers_for_login_IN_ARG_allowCache =
+{
+ {
+ -1,
+ (gchar *) "allowCache",
+ (gchar *) "b",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _remote_login_method_info_get_servers_for_login_IN_ARG_pointers[] =
+{
+ &_remote_login_method_info_get_servers_for_login_IN_ARG_uri,
+ &_remote_login_method_info_get_servers_for_login_IN_ARG_emailAddress,
+ &_remote_login_method_info_get_servers_for_login_IN_ARG_password,
+ &_remote_login_method_info_get_servers_for_login_IN_ARG_allowCache,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_get_servers_for_login_OUT_ARG_loginSuccess =
+{
+ {
+ -1,
+ (gchar *) "loginSuccess",
+ (gchar *) "b",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_get_servers_for_login_OUT_ARG_dataType =
+{
+ {
+ -1,
+ (gchar *) "dataType",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_get_servers_for_login_OUT_ARG_serverList =
+{
+ {
+ -1,
+ (gchar *) "serverList",
+ (gchar *) "a(sssba(sbva{sv})a(si))",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _remote_login_method_info_get_servers_for_login_OUT_ARG_pointers[] =
+{
+ &_remote_login_method_info_get_servers_for_login_OUT_ARG_loginSuccess,
+ &_remote_login_method_info_get_servers_for_login_OUT_ARG_dataType,
+ &_remote_login_method_info_get_servers_for_login_OUT_ARG_serverList,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _remote_login_method_info_get_servers_for_login =
+{
+ {
+ -1,
+ (gchar *) "GetServersForLogin",
+ (GDBusArgInfo **) &_remote_login_method_info_get_servers_for_login_IN_ARG_pointers,
+ (GDBusArgInfo **) &_remote_login_method_info_get_servers_for_login_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-get-servers-for-login",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_get_cached_domains_for_server_IN_ARG_uri =
+{
+ {
+ -1,
+ (gchar *) "uri",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _remote_login_method_info_get_cached_domains_for_server_IN_ARG_pointers[] =
+{
+ &_remote_login_method_info_get_cached_domains_for_server_IN_ARG_uri,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_get_cached_domains_for_server_OUT_ARG_domains =
+{
+ {
+ -1,
+ (gchar *) "domains",
+ (gchar *) "as",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _remote_login_method_info_get_cached_domains_for_server_OUT_ARG_pointers[] =
+{
+ &_remote_login_method_info_get_cached_domains_for_server_OUT_ARG_domains,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _remote_login_method_info_get_cached_domains_for_server =
+{
+ {
+ -1,
+ (gchar *) "GetCachedDomainsForServer",
+ (GDBusArgInfo **) &_remote_login_method_info_get_cached_domains_for_server_IN_ARG_pointers,
+ (GDBusArgInfo **) &_remote_login_method_info_get_cached_domains_for_server_OUT_ARG_pointers,
+ NULL
+ },
+ "handle-get-cached-domains-for-server",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_set_applications_for_server_IN_ARG_uccsUri =
+{
+ {
+ -1,
+ (gchar *) "uccsUri",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_set_applications_for_server_IN_ARG_serverUri =
+{
+ {
+ -1,
+ (gchar *) "serverUri",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_set_applications_for_server_IN_ARG_applications =
+{
+ {
+ -1,
+ (gchar *) "applications",
+ (gchar *) "a(si)",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _remote_login_method_info_set_applications_for_server_IN_ARG_pointers[] =
+{
+ &_remote_login_method_info_set_applications_for_server_IN_ARG_uccsUri,
+ &_remote_login_method_info_set_applications_for_server_IN_ARG_serverUri,
+ &_remote_login_method_info_set_applications_for_server_IN_ARG_applications,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _remote_login_method_info_set_applications_for_server =
+{
+ {
+ -1,
+ (gchar *) "SetApplicationsForServer",
+ (GDBusArgInfo **) &_remote_login_method_info_set_applications_for_server_IN_ARG_pointers,
+ NULL,
+ NULL
+ },
+ "handle-set-applications-for-server",
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_set_last_used_server_IN_ARG_uccsUri =
+{
+ {
+ -1,
+ (gchar *) "uccsUri",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_method_info_set_last_used_server_IN_ARG_serverUri =
+{
+ {
+ -1,
+ (gchar *) "serverUri",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _remote_login_method_info_set_last_used_server_IN_ARG_pointers[] =
+{
+ &_remote_login_method_info_set_last_used_server_IN_ARG_uccsUri,
+ &_remote_login_method_info_set_last_used_server_IN_ARG_serverUri,
+ NULL
+};
+
+static const _ExtendedGDBusMethodInfo _remote_login_method_info_set_last_used_server =
+{
+ {
+ -1,
+ (gchar *) "SetLastUsedServer",
+ (GDBusArgInfo **) &_remote_login_method_info_set_last_used_server_IN_ARG_pointers,
+ NULL,
+ NULL
+ },
+ "handle-set-last-used-server",
+ FALSE
+};
+
+static const _ExtendedGDBusMethodInfo * const _remote_login_method_info_pointers[] =
+{
+ &_remote_login_method_info_get_servers,
+ &_remote_login_method_info_get_servers_for_login,
+ &_remote_login_method_info_get_cached_domains_for_server,
+ &_remote_login_method_info_set_applications_for_server,
+ &_remote_login_method_info_set_last_used_server,
+ NULL
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_signal_info_servers_updated_ARG_serverList =
+{
+ {
+ -1,
+ (gchar *) "serverList",
+ (gchar *) "a(sssba(sbva{sv})a(si))",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _remote_login_signal_info_servers_updated_ARG_pointers[] =
+{
+ &_remote_login_signal_info_servers_updated_ARG_serverList,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _remote_login_signal_info_servers_updated =
+{
+ {
+ -1,
+ (gchar *) "ServersUpdated",
+ (GDBusArgInfo **) &_remote_login_signal_info_servers_updated_ARG_pointers,
+ NULL
+ },
+ "servers-updated"
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_signal_info_login_servers_updated_ARG_uri =
+{
+ {
+ -1,
+ (gchar *) "uri",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_signal_info_login_servers_updated_ARG_emailAddress =
+{
+ {
+ -1,
+ (gchar *) "emailAddress",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_signal_info_login_servers_updated_ARG_dataType =
+{
+ {
+ -1,
+ (gchar *) "dataType",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_signal_info_login_servers_updated_ARG_serverList =
+{
+ {
+ -1,
+ (gchar *) "serverList",
+ (gchar *) "a(sssba(sbva{sv})a(si))",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _remote_login_signal_info_login_servers_updated_ARG_pointers[] =
+{
+ &_remote_login_signal_info_login_servers_updated_ARG_uri,
+ &_remote_login_signal_info_login_servers_updated_ARG_emailAddress,
+ &_remote_login_signal_info_login_servers_updated_ARG_dataType,
+ &_remote_login_signal_info_login_servers_updated_ARG_serverList,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _remote_login_signal_info_login_servers_updated =
+{
+ {
+ -1,
+ (gchar *) "LoginServersUpdated",
+ (GDBusArgInfo **) &_remote_login_signal_info_login_servers_updated_ARG_pointers,
+ NULL
+ },
+ "login-servers-updated"
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_signal_info_login_changed_ARG_uri =
+{
+ {
+ -1,
+ (gchar *) "uri",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo _remote_login_signal_info_login_changed_ARG_emailAddress =
+{
+ {
+ -1,
+ (gchar *) "emailAddress",
+ (gchar *) "s",
+ NULL
+ },
+ FALSE
+};
+
+static const _ExtendedGDBusArgInfo * const _remote_login_signal_info_login_changed_ARG_pointers[] =
+{
+ &_remote_login_signal_info_login_changed_ARG_uri,
+ &_remote_login_signal_info_login_changed_ARG_emailAddress,
+ NULL
+};
+
+static const _ExtendedGDBusSignalInfo _remote_login_signal_info_login_changed =
+{
+ {
+ -1,
+ (gchar *) "LoginChanged",
+ (GDBusArgInfo **) &_remote_login_signal_info_login_changed_ARG_pointers,
+ NULL
+ },
+ "login-changed"
+};
+
+static const _ExtendedGDBusSignalInfo * const _remote_login_signal_info_pointers[] =
+{
+ &_remote_login_signal_info_servers_updated,
+ &_remote_login_signal_info_login_servers_updated,
+ &_remote_login_signal_info_login_changed,
+ NULL
+};
+
+static const _ExtendedGDBusInterfaceInfo _remote_login_interface_info =
+{
+ {
+ -1,
+ (gchar *) "com.canonical.RemoteLogin",
+ (GDBusMethodInfo **) &_remote_login_method_info_pointers,
+ (GDBusSignalInfo **) &_remote_login_signal_info_pointers,
+ NULL,
+ NULL
+ },
+ "remote-login",
+};
+
+
+/**
+ * remote_login_interface_info:
+ *
+ * Gets a machine-readable description of the <link linkend="gdbus-interface-com-canonical-RemoteLogin.top_of_page">com.canonical.RemoteLogin</link> D-Bus interface.
+ *
+ * Returns: (transfer none): A #GDBusInterfaceInfo. Do not free.
+ */
+GDBusInterfaceInfo *
+remote_login_interface_info (void)
+{
+ return (GDBusInterfaceInfo *) &_remote_login_interface_info.parent_struct;
+}
+
+/**
+ * remote_login_override_properties:
+ * @klass: The class structure for a #GObject<!-- -->-derived class.
+ * @property_id_begin: The property id to assign to the first overridden property.
+ *
+ * Overrides all #GObject properties in the #RemoteLogin interface for a concrete class.
+ * The properties are overridden in the order they are defined.
+ *
+ * Returns: The last property id.
+ */
+guint
+remote_login_override_properties (GObjectClass *klass, guint property_id_begin)
+{
+ return property_id_begin - 1;
+}
+
+
+
+/**
+ * RemoteLogin:
+ *
+ * Abstract interface type for the D-Bus interface <link linkend="gdbus-interface-com-canonical-RemoteLogin.top_of_page">com.canonical.RemoteLogin</link>.
+ */
+
+/**
+ * RemoteLoginIface:
+ * @parent_iface: The parent interface.
+ * @handle_get_cached_domains_for_server: Handler for the #RemoteLogin::handle-get-cached-domains-for-server signal.
+ * @handle_get_servers: Handler for the #RemoteLogin::handle-get-servers signal.
+ * @handle_get_servers_for_login: Handler for the #RemoteLogin::handle-get-servers-for-login signal.
+ * @handle_set_applications_for_server: Handler for the #RemoteLogin::handle-set-applications-for-server signal.
+ * @handle_set_last_used_server: Handler for the #RemoteLogin::handle-set-last-used-server signal.
+ * @login_changed: Handler for the #RemoteLogin::login-changed signal.
+ * @login_servers_updated: Handler for the #RemoteLogin::login-servers-updated signal.
+ * @servers_updated: Handler for the #RemoteLogin::servers-updated signal.
+ *
+ * Virtual table for the D-Bus interface <link linkend="gdbus-interface-com-canonical-RemoteLogin.top_of_page">com.canonical.RemoteLogin</link>.
+ */
+
+static void
+remote_login_default_init (RemoteLoginIface *iface)
+{
+ /* GObject signals for incoming D-Bus method calls: */
+ /**
+ * RemoteLogin::handle-get-servers:
+ * @object: A #RemoteLogin.
+ * @invocation: A #GDBusMethodInvocation.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetServers">GetServers()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call remote_login_complete_get_servers() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-get-servers",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (RemoteLoginIface, handle_get_servers),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 1,
+ G_TYPE_DBUS_METHOD_INVOCATION);
+
+ /**
+ * RemoteLogin::handle-get-servers-for-login:
+ * @object: A #RemoteLogin.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_uri: Argument passed by remote caller.
+ * @arg_emailAddress: Argument passed by remote caller.
+ * @arg_password: Argument passed by remote caller.
+ * @arg_allowCache: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetServersForLogin">GetServersForLogin()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call remote_login_complete_get_servers_for_login() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-get-servers-for-login",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (RemoteLoginIface, handle_get_servers_for_login),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 5,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_BOOLEAN);
+
+ /**
+ * RemoteLogin::handle-get-cached-domains-for-server:
+ * @object: A #RemoteLogin.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_uri: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetCachedDomainsForServer">GetCachedDomainsForServer()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call remote_login_complete_get_cached_domains_for_server() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-get-cached-domains-for-server",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (RemoteLoginIface, handle_get_cached_domains_for_server),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 2,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING);
+
+ /**
+ * RemoteLogin::handle-set-applications-for-server:
+ * @object: A #RemoteLogin.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_uccsUri: Argument passed by remote caller.
+ * @arg_serverUri: Argument passed by remote caller.
+ * @arg_applications: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-com-canonical-RemoteLogin.SetApplicationsForServer">SetApplicationsForServer()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call remote_login_complete_set_applications_for_server() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-set-applications-for-server",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (RemoteLoginIface, handle_set_applications_for_server),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 4,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_VARIANT);
+
+ /**
+ * RemoteLogin::handle-set-last-used-server:
+ * @object: A #RemoteLogin.
+ * @invocation: A #GDBusMethodInvocation.
+ * @arg_uccsUri: Argument passed by remote caller.
+ * @arg_serverUri: Argument passed by remote caller.
+ *
+ * Signal emitted when a remote caller is invoking the <link linkend="gdbus-method-com-canonical-RemoteLogin.SetLastUsedServer">SetLastUsedServer()</link> D-Bus method.
+ *
+ * If a signal handler returns %TRUE, it means the signal handler will handle the invocation (e.g. take a reference to @invocation and eventually call remote_login_complete_set_last_used_server() or e.g. g_dbus_method_invocation_return_error() on it) and no order signal handlers will run. If no signal handler handles the invocation, the %G_DBUS_ERROR_UNKNOWN_METHOD error is returned.
+ *
+ * Returns: %TRUE if the invocation was handled, %FALSE to let other signal handlers run.
+ */
+ g_signal_new ("handle-set-last-used-server",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (RemoteLoginIface, handle_set_last_used_server),
+ g_signal_accumulator_true_handled,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_BOOLEAN,
+ 3,
+ G_TYPE_DBUS_METHOD_INVOCATION, G_TYPE_STRING, G_TYPE_STRING);
+
+ /* GObject signals for received D-Bus signals: */
+ /**
+ * RemoteLogin::servers-updated:
+ * @object: A #RemoteLogin.
+ * @arg_serverList: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-com-canonical-RemoteLogin.ServersUpdated">"ServersUpdated"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("servers-updated",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (RemoteLoginIface, servers_updated),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 1, G_TYPE_VARIANT);
+
+ /**
+ * RemoteLogin::login-servers-updated:
+ * @object: A #RemoteLogin.
+ * @arg_uri: Argument.
+ * @arg_emailAddress: Argument.
+ * @arg_dataType: Argument.
+ * @arg_serverList: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-com-canonical-RemoteLogin.LoginServersUpdated">"LoginServersUpdated"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("login-servers-updated",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (RemoteLoginIface, login_servers_updated),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 4, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_VARIANT);
+
+ /**
+ * RemoteLogin::login-changed:
+ * @object: A #RemoteLogin.
+ * @arg_uri: Argument.
+ * @arg_emailAddress: Argument.
+ *
+ * On the client-side, this signal is emitted whenever the D-Bus signal <link linkend="gdbus-signal-com-canonical-RemoteLogin.LoginChanged">"LoginChanged"</link> is received.
+ *
+ * On the service-side, this signal can be used with e.g. g_signal_emit_by_name() to make the object emit the D-Bus signal.
+ */
+ g_signal_new ("login-changed",
+ G_TYPE_FROM_INTERFACE (iface),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (RemoteLoginIface, login_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_generic,
+ G_TYPE_NONE,
+ 2, G_TYPE_STRING, G_TYPE_STRING);
+
+}
+
+typedef RemoteLoginIface RemoteLoginInterface;
+G_DEFINE_INTERFACE (RemoteLogin, remote_login, G_TYPE_OBJECT);
+
+/**
+ * remote_login_emit_servers_updated:
+ * @object: A #RemoteLogin.
+ * @arg_serverList: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-com-canonical-RemoteLogin.ServersUpdated">"ServersUpdated"</link> D-Bus signal.
+ */
+void
+remote_login_emit_servers_updated (
+ RemoteLogin *object,
+ GVariant *arg_serverList)
+{
+ g_signal_emit_by_name (object, "servers-updated", arg_serverList);
+}
+
+/**
+ * remote_login_emit_login_servers_updated:
+ * @object: A #RemoteLogin.
+ * @arg_uri: Argument to pass with the signal.
+ * @arg_emailAddress: Argument to pass with the signal.
+ * @arg_dataType: Argument to pass with the signal.
+ * @arg_serverList: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-com-canonical-RemoteLogin.LoginServersUpdated">"LoginServersUpdated"</link> D-Bus signal.
+ */
+void
+remote_login_emit_login_servers_updated (
+ RemoteLogin *object,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress,
+ const gchar *arg_dataType,
+ GVariant *arg_serverList)
+{
+ g_signal_emit_by_name (object, "login-servers-updated", arg_uri, arg_emailAddress, arg_dataType, arg_serverList);
+}
+
+/**
+ * remote_login_emit_login_changed:
+ * @object: A #RemoteLogin.
+ * @arg_uri: Argument to pass with the signal.
+ * @arg_emailAddress: Argument to pass with the signal.
+ *
+ * Emits the <link linkend="gdbus-signal-com-canonical-RemoteLogin.LoginChanged">"LoginChanged"</link> D-Bus signal.
+ */
+void
+remote_login_emit_login_changed (
+ RemoteLogin *object,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress)
+{
+ g_signal_emit_by_name (object, "login-changed", arg_uri, arg_emailAddress);
+}
+
+/**
+ * remote_login_call_get_servers:
+ * @proxy: A #RemoteLoginProxy.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetServers">GetServers()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call remote_login_call_get_servers_finish() to get the result of the operation.
+ *
+ * See remote_login_call_get_servers_sync() for the synchronous, blocking version of this method.
+ */
+void
+remote_login_call_get_servers (
+ RemoteLogin *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "GetServers",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * remote_login_call_get_servers_finish:
+ * @proxy: A #RemoteLoginProxy.
+ * @out_serverList: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to remote_login_call_get_servers().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with remote_login_call_get_servers().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+remote_login_call_get_servers_finish (
+ RemoteLogin *proxy,
+ GVariant **out_serverList,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(@a(sssba(sbva{sv})a(si)))",
+ out_serverList);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * remote_login_call_get_servers_sync:
+ * @proxy: A #RemoteLoginProxy.
+ * @out_serverList: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetServers">GetServers()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See remote_login_call_get_servers() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+remote_login_call_get_servers_sync (
+ RemoteLogin *proxy,
+ GVariant **out_serverList,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "GetServers",
+ g_variant_new ("()"),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(@a(sssba(sbva{sv})a(si)))",
+ out_serverList);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * remote_login_call_get_servers_for_login:
+ * @proxy: A #RemoteLoginProxy.
+ * @arg_uri: Argument to pass with the method invocation.
+ * @arg_emailAddress: Argument to pass with the method invocation.
+ * @arg_password: Argument to pass with the method invocation.
+ * @arg_allowCache: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetServersForLogin">GetServersForLogin()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call remote_login_call_get_servers_for_login_finish() to get the result of the operation.
+ *
+ * See remote_login_call_get_servers_for_login_sync() for the synchronous, blocking version of this method.
+ */
+void
+remote_login_call_get_servers_for_login (
+ RemoteLogin *proxy,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress,
+ const gchar *arg_password,
+ gboolean arg_allowCache,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "GetServersForLogin",
+ g_variant_new ("(sssb)",
+ arg_uri,
+ arg_emailAddress,
+ arg_password,
+ arg_allowCache),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * remote_login_call_get_servers_for_login_finish:
+ * @proxy: A #RemoteLoginProxy.
+ * @out_loginSuccess: (out): Return location for return parameter or %NULL to ignore.
+ * @out_dataType: (out): Return location for return parameter or %NULL to ignore.
+ * @out_serverList: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to remote_login_call_get_servers_for_login().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with remote_login_call_get_servers_for_login().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+remote_login_call_get_servers_for_login_finish (
+ RemoteLogin *proxy,
+ gboolean *out_loginSuccess,
+ gchar **out_dataType,
+ GVariant **out_serverList,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(bs@a(sssba(sbva{sv})a(si)))",
+ out_loginSuccess,
+ out_dataType,
+ out_serverList);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * remote_login_call_get_servers_for_login_sync:
+ * @proxy: A #RemoteLoginProxy.
+ * @arg_uri: Argument to pass with the method invocation.
+ * @arg_emailAddress: Argument to pass with the method invocation.
+ * @arg_password: Argument to pass with the method invocation.
+ * @arg_allowCache: Argument to pass with the method invocation.
+ * @out_loginSuccess: (out): Return location for return parameter or %NULL to ignore.
+ * @out_dataType: (out): Return location for return parameter or %NULL to ignore.
+ * @out_serverList: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetServersForLogin">GetServersForLogin()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See remote_login_call_get_servers_for_login() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+remote_login_call_get_servers_for_login_sync (
+ RemoteLogin *proxy,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress,
+ const gchar *arg_password,
+ gboolean arg_allowCache,
+ gboolean *out_loginSuccess,
+ gchar **out_dataType,
+ GVariant **out_serverList,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "GetServersForLogin",
+ g_variant_new ("(sssb)",
+ arg_uri,
+ arg_emailAddress,
+ arg_password,
+ arg_allowCache),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(bs@a(sssba(sbva{sv})a(si)))",
+ out_loginSuccess,
+ out_dataType,
+ out_serverList);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * remote_login_call_get_cached_domains_for_server:
+ * @proxy: A #RemoteLoginProxy.
+ * @arg_uri: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetCachedDomainsForServer">GetCachedDomainsForServer()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call remote_login_call_get_cached_domains_for_server_finish() to get the result of the operation.
+ *
+ * See remote_login_call_get_cached_domains_for_server_sync() for the synchronous, blocking version of this method.
+ */
+void
+remote_login_call_get_cached_domains_for_server (
+ RemoteLogin *proxy,
+ const gchar *arg_uri,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "GetCachedDomainsForServer",
+ g_variant_new ("(s)",
+ arg_uri),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * remote_login_call_get_cached_domains_for_server_finish:
+ * @proxy: A #RemoteLoginProxy.
+ * @out_domains: (out): Return location for return parameter or %NULL to ignore.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to remote_login_call_get_cached_domains_for_server().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with remote_login_call_get_cached_domains_for_server().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+remote_login_call_get_cached_domains_for_server_finish (
+ RemoteLogin *proxy,
+ gchar ***out_domains,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(^as)",
+ out_domains);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * remote_login_call_get_cached_domains_for_server_sync:
+ * @proxy: A #RemoteLoginProxy.
+ * @arg_uri: Argument to pass with the method invocation.
+ * @out_domains: (out): Return location for return parameter or %NULL to ignore.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetCachedDomainsForServer">GetCachedDomainsForServer()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See remote_login_call_get_cached_domains_for_server() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+remote_login_call_get_cached_domains_for_server_sync (
+ RemoteLogin *proxy,
+ const gchar *arg_uri,
+ gchar ***out_domains,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "GetCachedDomainsForServer",
+ g_variant_new ("(s)",
+ arg_uri),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "(^as)",
+ out_domains);
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * remote_login_call_set_applications_for_server:
+ * @proxy: A #RemoteLoginProxy.
+ * @arg_uccsUri: Argument to pass with the method invocation.
+ * @arg_serverUri: Argument to pass with the method invocation.
+ * @arg_applications: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-com-canonical-RemoteLogin.SetApplicationsForServer">SetApplicationsForServer()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call remote_login_call_set_applications_for_server_finish() to get the result of the operation.
+ *
+ * See remote_login_call_set_applications_for_server_sync() for the synchronous, blocking version of this method.
+ */
+void
+remote_login_call_set_applications_for_server (
+ RemoteLogin *proxy,
+ const gchar *arg_uccsUri,
+ const gchar *arg_serverUri,
+ GVariant *arg_applications,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "SetApplicationsForServer",
+ g_variant_new ("(ss@a(si))",
+ arg_uccsUri,
+ arg_serverUri,
+ arg_applications),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * remote_login_call_set_applications_for_server_finish:
+ * @proxy: A #RemoteLoginProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to remote_login_call_set_applications_for_server().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with remote_login_call_set_applications_for_server().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+remote_login_call_set_applications_for_server_finish (
+ RemoteLogin *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * remote_login_call_set_applications_for_server_sync:
+ * @proxy: A #RemoteLoginProxy.
+ * @arg_uccsUri: Argument to pass with the method invocation.
+ * @arg_serverUri: Argument to pass with the method invocation.
+ * @arg_applications: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-com-canonical-RemoteLogin.SetApplicationsForServer">SetApplicationsForServer()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See remote_login_call_set_applications_for_server() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+remote_login_call_set_applications_for_server_sync (
+ RemoteLogin *proxy,
+ const gchar *arg_uccsUri,
+ const gchar *arg_serverUri,
+ GVariant *arg_applications,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "SetApplicationsForServer",
+ g_variant_new ("(ss@a(si))",
+ arg_uccsUri,
+ arg_serverUri,
+ arg_applications),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * remote_login_call_set_last_used_server:
+ * @proxy: A #RemoteLoginProxy.
+ * @arg_uccsUri: Argument to pass with the method invocation.
+ * @arg_serverUri: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously invokes the <link linkend="gdbus-method-com-canonical-RemoteLogin.SetLastUsedServer">SetLastUsedServer()</link> D-Bus method on @proxy.
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call remote_login_call_set_last_used_server_finish() to get the result of the operation.
+ *
+ * See remote_login_call_set_last_used_server_sync() for the synchronous, blocking version of this method.
+ */
+void
+remote_login_call_set_last_used_server (
+ RemoteLogin *proxy,
+ const gchar *arg_uccsUri,
+ const gchar *arg_serverUri,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_dbus_proxy_call (G_DBUS_PROXY (proxy),
+ "SetLastUsedServer",
+ g_variant_new ("(ss)",
+ arg_uccsUri,
+ arg_serverUri),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ callback,
+ user_data);
+}
+
+/**
+ * remote_login_call_set_last_used_server_finish:
+ * @proxy: A #RemoteLoginProxy.
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to remote_login_call_set_last_used_server().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes an operation started with remote_login_call_set_last_used_server().
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+remote_login_call_set_last_used_server_finish (
+ RemoteLogin *proxy,
+ GAsyncResult *res,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_finish (G_DBUS_PROXY (proxy), res, error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * remote_login_call_set_last_used_server_sync:
+ * @proxy: A #RemoteLoginProxy.
+ * @arg_uccsUri: Argument to pass with the method invocation.
+ * @arg_serverUri: Argument to pass with the method invocation.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL.
+ *
+ * Synchronously invokes the <link linkend="gdbus-method-com-canonical-RemoteLogin.SetLastUsedServer">SetLastUsedServer()</link> D-Bus method on @proxy. The calling thread is blocked until a reply is received.
+ *
+ * See remote_login_call_set_last_used_server() for the asynchronous version of this method.
+ *
+ * Returns: (skip): %TRUE if the call succeded, %FALSE if @error is set.
+ */
+gboolean
+remote_login_call_set_last_used_server_sync (
+ RemoteLogin *proxy,
+ const gchar *arg_uccsUri,
+ const gchar *arg_serverUri,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GVariant *_ret;
+ _ret = g_dbus_proxy_call_sync (G_DBUS_PROXY (proxy),
+ "SetLastUsedServer",
+ g_variant_new ("(ss)",
+ arg_uccsUri,
+ arg_serverUri),
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ cancellable,
+ error);
+ if (_ret == NULL)
+ goto _out;
+ g_variant_get (_ret,
+ "()");
+ g_variant_unref (_ret);
+_out:
+ return _ret != NULL;
+}
+
+/**
+ * remote_login_complete_get_servers:
+ * @object: A #RemoteLogin.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @serverList: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetServers">GetServers()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+remote_login_complete_get_servers (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation,
+ GVariant *serverList)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(@a(sssba(sbva{sv})a(si)))",
+ serverList));
+}
+
+/**
+ * remote_login_complete_get_servers_for_login:
+ * @object: A #RemoteLogin.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @loginSuccess: Parameter to return.
+ * @dataType: Parameter to return.
+ * @serverList: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetServersForLogin">GetServersForLogin()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+remote_login_complete_get_servers_for_login (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation,
+ gboolean loginSuccess,
+ const gchar *dataType,
+ GVariant *serverList)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(bs@a(sssba(sbva{sv})a(si)))",
+ loginSuccess,
+ dataType,
+ serverList));
+}
+
+/**
+ * remote_login_complete_get_cached_domains_for_server:
+ * @object: A #RemoteLogin.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ * @domains: Parameter to return.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-com-canonical-RemoteLogin.GetCachedDomainsForServer">GetCachedDomainsForServer()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+remote_login_complete_get_cached_domains_for_server (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *const *domains)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("(^as)",
+ domains));
+}
+
+/**
+ * remote_login_complete_set_applications_for_server:
+ * @object: A #RemoteLogin.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-com-canonical-RemoteLogin.SetApplicationsForServer">SetApplicationsForServer()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+remote_login_complete_set_applications_for_server (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/**
+ * remote_login_complete_set_last_used_server:
+ * @object: A #RemoteLogin.
+ * @invocation: (transfer full): A #GDBusMethodInvocation.
+ *
+ * Helper function used in service implementations to finish handling invocations of the <link linkend="gdbus-method-com-canonical-RemoteLogin.SetLastUsedServer">SetLastUsedServer()</link> D-Bus method. If you instead want to finish handling an invocation by returning an error, use g_dbus_method_invocation_return_error() or similar.
+ *
+ * This method will free @invocation, you cannot use it afterwards.
+ */
+void
+remote_login_complete_set_last_used_server (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation)
+{
+ g_dbus_method_invocation_return_value (invocation,
+ g_variant_new ("()"));
+}
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * RemoteLoginProxy:
+ *
+ * The #RemoteLoginProxy structure contains only private data and should only be accessed using the provided API.
+ */
+
+/**
+ * RemoteLoginProxyClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #RemoteLoginProxy.
+ */
+
+struct _RemoteLoginProxyPrivate
+{
+ GData *qdata;
+};
+
+static void remote_login_proxy_iface_init (RemoteLoginIface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (RemoteLoginProxy, remote_login_proxy, G_TYPE_DBUS_PROXY,
+ G_IMPLEMENT_INTERFACE (TYPE_REMOTE_LOGIN, remote_login_proxy_iface_init));
+
+static void
+remote_login_proxy_finalize (GObject *object)
+{
+ RemoteLoginProxy *proxy = REMOTE_LOGIN_PROXY (object);
+ g_datalist_clear (&proxy->priv->qdata);
+ G_OBJECT_CLASS (remote_login_proxy_parent_class)->finalize (object);
+}
+
+static void
+remote_login_proxy_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+}
+
+static void
+remote_login_proxy_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+}
+
+static void
+remote_login_proxy_g_signal (GDBusProxy *proxy,
+ const gchar *sender_name,
+ const gchar *signal_name,
+ GVariant *parameters)
+{
+ _ExtendedGDBusSignalInfo *info;
+ GVariantIter iter;
+ GVariant *child;
+ GValue *paramv;
+ guint num_params;
+ guint n;
+ guint signal_id;
+ info = (_ExtendedGDBusSignalInfo *) g_dbus_interface_info_lookup_signal ((GDBusInterfaceInfo *) &_remote_login_interface_info.parent_struct, signal_name);
+ if (info == NULL)
+ return;
+ num_params = g_variant_n_children (parameters);
+ paramv = g_new0 (GValue, num_params + 1);
+ g_value_init (&paramv[0], TYPE_REMOTE_LOGIN);
+ g_value_set_object (&paramv[0], proxy);
+ g_variant_iter_init (&iter, parameters);
+ n = 1;
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.args[n - 1];
+ if (arg_info->use_gvariant)
+ {
+ g_value_init (&paramv[n], G_TYPE_VARIANT);
+ g_value_set_variant (&paramv[n], child);
+ n++;
+ }
+ else
+ g_dbus_gvariant_to_gvalue (child, &paramv[n++]);
+ g_variant_unref (child);
+ }
+ signal_id = g_signal_lookup (info->signal_name, TYPE_REMOTE_LOGIN);
+ g_signal_emitv (paramv, signal_id, 0, NULL);
+ for (n = 0; n < num_params + 1; n++)
+ g_value_unset (&paramv[n]);
+ g_free (paramv);
+}
+
+static void
+remote_login_proxy_g_properties_changed (GDBusProxy *_proxy,
+ GVariant *changed_properties,
+ const gchar *const *invalidated_properties)
+{
+ RemoteLoginProxy *proxy = REMOTE_LOGIN_PROXY (_proxy);
+ guint n;
+ const gchar *key;
+ GVariantIter *iter;
+ _ExtendedGDBusPropertyInfo *info;
+ g_variant_get (changed_properties, "a{sv}", &iter);
+ while (g_variant_iter_next (iter, "{&sv}", &key, NULL))
+ {
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_remote_login_interface_info.parent_struct, key);
+ g_datalist_remove_data (&proxy->priv->qdata, key);
+ if (info != NULL)
+ g_object_notify (G_OBJECT (proxy), info->hyphen_name);
+ }
+ g_variant_iter_free (iter);
+ for (n = 0; invalidated_properties[n] != NULL; n++)
+ {
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_remote_login_interface_info.parent_struct, invalidated_properties[n]);
+ g_datalist_remove_data (&proxy->priv->qdata, invalidated_properties[n]);
+ if (info != NULL)
+ g_object_notify (G_OBJECT (proxy), info->hyphen_name);
+ }
+}
+
+static void
+remote_login_proxy_init (RemoteLoginProxy *proxy)
+{
+ proxy->priv = G_TYPE_INSTANCE_GET_PRIVATE (proxy, TYPE_REMOTE_LOGIN_PROXY, RemoteLoginProxyPrivate);
+ g_dbus_proxy_set_interface_info (G_DBUS_PROXY (proxy), remote_login_interface_info ());
+}
+
+static void
+remote_login_proxy_class_init (RemoteLoginProxyClass *klass)
+{
+ GObjectClass *gobject_class;
+ GDBusProxyClass *proxy_class;
+
+ g_type_class_add_private (klass, sizeof (RemoteLoginProxyPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = remote_login_proxy_finalize;
+ gobject_class->get_property = remote_login_proxy_get_property;
+ gobject_class->set_property = remote_login_proxy_set_property;
+
+ proxy_class = G_DBUS_PROXY_CLASS (klass);
+ proxy_class->g_signal = remote_login_proxy_g_signal;
+ proxy_class->g_properties_changed = remote_login_proxy_g_properties_changed;
+
+}
+
+static void
+remote_login_proxy_iface_init (RemoteLoginIface *iface)
+{
+}
+
+/**
+ * remote_login_proxy_new:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ * Asynchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-com-canonical-RemoteLogin.top_of_page">com.canonical.RemoteLogin</link>. See g_dbus_proxy_new() for more details.
+ *
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call remote_login_proxy_new_finish() to get the result of the operation.
+ *
+ * See remote_login_proxy_new_sync() for the synchronous, blocking version of this constructor.
+ */
+void
+remote_login_proxy_new (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (TYPE_REMOTE_LOGIN_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "com.canonical.RemoteLogin", NULL);
+}
+
+/**
+ * remote_login_proxy_new_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to remote_login_proxy_new().
+ * @error: Return location for error or %NULL
+ *
+ * Finishes an operation started with remote_login_proxy_new().
+ *
+ * Returns: (transfer full) (type RemoteLoginProxy): The constructed proxy object or %NULL if @error is set.
+ */
+RemoteLogin *
+remote_login_proxy_new_finish (
+ GAsyncResult *res,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (res);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
+ g_object_unref (source_object);
+ if (ret != NULL)
+ return REMOTE_LOGIN (ret);
+ else
+ return NULL;
+}
+
+/**
+ * remote_login_proxy_new_sync:
+ * @connection: A #GDBusConnection.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: (allow-none): A bus name (well-known or unique) or %NULL if @connection is not a message bus connection.
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL
+ *
+ * Synchronously creates a proxy for the D-Bus interface <link linkend="gdbus-interface-com-canonical-RemoteLogin.top_of_page">com.canonical.RemoteLogin</link>. See g_dbus_proxy_new_sync() for more details.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * See remote_login_proxy_new() for the asynchronous version of this constructor.
+ *
+ * Returns: (transfer full) (type RemoteLoginProxy): The constructed proxy object or %NULL if @error is set.
+ */
+RemoteLogin *
+remote_login_proxy_new_sync (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInitable *ret;
+ ret = g_initable_new (TYPE_REMOTE_LOGIN_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-connection", connection, "g-object-path", object_path, "g-interface-name", "com.canonical.RemoteLogin", NULL);
+ if (ret != NULL)
+ return REMOTE_LOGIN (ret);
+ else
+ return NULL;
+}
+
+
+/**
+ * remote_login_proxy_new_for_bus:
+ * @bus_type: A #GBusType.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like remote_login_proxy_new() but takes a #GBusType instead of a #GDBusConnection.
+ *
+ * When the operation is finished, @callback will be invoked in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link> of the thread you are calling this method from.
+ * You can then call remote_login_proxy_new_for_bus_finish() to get the result of the operation.
+ *
+ * See remote_login_proxy_new_for_bus_sync() for the synchronous, blocking version of this constructor.
+ */
+void
+remote_login_proxy_new_for_bus (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ g_async_initable_new_async (TYPE_REMOTE_LOGIN_PROXY, G_PRIORITY_DEFAULT, cancellable, callback, user_data, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "com.canonical.RemoteLogin", NULL);
+}
+
+/**
+ * remote_login_proxy_new_for_bus_finish:
+ * @res: The #GAsyncResult obtained from the #GAsyncReadyCallback passed to remote_login_proxy_new_for_bus().
+ * @error: Return location for error or %NULL
+ *
+ * Finishes an operation started with remote_login_proxy_new_for_bus().
+ *
+ * Returns: (transfer full) (type RemoteLoginProxy): The constructed proxy object or %NULL if @error is set.
+ */
+RemoteLogin *
+remote_login_proxy_new_for_bus_finish (
+ GAsyncResult *res,
+ GError **error)
+{
+ GObject *ret;
+ GObject *source_object;
+ source_object = g_async_result_get_source_object (res);
+ ret = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), res, error);
+ g_object_unref (source_object);
+ if (ret != NULL)
+ return REMOTE_LOGIN (ret);
+ else
+ return NULL;
+}
+
+/**
+ * remote_login_proxy_new_for_bus_sync:
+ * @bus_type: A #GBusType.
+ * @flags: Flags from the #GDBusProxyFlags enumeration.
+ * @name: A bus name (well-known or unique).
+ * @object_path: An object path.
+ * @cancellable: (allow-none): A #GCancellable or %NULL.
+ * @error: Return location for error or %NULL
+ *
+ * Like remote_login_proxy_new_sync() but takes a #GBusType instead of a #GDBusConnection.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * See remote_login_proxy_new_for_bus() for the asynchronous version of this constructor.
+ *
+ * Returns: (transfer full) (type RemoteLoginProxy): The constructed proxy object or %NULL if @error is set.
+ */
+RemoteLogin *
+remote_login_proxy_new_for_bus_sync (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GInitable *ret;
+ ret = g_initable_new (TYPE_REMOTE_LOGIN_PROXY, cancellable, error, "g-flags", flags, "g-name", name, "g-bus-type", bus_type, "g-object-path", object_path, "g-interface-name", "com.canonical.RemoteLogin", NULL);
+ if (ret != NULL)
+ return REMOTE_LOGIN (ret);
+ else
+ return NULL;
+}
+
+
+/* ------------------------------------------------------------------------ */
+
+/**
+ * RemoteLoginSkeleton:
+ *
+ * The #RemoteLoginSkeleton structure contains only private data and should only be accessed using the provided API.
+ */
+
+/**
+ * RemoteLoginSkeletonClass:
+ * @parent_class: The parent class.
+ *
+ * Class structure for #RemoteLoginSkeleton.
+ */
+
+struct _RemoteLoginSkeletonPrivate
+{
+ GValue *properties;
+ GList *changed_properties;
+ GSource *changed_properties_idle_source;
+ GMainContext *context;
+ GMutex lock;
+};
+
+static void
+_remote_login_skeleton_handle_method_call (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *method_name,
+ GVariant *parameters,
+ GDBusMethodInvocation *invocation,
+ gpointer user_data)
+{
+ RemoteLoginSkeleton *skeleton = REMOTE_LOGIN_SKELETON (user_data);
+ _ExtendedGDBusMethodInfo *info;
+ GVariantIter iter;
+ GVariant *child;
+ GValue *paramv;
+ guint num_params;
+ guint num_extra;
+ guint n;
+ guint signal_id;
+ GValue return_value = G_VALUE_INIT;
+ info = (_ExtendedGDBusMethodInfo *) g_dbus_method_invocation_get_method_info (invocation);
+ g_assert (info != NULL);
+ num_params = g_variant_n_children (parameters);
+ num_extra = info->pass_fdlist ? 3 : 2; paramv = g_new0 (GValue, num_params + num_extra);
+ n = 0;
+ g_value_init (&paramv[n], TYPE_REMOTE_LOGIN);
+ g_value_set_object (&paramv[n++], skeleton);
+ g_value_init (&paramv[n], G_TYPE_DBUS_METHOD_INVOCATION);
+ g_value_set_object (&paramv[n++], invocation);
+ if (info->pass_fdlist)
+ {
+#ifdef G_OS_UNIX
+ g_value_init (&paramv[n], G_TYPE_UNIX_FD_LIST);
+ g_value_set_object (&paramv[n++], g_dbus_message_get_unix_fd_list (g_dbus_method_invocation_get_message (invocation)));
+#else
+ g_assert_not_reached ();
+#endif
+ }
+ g_variant_iter_init (&iter, parameters);
+ while ((child = g_variant_iter_next_value (&iter)) != NULL)
+ {
+ _ExtendedGDBusArgInfo *arg_info = (_ExtendedGDBusArgInfo *) info->parent_struct.in_args[n - num_extra];
+ if (arg_info->use_gvariant)
+ {
+ g_value_init (&paramv[n], G_TYPE_VARIANT);
+ g_value_set_variant (&paramv[n], child);
+ n++;
+ }
+ else
+ g_dbus_gvariant_to_gvalue (child, &paramv[n++]);
+ g_variant_unref (child);
+ }
+ signal_id = g_signal_lookup (info->signal_name, TYPE_REMOTE_LOGIN);
+ g_value_init (&return_value, G_TYPE_BOOLEAN);
+ g_signal_emitv (paramv, signal_id, 0, &return_value);
+ if (!g_value_get_boolean (&return_value))
+ g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD, "Method %s is not implemented on interface %s", method_name, interface_name);
+ g_value_unset (&return_value);
+ for (n = 0; n < num_params + num_extra; n++)
+ g_value_unset (&paramv[n]);
+ g_free (paramv);
+}
+
+static GVariant *
+_remote_login_skeleton_handle_get_property (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GError **error,
+ gpointer user_data)
+{
+ RemoteLoginSkeleton *skeleton = REMOTE_LOGIN_SKELETON (user_data);
+ GValue value = G_VALUE_INIT;
+ GParamSpec *pspec;
+ _ExtendedGDBusPropertyInfo *info;
+ GVariant *ret;
+ ret = NULL;
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_remote_login_interface_info.parent_struct, property_name);
+ g_assert (info != NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
+ if (pspec == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
+ }
+ else
+ {
+ g_value_init (&value, pspec->value_type);
+ g_object_get_property (G_OBJECT (skeleton), info->hyphen_name, &value);
+ ret = g_dbus_gvalue_to_gvariant (&value, G_VARIANT_TYPE (info->parent_struct.signature));
+ g_value_unset (&value);
+ }
+ return ret;
+}
+
+static gboolean
+_remote_login_skeleton_handle_set_property (
+ GDBusConnection *connection,
+ const gchar *sender,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *property_name,
+ GVariant *variant,
+ GError **error,
+ gpointer user_data)
+{
+ RemoteLoginSkeleton *skeleton = REMOTE_LOGIN_SKELETON (user_data);
+ GValue value = G_VALUE_INIT;
+ GParamSpec *pspec;
+ _ExtendedGDBusPropertyInfo *info;
+ gboolean ret;
+ ret = FALSE;
+ info = (_ExtendedGDBusPropertyInfo *) g_dbus_interface_info_lookup_property ((GDBusInterfaceInfo *) &_remote_login_interface_info.parent_struct, property_name);
+ g_assert (info != NULL);
+ pspec = g_object_class_find_property (G_OBJECT_GET_CLASS (skeleton), info->hyphen_name);
+ if (pspec == NULL)
+ {
+ g_set_error (error, G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS, "No property with name %s", property_name);
+ }
+ else
+ {
+ if (info->use_gvariant)
+ g_value_set_variant (&value, variant);
+ else
+ g_dbus_gvariant_to_gvalue (variant, &value);
+ g_object_set_property (G_OBJECT (skeleton), info->hyphen_name, &value);
+ g_value_unset (&value);
+ ret = TRUE;
+ }
+ return ret;
+}
+
+static const GDBusInterfaceVTable _remote_login_skeleton_vtable =
+{
+ _remote_login_skeleton_handle_method_call,
+ _remote_login_skeleton_handle_get_property,
+ _remote_login_skeleton_handle_set_property
+};
+
+static GDBusInterfaceInfo *
+remote_login_skeleton_dbus_interface_get_info (GDBusInterfaceSkeleton *skeleton)
+{
+ return remote_login_interface_info ();
+}
+
+static GDBusInterfaceVTable *
+remote_login_skeleton_dbus_interface_get_vtable (GDBusInterfaceSkeleton *skeleton)
+{
+ return (GDBusInterfaceVTable *) &_remote_login_skeleton_vtable;
+}
+
+static GVariant *
+remote_login_skeleton_dbus_interface_get_properties (GDBusInterfaceSkeleton *_skeleton)
+{
+ RemoteLoginSkeleton *skeleton = REMOTE_LOGIN_SKELETON (_skeleton);
+
+ GVariantBuilder builder;
+ guint n;
+ g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
+ if (_remote_login_interface_info.parent_struct.properties == NULL)
+ goto out;
+ for (n = 0; _remote_login_interface_info.parent_struct.properties[n] != NULL; n++)
+ {
+ GDBusPropertyInfo *info = _remote_login_interface_info.parent_struct.properties[n];
+ if (info->flags & G_DBUS_PROPERTY_INFO_FLAGS_READABLE)
+ {
+ GVariant *value;
+ value = _remote_login_skeleton_handle_get_property (g_dbus_interface_skeleton_get_connection (G_DBUS_INTERFACE_SKELETON (skeleton)), NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "com.canonical.RemoteLogin", info->name, NULL, skeleton);
+ if (value != NULL)
+ {
+ g_variant_take_ref (value);
+ g_variant_builder_add (&builder, "{sv}", info->name, value);
+ g_variant_unref (value);
+ }
+ }
+ }
+out:
+ return g_variant_builder_end (&builder);
+}
+
+static void
+remote_login_skeleton_dbus_interface_flush (GDBusInterfaceSkeleton *_skeleton)
+{
+}
+
+static void
+_remote_login_on_signal_servers_updated (
+ RemoteLogin *object,
+ GVariant *arg_serverList)
+{
+ RemoteLoginSkeleton *skeleton = REMOTE_LOGIN_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(@a(sssba(sbva{sv})a(si)))",
+ arg_serverList));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "com.canonical.RemoteLogin", "ServersUpdated",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void
+_remote_login_on_signal_login_servers_updated (
+ RemoteLogin *object,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress,
+ const gchar *arg_dataType,
+ GVariant *arg_serverList)
+{
+ RemoteLoginSkeleton *skeleton = REMOTE_LOGIN_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(sss@a(sssba(sbva{sv})a(si)))",
+ arg_uri,
+ arg_emailAddress,
+ arg_dataType,
+ arg_serverList));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "com.canonical.RemoteLogin", "LoginServersUpdated",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void
+_remote_login_on_signal_login_changed (
+ RemoteLogin *object,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress)
+{
+ RemoteLoginSkeleton *skeleton = REMOTE_LOGIN_SKELETON (object);
+
+ GList *connections, *l;
+ GVariant *signal_variant;
+ connections = g_dbus_interface_skeleton_get_connections (G_DBUS_INTERFACE_SKELETON (skeleton));
+
+ signal_variant = g_variant_ref_sink (g_variant_new ("(ss)",
+ arg_uri,
+ arg_emailAddress));
+ for (l = connections; l != NULL; l = l->next)
+ {
+ GDBusConnection *connection = l->data;
+ g_dbus_connection_emit_signal (connection,
+ NULL, g_dbus_interface_skeleton_get_object_path (G_DBUS_INTERFACE_SKELETON (skeleton)), "com.canonical.RemoteLogin", "LoginChanged",
+ signal_variant, NULL);
+ }
+ g_variant_unref (signal_variant);
+ g_list_free_full (connections, g_object_unref);
+}
+
+static void remote_login_skeleton_iface_init (RemoteLoginIface *iface);
+G_DEFINE_TYPE_WITH_CODE (RemoteLoginSkeleton, remote_login_skeleton, G_TYPE_DBUS_INTERFACE_SKELETON,
+ G_IMPLEMENT_INTERFACE (TYPE_REMOTE_LOGIN, remote_login_skeleton_iface_init));
+
+static void
+remote_login_skeleton_finalize (GObject *object)
+{
+ RemoteLoginSkeleton *skeleton = REMOTE_LOGIN_SKELETON (object);
+ g_list_free_full (skeleton->priv->changed_properties, (GDestroyNotify) _changed_property_free);
+ if (skeleton->priv->changed_properties_idle_source != NULL)
+ g_source_destroy (skeleton->priv->changed_properties_idle_source);
+ g_main_context_unref (skeleton->priv->context);
+ g_mutex_clear (&skeleton->priv->lock);
+ G_OBJECT_CLASS (remote_login_skeleton_parent_class)->finalize (object);
+}
+
+static void
+remote_login_skeleton_init (RemoteLoginSkeleton *skeleton)
+{
+ skeleton->priv = G_TYPE_INSTANCE_GET_PRIVATE (skeleton, TYPE_REMOTE_LOGIN_SKELETON, RemoteLoginSkeletonPrivate);
+ g_mutex_init (&skeleton->priv->lock);
+ skeleton->priv->context = g_main_context_ref_thread_default ();
+}
+
+static void
+remote_login_skeleton_class_init (RemoteLoginSkeletonClass *klass)
+{
+ GObjectClass *gobject_class;
+ GDBusInterfaceSkeletonClass *skeleton_class;
+
+ g_type_class_add_private (klass, sizeof (RemoteLoginSkeletonPrivate));
+
+ gobject_class = G_OBJECT_CLASS (klass);
+ gobject_class->finalize = remote_login_skeleton_finalize;
+
+ skeleton_class = G_DBUS_INTERFACE_SKELETON_CLASS (klass);
+ skeleton_class->get_info = remote_login_skeleton_dbus_interface_get_info;
+ skeleton_class->get_properties = remote_login_skeleton_dbus_interface_get_properties;
+ skeleton_class->flush = remote_login_skeleton_dbus_interface_flush;
+ skeleton_class->get_vtable = remote_login_skeleton_dbus_interface_get_vtable;
+}
+
+static void
+remote_login_skeleton_iface_init (RemoteLoginIface *iface)
+{
+ iface->servers_updated = _remote_login_on_signal_servers_updated;
+ iface->login_servers_updated = _remote_login_on_signal_login_servers_updated;
+ iface->login_changed = _remote_login_on_signal_login_changed;
+}
+
+/**
+ * remote_login_skeleton_new:
+ *
+ * Creates a skeleton object for the D-Bus interface <link linkend="gdbus-interface-com-canonical-RemoteLogin.top_of_page">com.canonical.RemoteLogin</link>.
+ *
+ * Returns: (transfer full) (type RemoteLoginSkeleton): The skeleton object.
+ */
+RemoteLogin *
+remote_login_skeleton_new (void)
+{
+ return REMOTE_LOGIN (g_object_new (TYPE_REMOTE_LOGIN_SKELETON, NULL));
+}
+
diff --git a/src/remote-login.h b/src/remote-login.h
new file mode 100644
index 0000000..6b0d229
--- /dev/null
+++ b/src/remote-login.h
@@ -0,0 +1,344 @@
+/*
+ * Generated by gdbus-codegen 2.33.12. DO NOT EDIT.
+ *
+ * The license of this code is the same as for the source it was derived from.
+ */
+
+#ifndef __REMOTE_LOGIN_H__
+#define __REMOTE_LOGIN_H__
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+
+/* ------------------------------------------------------------------------ */
+/* Declarations for com.canonical.RemoteLogin */
+
+#define TYPE_REMOTE_LOGIN (remote_login_get_type ())
+#define REMOTE_LOGIN(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_REMOTE_LOGIN, RemoteLogin))
+#define IS_REMOTE_LOGIN(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_REMOTE_LOGIN))
+#define REMOTE_LOGIN_GET_IFACE(o) (G_TYPE_INSTANCE_GET_INTERFACE ((o), TYPE_REMOTE_LOGIN, RemoteLoginIface))
+
+struct _RemoteLogin;
+typedef struct _RemoteLogin RemoteLogin;
+typedef struct _RemoteLoginIface RemoteLoginIface;
+
+struct _RemoteLoginIface
+{
+ GTypeInterface parent_iface;
+
+
+ gboolean (*handle_get_cached_domains_for_server) (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_uri);
+
+ gboolean (*handle_get_servers) (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation);
+
+ gboolean (*handle_get_servers_for_login) (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress,
+ const gchar *arg_password,
+ gboolean arg_allowCache);
+
+ gboolean (*handle_set_applications_for_server) (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_uccsUri,
+ const gchar *arg_serverUri,
+ GVariant *arg_applications);
+
+ gboolean (*handle_set_last_used_server) (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *arg_uccsUri,
+ const gchar *arg_serverUri);
+
+ void (*login_changed) (
+ RemoteLogin *object,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress);
+
+ void (*login_servers_updated) (
+ RemoteLogin *object,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress,
+ const gchar *arg_dataType,
+ GVariant *arg_serverList);
+
+ void (*servers_updated) (
+ RemoteLogin *object,
+ GVariant *arg_serverList);
+
+};
+
+GType remote_login_get_type (void) G_GNUC_CONST;
+
+GDBusInterfaceInfo *remote_login_interface_info (void);
+guint remote_login_override_properties (GObjectClass *klass, guint property_id_begin);
+
+
+/* D-Bus method call completion functions: */
+void remote_login_complete_get_servers (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation,
+ GVariant *serverList);
+
+void remote_login_complete_get_servers_for_login (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation,
+ gboolean loginSuccess,
+ const gchar *dataType,
+ GVariant *serverList);
+
+void remote_login_complete_get_cached_domains_for_server (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation,
+ const gchar *const *domains);
+
+void remote_login_complete_set_applications_for_server (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation);
+
+void remote_login_complete_set_last_used_server (
+ RemoteLogin *object,
+ GDBusMethodInvocation *invocation);
+
+
+
+/* D-Bus signal emissions functions: */
+void remote_login_emit_servers_updated (
+ RemoteLogin *object,
+ GVariant *arg_serverList);
+
+void remote_login_emit_login_servers_updated (
+ RemoteLogin *object,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress,
+ const gchar *arg_dataType,
+ GVariant *arg_serverList);
+
+void remote_login_emit_login_changed (
+ RemoteLogin *object,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress);
+
+
+
+/* D-Bus method calls: */
+void remote_login_call_get_servers (
+ RemoteLogin *proxy,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean remote_login_call_get_servers_finish (
+ RemoteLogin *proxy,
+ GVariant **out_serverList,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean remote_login_call_get_servers_sync (
+ RemoteLogin *proxy,
+ GVariant **out_serverList,
+ GCancellable *cancellable,
+ GError **error);
+
+void remote_login_call_get_servers_for_login (
+ RemoteLogin *proxy,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress,
+ const gchar *arg_password,
+ gboolean arg_allowCache,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean remote_login_call_get_servers_for_login_finish (
+ RemoteLogin *proxy,
+ gboolean *out_loginSuccess,
+ gchar **out_dataType,
+ GVariant **out_serverList,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean remote_login_call_get_servers_for_login_sync (
+ RemoteLogin *proxy,
+ const gchar *arg_uri,
+ const gchar *arg_emailAddress,
+ const gchar *arg_password,
+ gboolean arg_allowCache,
+ gboolean *out_loginSuccess,
+ gchar **out_dataType,
+ GVariant **out_serverList,
+ GCancellable *cancellable,
+ GError **error);
+
+void remote_login_call_get_cached_domains_for_server (
+ RemoteLogin *proxy,
+ const gchar *arg_uri,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean remote_login_call_get_cached_domains_for_server_finish (
+ RemoteLogin *proxy,
+ gchar ***out_domains,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean remote_login_call_get_cached_domains_for_server_sync (
+ RemoteLogin *proxy,
+ const gchar *arg_uri,
+ gchar ***out_domains,
+ GCancellable *cancellable,
+ GError **error);
+
+void remote_login_call_set_applications_for_server (
+ RemoteLogin *proxy,
+ const gchar *arg_uccsUri,
+ const gchar *arg_serverUri,
+ GVariant *arg_applications,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean remote_login_call_set_applications_for_server_finish (
+ RemoteLogin *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean remote_login_call_set_applications_for_server_sync (
+ RemoteLogin *proxy,
+ const gchar *arg_uccsUri,
+ const gchar *arg_serverUri,
+ GVariant *arg_applications,
+ GCancellable *cancellable,
+ GError **error);
+
+void remote_login_call_set_last_used_server (
+ RemoteLogin *proxy,
+ const gchar *arg_uccsUri,
+ const gchar *arg_serverUri,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+gboolean remote_login_call_set_last_used_server_finish (
+ RemoteLogin *proxy,
+ GAsyncResult *res,
+ GError **error);
+
+gboolean remote_login_call_set_last_used_server_sync (
+ RemoteLogin *proxy,
+ const gchar *arg_uccsUri,
+ const gchar *arg_serverUri,
+ GCancellable *cancellable,
+ GError **error);
+
+
+
+/* ---- */
+
+#define TYPE_REMOTE_LOGIN_PROXY (remote_login_proxy_get_type ())
+#define REMOTE_LOGIN_PROXY(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_REMOTE_LOGIN_PROXY, RemoteLoginProxy))
+#define REMOTE_LOGIN_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TYPE_REMOTE_LOGIN_PROXY, RemoteLoginProxyClass))
+#define REMOTE_LOGIN_PROXY_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_REMOTE_LOGIN_PROXY, RemoteLoginProxyClass))
+#define IS_REMOTE_LOGIN_PROXY(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_REMOTE_LOGIN_PROXY))
+#define IS_REMOTE_LOGIN_PROXY_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_REMOTE_LOGIN_PROXY))
+
+typedef struct _RemoteLoginProxy RemoteLoginProxy;
+typedef struct _RemoteLoginProxyClass RemoteLoginProxyClass;
+typedef struct _RemoteLoginProxyPrivate RemoteLoginProxyPrivate;
+
+struct _RemoteLoginProxy
+{
+ /*< private >*/
+ GDBusProxy parent_instance;
+ RemoteLoginProxyPrivate *priv;
+};
+
+struct _RemoteLoginProxyClass
+{
+ GDBusProxyClass parent_class;
+};
+
+GType remote_login_proxy_get_type (void) G_GNUC_CONST;
+
+void remote_login_proxy_new (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+RemoteLogin *remote_login_proxy_new_finish (
+ GAsyncResult *res,
+ GError **error);
+RemoteLogin *remote_login_proxy_new_sync (
+ GDBusConnection *connection,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error);
+
+void remote_login_proxy_new_for_bus (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+RemoteLogin *remote_login_proxy_new_for_bus_finish (
+ GAsyncResult *res,
+ GError **error);
+RemoteLogin *remote_login_proxy_new_for_bus_sync (
+ GBusType bus_type,
+ GDBusProxyFlags flags,
+ const gchar *name,
+ const gchar *object_path,
+ GCancellable *cancellable,
+ GError **error);
+
+
+/* ---- */
+
+#define TYPE_REMOTE_LOGIN_SKELETON (remote_login_skeleton_get_type ())
+#define REMOTE_LOGIN_SKELETON(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_REMOTE_LOGIN_SKELETON, RemoteLoginSkeleton))
+#define REMOTE_LOGIN_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TYPE_REMOTE_LOGIN_SKELETON, RemoteLoginSkeletonClass))
+#define REMOTE_LOGIN_SKELETON_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_REMOTE_LOGIN_SKELETON, RemoteLoginSkeletonClass))
+#define IS_REMOTE_LOGIN_SKELETON(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_REMOTE_LOGIN_SKELETON))
+#define IS_REMOTE_LOGIN_SKELETON_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_REMOTE_LOGIN_SKELETON))
+
+typedef struct _RemoteLoginSkeleton RemoteLoginSkeleton;
+typedef struct _RemoteLoginSkeletonClass RemoteLoginSkeletonClass;
+typedef struct _RemoteLoginSkeletonPrivate RemoteLoginSkeletonPrivate;
+
+struct _RemoteLoginSkeleton
+{
+ /*< private >*/
+ GDBusInterfaceSkeleton parent_instance;
+ RemoteLoginSkeletonPrivate *priv;
+};
+
+struct _RemoteLoginSkeletonClass
+{
+ GDBusInterfaceSkeletonClass parent_class;
+};
+
+GType remote_login_skeleton_get_type (void) G_GNUC_CONST;
+
+RemoteLogin *remote_login_skeleton_new (void);
+
+
+G_END_DECLS
+
+#endif /* __REMOTE_LOGIN_H__ */
diff --git a/src/server.c b/src/server.c
new file mode 100644
index 0000000..2f36898
--- /dev/null
+++ b/src/server.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "server.h"
+#include "defines.h"
+#include "citrix-server.h"
+#include "rdp-server.h"
+#include "uccs-server.h"
+
+static void server_class_init (ServerClass *klass);
+static void server_init (Server *self);
+static void server_dispose (GObject *object);
+static void server_finalize (GObject *object);
+
+/* Signals */
+enum {
+ STATE_CHANGED,
+ LAST_SIGNAL
+};
+
+G_DEFINE_TYPE (Server, server, G_TYPE_OBJECT);
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void
+server_class_init (ServerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = server_dispose;
+ object_class->finalize = server_finalize;
+
+ signals[STATE_CHANGED] = g_signal_new(SERVER_SIGNAL_STATE_CHANGED,
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET(ServerClass, state_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__INT,
+ G_TYPE_NONE, 1, G_TYPE_INT, G_TYPE_NONE);
+
+ return;
+}
+
+static void
+server_init (Server *self)
+{
+ self->name = NULL;
+ self->uri = NULL;
+ self->last_used = FALSE;
+ self->state = SERVER_STATE_ALLGOOD;
+
+ return;
+}
+
+static void
+server_dispose (GObject *object)
+{
+
+ G_OBJECT_CLASS (server_parent_class)->dispose (object);
+ return;
+}
+
+static void
+server_finalize (GObject *object)
+{
+ Server * server = SERVER(object);
+
+ g_free(server->name);
+ g_free(server->uri);
+
+ G_OBJECT_CLASS (server_parent_class)->finalize (object);
+ return;
+}
+
+/**
+ * server_new_from_keyfile:
+ * @keyfile: The keyfile with the @group in it to define the server
+ * @group: Group name for this server
+ *
+ * Looks at a group within the keyfile and builds a server based on
+ * it's type. Mostly works with a subclass based on the type.
+ *
+ * Return value: A new Server object or NULL if error
+ */
+Server *
+server_new_from_keyfile (GKeyFile * keyfile, const gchar * group)
+{
+ g_return_val_if_fail(keyfile != NULL, NULL);
+ g_return_val_if_fail(group != NULL, NULL);
+
+ if (!g_key_file_has_group(keyfile, group)) {
+ return NULL;
+ }
+
+ gchar * type = NULL;
+ if (g_key_file_has_key(keyfile, group, CONFIG_SERVER_TYPE, NULL)) {
+ type = g_key_file_get_string(keyfile, group, CONFIG_SERVER_TYPE, NULL);
+ }
+
+ if (g_strcmp0(type, CONFIG_SERVER_TYPE_RDP) == 0) {
+ return SERVER(rdp_server_new_from_keyfile(keyfile, group));
+ } else if (g_strcmp0(type, CONFIG_SERVER_TYPE_ICA) == 0) {
+ return SERVER(citrix_server_new_from_keyfile(keyfile, group));
+ } else {
+ return SERVER(uccs_server_new_from_keyfile(keyfile, group));
+ }
+
+ return NULL;
+}
+
+/**
+ * server_new_from_json:
+ * @object: JSON object with server definition
+ *
+ * Looks at the type and then uses a subclassed function to build the
+ * server.
+ *
+ * Return value: A new Server object or NULL if error
+ */
+Server *
+server_new_from_json (JsonObject * object)
+{
+ g_return_val_if_fail(object != NULL, NULL);
+
+ if (!json_object_has_member(object, "Protocol")) {
+ return NULL;
+ }
+
+ JsonNode * proto_node = json_object_get_member(object, "Protocol");
+ if (JSON_NODE_TYPE(proto_node) != JSON_NODE_VALUE) {
+ return NULL;
+ }
+ if (json_node_get_value_type(proto_node) != G_TYPE_STRING) {
+ return NULL;
+ }
+
+ const gchar * proto = json_node_get_string(proto_node);
+ Server * newserver = NULL;
+
+ if (g_strcmp0(proto, "ICA") == 0 || g_strcmp0(proto, "ica") == 0) {
+ newserver = citrix_server_new_from_json(object);
+ }
+ else if (g_strcmp0(proto, "freerdp") == 0 || g_strcmp0(proto, "rdp") == 0 || g_strcmp0(proto, "RDP") == 0 || g_strcmp0(proto, "FreeRDP") == 0) {
+ newserver = rdp_server_new_from_json(object);
+ }
+
+ return newserver;
+}
+
+GVariant *
+server_get_variant (Server * server)
+{
+ /* Okay, this doesn't do anything useful, but it will generate an error
+ which could be a good thing */
+ g_return_val_if_fail(IS_SERVER(server), NULL);
+
+ ServerClass * klass = SERVER_GET_CLASS(server);
+ if (klass->get_properties != NULL) {
+ GVariantBuilder tuple;
+ g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE);
+
+ if (IS_CITRIX_SERVER(server)) {
+ g_variant_builder_add_value(&tuple, g_variant_new_string("ica"));
+ } else if (IS_RDP_SERVER(server)) {
+ g_variant_builder_add_value(&tuple, g_variant_new_string("freerdp"));
+ } else if (IS_UCCS_SERVER(server)) {
+ g_variant_builder_add_value(&tuple, g_variant_new_string("uccs"));
+ } else {
+ g_assert_not_reached();
+ }
+
+ if (server->name != NULL) {
+ g_variant_builder_add_value(&tuple, g_variant_new_string(server->name));
+ } else {
+ g_warning("Server has no name");
+ g_variant_builder_add_value(&tuple, g_variant_new_string(""));
+ }
+
+ if (server->uri != NULL) {
+ g_variant_builder_add_value(&tuple, g_variant_new_string(server->uri));
+ } else {
+ g_warning("Server has no URI");
+ g_variant_builder_add_value(&tuple, g_variant_new_string(""));
+ }
+
+ g_variant_builder_add_value(&tuple, g_variant_new_boolean(server->last_used));
+
+ GVariant * props = klass->get_properties(server);
+ g_variant_builder_add_value(&tuple, props);
+
+ if (klass->get_applications != NULL) {
+ GVariant * array = klass->get_applications(server);
+ g_variant_builder_add_value(&tuple, array);
+ } else {
+ /* NULL array of applications */
+ g_variant_builder_add_value(&tuple, g_variant_new_array(G_VARIANT_TYPE("(si)"), NULL, 0));
+ }
+
+ return g_variant_builder_end(&tuple);
+ }
+
+ return NULL;
+}
+
+/**
+ * server_cached_domains:
+ * @server: Where should we find those domains?
+ *
+ * Gets a list of cached domains for a particular server, if this function
+ * isn't overriden, then a null array is returned.
+ */
+GVariant *
+server_cached_domains (Server * server)
+{
+ g_return_val_if_fail(IS_SERVER(server), NULL);
+
+ ServerClass * klass = SERVER_GET_CLASS(server);
+ if (klass->get_domains != NULL) {
+ return klass->get_domains(server);
+ }
+
+ return g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0);
+}
+
+/**
+ * server_find_uri:
+ * @server: Server to look in
+ * @uri: URI to search for
+ *
+ * Checks the URI of this server to see if it matches, and then look
+ * to see if subclasses have a way to match it another way.
+ */
+Server *
+server_find_uri (Server * server, const gchar * uri)
+{
+ g_return_val_if_fail(IS_SERVER(server), NULL);
+
+ if (g_strcmp0(server->uri, uri) == 0) {
+ return server;
+ }
+
+ ServerClass * klass = SERVER_GET_CLASS(server);
+
+ if (klass->find_uri != NULL) {
+ return klass->find_uri(server, uri);
+ }
+
+ return NULL;
+}
+
+/**
+ * server_set_last_used:
+ * @server: Server to look in
+ * @uri: URI to set as last used
+ *
+ * Checks the URI of this server to see if it matches, and then look
+ * to see if subclasses have a way to match it another way.
+ */
+void
+server_set_last_used_server (Server * server, const gchar * uri)
+{
+ g_return_if_fail(IS_SERVER(server));
+
+ if (g_strcmp0(server->uri, uri) == 0) {
+ server->last_used = TRUE;
+ } else {
+ ServerClass * klass = SERVER_GET_CLASS(server);
+
+ if (klass->set_last_used_server != NULL) {
+ klass->set_last_used_server(server, uri);
+ }
+ }
+}
diff --git a/src/server.h b/src/server.h
new file mode 100644
index 0000000..e9f214d
--- /dev/null
+++ b/src/server.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#ifndef __SERVER_H__
+#define __SERVER_H__
+
+#include <glib-object.h>
+#include <json-glib/json-glib.h>
+
+G_BEGIN_DECLS
+
+#define SERVER_TYPE (server_get_type ())
+#define SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SERVER_TYPE, Server))
+#define SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SERVER_TYPE, ServerClass))
+#define IS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SERVER_TYPE))
+#define IS_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SERVER_TYPE))
+#define SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), SERVER_TYPE, ServerClass))
+
+#define SERVER_SIGNAL_STATE_CHANGED "state-changed"
+
+typedef struct _Server Server;
+typedef struct _ServerClass ServerClass;
+typedef enum _ServerState ServerState;
+
+enum _ServerState {
+ SERVER_STATE_ALLGOOD,
+ SERVER_STATE_UNAVAILABLE
+};
+
+struct _ServerClass {
+ GObjectClass parent_class;
+ GVariant * (*get_properties) (Server * server);
+ GVariant * (*get_applications) (Server * server);
+ GVariant * (*get_domains) (Server * server);
+ Server * (*find_uri) (Server * server, const gchar * uri);
+ void (*set_last_used_server) (Server * server, const gchar * uri);
+
+ /* signals */
+ void (*state_changed) (Server * server, ServerState newstate, gpointer user_data);
+};
+
+struct _Server {
+ GObject parent;
+
+ gchar * name;
+ gchar * uri;
+ gboolean last_used;
+
+ ServerState state;
+};
+
+GType server_get_type (void);
+Server * server_new_from_keyfile (GKeyFile * keyfile, const gchar * group);
+Server * server_new_from_json (JsonObject * object);
+GVariant * server_get_variant (Server * server);
+GVariant * server_cached_domains (Server * server);
+Server * server_find_uri (Server * server, const gchar * uri);
+void server_set_last_used_server (Server * server, const gchar * uri);
+
+G_END_DECLS
+
+#endif
diff --git a/src/uccs-server.c b/src/uccs-server.c
new file mode 100644
index 0000000..c17cf38
--- /dev/null
+++ b/src/uccs-server.c
@@ -0,0 +1,949 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <glib/gi18n.h>
+
+#include <json-glib/json-glib.h>
+
+#include <gio/gunixinputstream.h>
+#include <gio/gunixoutputstream.h>
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "uccs-server.h"
+#include "defines.h"
+
+#include "rdp-server.h"
+#include "citrix-server.h"
+
+#include "crypt.h"
+
+static void uccs_server_class_init (UccsServerClass *klass);
+static void uccs_server_init (UccsServer *self);
+static void uccs_server_dispose (GObject *object);
+static void uccs_server_finalize (GObject *object);
+static GVariant * get_properties (Server * server);
+static void json_waiters_notify (UccsServer * server, gboolean unlocked);
+static GVariant * get_cached_domains (Server * server);
+static Server * find_uri (Server * server, const gchar * uri);
+static void set_last_used_server (Server * server, const gchar * uri);
+static void evaluate_state (UccsServer * server);
+static void nm_state_changed (NMClient *client, const GParamSpec *pspec, gpointer user_data);
+
+typedef struct _json_callback_t json_callback_t;
+struct _json_callback_t {
+ gchar * sender;
+ void (*callback) (UccsServer * server, gboolean unlocked, gpointer user_data);
+ gpointer userdata;
+};
+
+G_DEFINE_TYPE (UccsServer, uccs_server, SERVER_TYPE);
+
+/* Static global client so we don't keep reallocating them. We only need
+ one really */
+static NMClient * global_client = NULL;
+
+static void
+uccs_server_class_init (UccsServerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = uccs_server_dispose;
+ object_class->finalize = uccs_server_finalize;
+
+ ServerClass * server_class = SERVER_CLASS(klass);
+
+ server_class->get_properties = get_properties;
+ /* UCCS can't have applications */
+ server_class->get_applications = NULL;
+ server_class->get_domains = get_cached_domains;
+ server_class->find_uri = find_uri;
+ server_class->set_last_used_server = set_last_used_server;
+
+ return;
+}
+
+static void
+uccs_server_init (UccsServer *self)
+{
+ self->exec = g_find_program_in_path(UCCS_QUERY_TOOL);
+
+ self->username = NULL;
+ self->password = NULL;
+
+ self->lovers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
+ self->subservers = NULL;
+
+ self->json_waiters = NULL;
+ self->json_watch = 0;
+ self->json_pid = 0;
+
+ self->json_stream = NULL;
+ self->pass_stream = NULL;
+
+ self->min_network = NM_STATE_CONNECTED_GLOBAL;
+ self->last_network = NM_STATE_DISCONNECTED;
+ self->nm_client = NULL;
+ self->nm_signal = 0;
+
+ /* Start as unavailable */
+ self->parent.state = SERVER_STATE_UNAVAILABLE;
+
+ if (global_client == NULL) {
+ global_client = nm_client_new();
+
+ if (global_client != NULL) {
+ g_object_add_weak_pointer(G_OBJECT(global_client), (gpointer *)&global_client);
+ self->nm_client = global_client;
+ }
+ } else {
+ self->nm_client = g_object_ref(global_client);
+ }
+
+ if (self->nm_client != NULL) {
+ self->nm_signal = g_signal_connect(self->nm_client, "notify::" NM_CLIENT_STATE, G_CALLBACK(nm_state_changed), self);
+ }
+
+ self->verify_server = TRUE;
+ self->verified_server = FALSE;
+ self->session = NULL;
+
+ /* Need the soup session before the state changed */
+ self->session = soup_session_sync_new();
+
+ nm_state_changed(self->nm_client, NULL, self);
+ evaluate_state(self);
+
+ return;
+}
+
+/* Small function to try and figure out the state of the server and set the
+ status appropriately */
+static void
+evaluate_state (UccsServer * server)
+{
+ ServerState tempstate = SERVER_STATE_ALLGOOD;
+
+ if (server->exec == NULL) {
+ tempstate = SERVER_STATE_UNAVAILABLE;
+ }
+
+ if (server->last_network < server->min_network) {
+ tempstate = SERVER_STATE_UNAVAILABLE;
+ }
+
+ if (server->verify_server && !server->verified_server && server->min_network > NM_STATE_DISCONNECTED) {
+ tempstate = SERVER_STATE_UNAVAILABLE;
+ }
+
+ if (tempstate != server->parent.state) {
+ server->parent.state = tempstate;
+ g_signal_emit_by_name(server, SERVER_SIGNAL_STATE_CHANGED, server->parent.state);
+ }
+
+ return;
+}
+
+struct _hash_helper {
+ GVariant * params;
+ GDBusConnection * session;
+};
+
+/* GHashTable foreach item */
+static gboolean
+clear_hash_helper (gpointer key, gpointer value, gpointer user_data)
+{
+ struct _hash_helper * helper = (struct _hash_helper *)user_data;
+ GError * error = NULL;
+
+ g_dbus_connection_emit_signal(helper->session,
+ (const gchar *)key, /* dest */
+ "/com/canonical/RemoteLogin", /* object path */
+ "com.canonical.RemoteLogin", /* interface name */
+ "com.canonical.RemoteLogin.LoginChanged", /* signal name */
+ helper->params, /* params */
+ &error);
+
+ if (error != NULL) {
+ g_warning("Unable to signal UCCS server shutdown: %s", error->message);
+ g_error_free(error);
+ }
+
+ return TRUE;
+}
+
+/* Clear the hash table by going through it and signaling */
+static void
+clear_hash (UccsServer * server)
+{
+ if (g_hash_table_size(server->lovers) == 0) {
+ return;
+ }
+
+ g_return_if_fail(server->parent.uri != NULL);
+ g_return_if_fail(server->username != NULL);
+
+ GDBusConnection * session = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL); /* Shouldn't block, we should have it */
+ GVariant * param = g_variant_new("(ss)", server->parent.uri, server->username); /* params */
+ g_variant_ref_sink(param);
+
+ struct _hash_helper helper;
+ helper.params = param;
+ helper.session = session;
+
+ g_hash_table_foreach_remove(server->lovers, clear_hash_helper, &helper);
+
+ g_object_unref(session);
+ g_variant_unref(param);
+
+ return;
+}
+
+/* Clear the JSON task and waiters */
+static void
+clear_json (UccsServer * self)
+{
+ if (self->json_watch != 0) {
+ g_source_remove(self->json_watch);
+ self->json_watch = 0;
+ }
+
+ if (self->json_pid != 0) {
+ g_spawn_close_pid(self->json_pid);
+ self->json_pid = 0;
+ }
+
+ if (self->json_stream != NULL) {
+ g_input_stream_close(self->json_stream, NULL, NULL);
+ g_object_unref(self->json_stream);
+ self->json_stream = NULL;
+ }
+
+ if (self->pass_stream != NULL) {
+ g_output_stream_close(self->pass_stream, NULL, NULL);
+ g_object_unref(self->pass_stream);
+ self->pass_stream = NULL;
+ }
+
+ json_waiters_notify(self, FALSE);
+
+ return;
+}
+
+/* Clean up references */
+static void
+uccs_server_dispose (GObject *object)
+{
+ UccsServer * self = UCCS_SERVER(object);
+
+ g_clear_object(&self->session);
+
+ if (self->nm_signal != 0) {
+ g_signal_handler_disconnect(self->nm_client, self->nm_signal);
+ self->nm_signal = 0;
+ }
+
+ g_clear_object(&self->nm_client);
+
+ clear_json(self);
+
+ if (self->lovers != NULL) {
+ clear_hash(self);
+ }
+
+ g_list_free_full(self->subservers, g_object_unref);
+ self->subservers = NULL; /* Ironically the free function is the only GList
+ function that doesn't return a new pointer by itself */
+
+ G_OBJECT_CLASS (uccs_server_parent_class)->dispose (object);
+ return;
+}
+
+/* Clean up memory */
+static void
+uccs_server_finalize (GObject *object)
+{
+ UccsServer * self = UCCS_SERVER(object);
+
+ g_free(self->exec); self->exec = NULL;
+ g_free(self->username); self->username = NULL;
+ g_free(self->password); self->password = NULL;
+
+ if (self->lovers != NULL) {
+ g_hash_table_unref(self->lovers);
+ self->lovers = NULL;
+ }
+
+ G_OBJECT_CLASS (uccs_server_parent_class)->finalize (object);
+ return;
+}
+
+/* Callback from the message getting complete */
+static void
+verify_server_cb (SoupSession * session, SoupMessage * message, gpointer user_data)
+{
+ UccsServer * server = UCCS_SERVER(user_data);
+ guint statuscode = 404;
+
+ g_object_get(G_OBJECT(message), SOUP_MESSAGE_STATUS_CODE, &statuscode, NULL);
+ g_debug("Verification came back with status: %d", statuscode);
+
+ if (statuscode == 200) {
+ server->verified_server = TRUE;
+ } else {
+ server->verified_server = FALSE;
+ }
+
+ evaluate_state(server);
+
+ return;
+}
+
+/* Set up the process to verify the server */
+static void
+verify_server (UccsServer * server)
+{
+ g_return_if_fail(server->session != NULL);
+
+ if (server->parent.uri == NULL) {
+ return;
+ }
+
+ SoupMessage * message = soup_message_new("HEAD", server->parent.uri);
+ soup_session_queue_message(server->session, message, verify_server_cb, server);
+ g_debug("Getting HEAD from: %s", server->parent.uri);
+
+ return;
+}
+
+/* Callback for when the Network Manger state changes */
+static void
+nm_state_changed (NMClient *client, const GParamSpec *pspec, gpointer user_data)
+{
+ g_return_if_fail(IS_UCCS_SERVER(user_data));
+ UccsServer * server = UCCS_SERVER(user_data);
+
+ if (server->nm_client == NULL || !nm_client_get_manager_running(server->nm_client)) {
+ server->last_network = NM_STATE_DISCONNECTED;
+ } else {
+ server->last_network = nm_client_get_state(server->nm_client);
+ }
+
+ if (server->last_network == NM_STATE_DISCONNECTED) {
+ server->verified_server = FALSE;
+ soup_session_abort(server->session);
+ }
+
+ if (server->last_network == NM_STATE_CONNECTED_GLOBAL && server->verify_server && !server->verified_server) {
+ verify_server(server);
+ }
+
+ evaluate_state(server);
+
+ return;
+}
+
+/* Get the properties that can be sent by the greeter for this server */
+static GVariant *
+get_properties (Server * server)
+{
+ GVariantBuilder propbuilder;
+ g_variant_builder_init(&propbuilder, G_VARIANT_TYPE_ARRAY);
+
+ GVariantBuilder namebuilder;
+ g_variant_builder_init(&namebuilder, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_add_value(&namebuilder, g_variant_new_string("email"));
+ g_variant_builder_add_value(&namebuilder, g_variant_new_boolean(TRUE));
+ g_variant_builder_add_value(&namebuilder, g_variant_new_variant(g_variant_new_string("")));
+ g_variant_builder_add_value(&namebuilder, g_variant_parse(G_VARIANT_TYPE_VARDICT, "{}", NULL, NULL, NULL));
+ g_variant_builder_add_value(&propbuilder, g_variant_builder_end(&namebuilder));
+
+ GVariantBuilder passbuilder;
+ g_variant_builder_init(&passbuilder, G_VARIANT_TYPE_TUPLE);
+ g_variant_builder_add_value(&passbuilder, g_variant_new_string("password"));
+ g_variant_builder_add_value(&passbuilder, g_variant_new_boolean(TRUE));
+ g_variant_builder_add_value(&passbuilder, g_variant_new_variant(g_variant_new_string("")));
+ g_variant_builder_add_value(&passbuilder, g_variant_parse(G_VARIANT_TYPE_VARDICT, "{}", NULL, NULL, NULL));
+ g_variant_builder_add_value(&propbuilder, g_variant_builder_end(&passbuilder));
+
+ return g_variant_builder_end(&propbuilder);
+}
+
+/* Set the exec value for the server */
+const gchar *
+uccs_server_set_exec (UccsServer * server, const gchar * exec)
+{
+ g_return_val_if_fail(IS_UCCS_SERVER(server), NULL);
+
+ g_clear_pointer(&server->exec, g_free);
+
+ if (exec != NULL) {
+ server->exec = g_find_program_in_path(exec);
+ }
+
+ evaluate_state(server);
+
+ return server->exec;
+}
+
+/* Build a new uccs server from a keyfile and a group in it */
+Server *
+uccs_server_new_from_keyfile (GKeyFile * keyfile, const gchar * groupname)
+{
+ g_return_val_if_fail(keyfile != NULL, NULL); /* NOTE: No way to check if that's really a keyfile :-( */
+ g_return_val_if_fail(groupname != NULL, NULL);
+
+ if (!g_key_file_has_group(keyfile, groupname)) {
+ g_warning("Server specified but group '%s' was not found", groupname);
+ return NULL;
+ }
+
+ UccsServer * server = g_object_new(UCCS_SERVER_TYPE, NULL);
+
+ if (g_key_file_has_key(keyfile, groupname, CONFIG_SERVER_NAME, NULL)) {
+ gchar * keyname = g_key_file_get_string(keyfile, groupname, CONFIG_SERVER_NAME, NULL);
+ server->parent.name = g_strdup(_(keyname));
+ g_free(keyname);
+ }
+
+ if (g_key_file_has_key(keyfile, groupname, CONFIG_SERVER_URI, NULL)) {
+ server->parent.uri = g_key_file_get_string(keyfile, groupname, CONFIG_SERVER_URI, NULL);
+ }
+
+ if (g_key_file_has_key(keyfile, groupname, CONFIG_UCCS_EXEC, NULL)) {
+ gchar * key = g_key_file_get_string(keyfile, groupname, CONFIG_UCCS_EXEC, NULL);
+ uccs_server_set_exec(server, key);
+ g_free(key);
+ }
+
+ if (g_key_file_has_key(keyfile, groupname, CONFIG_UCCS_NETWORK, NULL)) {
+ gchar * key = g_key_file_get_string(keyfile, groupname, CONFIG_UCCS_NETWORK, NULL);
+
+ if (g_strcmp0(key, CONFIG_UCCS_NETWORK_NONE) == 0) {
+ server->min_network = NM_STATE_DISCONNECTED;
+ } else if (g_strcmp0(key, CONFIG_UCCS_NETWORK_GLOBAL) == 0) {
+ server->min_network = NM_STATE_CONNECTED_GLOBAL;
+ }
+ /* NOTE: There is a possibility for other network types to be added here,
+ but they can be tricky to test. Feel free to patch it, but please include
+ those tests :-) */
+
+ g_free(key);
+ }
+
+ if (g_key_file_has_key(keyfile, groupname, CONFIG_UCCS_VERIFY, NULL)) {
+ server->verify_server = g_key_file_get_boolean(keyfile, groupname, CONFIG_UCCS_VERIFY, NULL);
+ }
+
+ evaluate_state(server);
+
+ return SERVER(server);
+}
+
+/* Look at the array of RLS data and build a server for each entry
+ in the array */
+static gboolean
+parse_rds_array (UccsServer * server, JsonArray * array)
+{
+ int i;
+ for (i = 0; i < json_array_get_length(array); i++) {
+ JsonNode * node = json_array_get_element(array, i);
+
+ if (JSON_NODE_TYPE(node) != JSON_NODE_OBJECT) {
+ continue;
+ }
+
+ JsonObject * object = json_node_get_object(node);
+ Server * newserver = server_new_from_json(object);
+ if (newserver != NULL) {
+ server->subservers = g_list_append(server->subservers, newserver);
+ }
+ }
+
+ return TRUE;
+}
+
+/* Parse the JSON content and allocate servers based on that */
+static gboolean
+parse_json (UccsServer * server, GInputStream * json)
+{
+ if (json == NULL) return FALSE; /* Shouldn't happen, but let's just handle it */
+
+ gboolean passed = TRUE;
+ JsonParser * parser = json_parser_new();
+ GError * error = NULL;
+
+ if (!json_parser_load_from_stream(parser, json, NULL, &error)) {
+ g_warning("Unable to parse JSON data: %s", error->message);
+ g_error_free(error);
+ error = NULL;
+ passed = FALSE;
+ }
+
+ /* Make sure we have a sane root node */
+ JsonNode * root_node = NULL;
+ if (passed) {
+ root_node = json_parser_get_root(parser);
+
+#if 0
+ JsonGenerator * gen = json_generator_new();
+ json_generator_set_root(gen, root_node);
+ gchar * data = json_generator_to_data(gen, NULL);
+ g_debug("%s", data);
+ g_free(data);
+ g_object_unref(G_OBJECT(gen));
+#endif
+ }
+ if (root_node != NULL && JSON_NODE_TYPE(root_node) != JSON_NODE_OBJECT) {
+ g_warning("Root node of JSON data is not an object. It is: %s", json_node_type_name(root_node));
+ passed = FALSE;
+ }
+
+ /* Take our object and see if it has the property that we need */
+ JsonObject * root_object = NULL;
+ if (passed) {
+ root_object = json_node_get_object(root_node);
+ }
+ if (root_object != NULL && json_object_has_member(root_object, "RemoteDesktopServers")) {
+ /* This shows that we have some. It's okay if there aren't any. Seems
+ a bit silly, but we're not bitching too much. */
+ JsonNode * rds_node = json_object_get_member(root_object, "RemoteDesktopServers");
+ if (JSON_NODE_TYPE(rds_node) == JSON_NODE_ARRAY) {
+ JsonArray * rds_array = json_node_get_array(rds_node);
+ passed = parse_rds_array(server, rds_array);
+ } else {
+ /* Okay we're a little bit angrier about this one */
+ g_warning("Malformed 'RemoteDesktopServer' entry. Not an array but a: %s", json_node_type_name(rds_node));
+ passed = FALSE;
+ }
+
+ if (json_object_has_member(root_object, "DefaultServer")) {
+ JsonNode * ds_node = json_object_get_member(root_object, "DefaultServer");
+ if (JSON_NODE_TYPE(ds_node) == JSON_NODE_VALUE && json_node_get_value_type(ds_node) == G_TYPE_STRING) {
+ const gchar * default_server_name = json_node_get_string(ds_node);
+ if (default_server_name != NULL) {
+ GList * lserver;
+ for (lserver = server->subservers; lserver != NULL; lserver = g_list_next(lserver)) {
+ Server * serv = SERVER(lserver->data);
+
+ if (g_strcmp0(serv->name, default_server_name) == 0) {
+ serv->last_used = TRUE;
+ break;
+ }
+ }
+ if (lserver == NULL && strlen(default_server_name) > 0) {
+ g_warning("Could not find the 'DefaultServer' server.");
+ passed = FALSE;
+ }
+ }
+ } else {
+ g_warning("Malformed 'DefaultServer' entry. Not a string value");
+ passed = FALSE;
+ }
+ }
+ } else {
+ g_debug("No 'RemoteDesktopServers' found");
+ }
+
+ g_object_unref(parser);
+ return passed;
+}
+
+/* Go through the waiters and notify them of the status */
+static void
+json_waiters_notify (UccsServer * server, gboolean unlocked)
+{
+ /* NOTE: Taking the list as the call back might add themselves to
+ the list so we don't want to have it corrupted in the middle of
+ the execution of this function */
+ GList * waiters = server->json_waiters;
+ server->json_waiters = NULL;
+
+ while (waiters != NULL) {
+ json_callback_t * json_callback = (json_callback_t *)waiters->data;
+
+ if (unlocked) {
+ g_hash_table_insert(server->lovers, g_strdup(json_callback->sender), GINT_TO_POINTER(TRUE));
+ }
+
+ if (json_callback->callback != NULL) {
+ json_callback->callback(server, unlocked, json_callback->userdata);
+ }
+
+ g_free(json_callback->sender);
+ g_free(json_callback);
+ waiters = g_list_delete_link(waiters, waiters);
+ }
+
+ return;
+}
+
+/* Callback from when we know that we've got all the JSON we're
+ gonna get */
+static void
+json_grab_cb (GPid pid, gint status, gpointer user_data)
+{
+ UccsServer * server = UCCS_SERVER(user_data);
+
+ server->json_pid = 0;
+ server->json_watch = 0;
+
+ if (status == 0) {
+ gboolean parser = parse_json(server, server->json_stream);
+
+ json_waiters_notify(server, parser);
+ } else {
+ g_free(server->username);
+ server->username = NULL;
+ g_free(server->password);
+ server->password = NULL;
+
+ json_waiters_notify(server, FALSE);
+ }
+
+ /* Drop the Streams -- NOTE: DO NOT CROSS THE STREAMS */
+ g_output_stream_close(server->pass_stream, NULL, NULL);
+ g_object_unref(server->pass_stream);
+ server->pass_stream = NULL;
+
+ g_input_stream_close(server->json_stream, NULL, NULL);
+ g_object_unref(server->json_stream);
+ server->json_stream = NULL;
+
+ g_spawn_close_pid(pid);
+
+ return;
+}
+
+/* This is the callback for writing the password, it mostly exists
+ to free the buffer, but we'll print some info as well just because
+ we can */
+static void
+password_write_cb (GObject * src_obj, GAsyncResult * res, gpointer user_data)
+{
+ /* Kill the buffer */
+ g_free(user_data);
+
+ GError * error = NULL;
+ g_output_stream_write_finish(G_OUTPUT_STREAM(src_obj), res, &error);
+
+ if (error != NULL) {
+ g_warning("Unable to write password to UCCS process: %s", error->message);
+ g_error_free(error);
+ } else {
+ g_debug("Wrote password to UCCS process");
+ g_output_stream_close(G_OUTPUT_STREAM(src_obj), NULL, NULL);
+ }
+
+ return;
+}
+
+/**
+ * uccs_server_unlock:
+ * @server: The server to unlock
+ * @address: DBus address of the person unlocking us
+ * @username: Username for the UCCS
+ * @password: (allow-none) Password to use
+ * @allowcache: If using cache is allowed
+ * @callback: Function to call when we have an answer
+ * @user_data: Data for the callback
+ *
+ * Unlocks the UCCS server making servers available either from the
+ * cache or from the network.
+ */
+void
+uccs_server_unlock (UccsServer * server, const gchar * address, const gchar * username, const gchar * password, gboolean allowcache, void (*callback) (UccsServer * server, gboolean unlocked, gpointer user_data), gpointer user_data)
+{
+ g_return_if_fail(IS_UCCS_SERVER(server));
+ g_return_if_fail(username != NULL);
+ g_return_if_fail(address != NULL);
+
+ /* Check the current values we have, they might be NULL, which in
+ that case they won't match */
+ if (allowcache && g_strcmp0(username, server->username) == 0 &&
+ g_strcmp0(password, server->password) == 0) {
+ g_hash_table_insert(server->lovers, g_strdup(address), GINT_TO_POINTER(TRUE));
+
+ if (callback != NULL) {
+ callback(server, TRUE, user_data);
+ }
+
+ return;
+ }
+
+ g_return_if_fail(server->exec != NULL); /* Shouldn't happen, but I'd feel safer if we checked */
+
+ /* If we're not going to allow the cache, just clear it right away */
+ if (!allowcache) {
+ clear_hash(server);
+ }
+
+ /* We're changing the username and password, if there were other
+ people who had it, they need to know we're different now */
+ if (g_strcmp0(username, server->username) != 0 ||
+ g_strcmp0(password, server->password) != 0) {
+ clear_hash(server);
+ clear_json(server);
+
+ g_clear_pointer(&server->username, g_free);
+ g_clear_pointer(&server->password, g_free);
+
+ server->username = g_strdup(username);
+ server->password = g_strdup(password);
+ }
+
+ /* Add ourselves to the queue */
+ json_callback_t * json_callback = g_new0(json_callback_t, 1);
+ json_callback->sender = g_strdup(address);
+ json_callback->callback = callback;
+ json_callback->userdata = user_data;
+
+ server->json_waiters = g_list_append(server->json_waiters, json_callback);
+
+ if (server->json_pid == 0) {
+ gint std_in, std_out;
+ GError * error = NULL;
+
+ const gchar * argv[3];
+ argv[0] = server->exec;
+ argv[1] = server->username;
+ argv[2] = NULL;
+
+ g_spawn_async_with_pipes(NULL, /* pwd */
+ (gchar **)argv,
+ NULL, /* env */
+ G_SPAWN_DO_NOT_REAP_CHILD,
+ NULL, NULL, /* child setup */
+ &server->json_pid,
+ &std_in,
+ &std_out,
+ NULL, /* stderr */
+ &error); /* error */
+
+ if (error != NULL) {
+ g_warning("Unable to start UCCS process: %s", error->message);
+ g_error_free(error);
+ server->json_pid = 0; /* really shouldn't get changed, but since we're using it to detect if it's running, let's double check, eh? */
+ json_waiters_notify(server, FALSE);
+ } else {
+ /* Watch for when it's done */
+ server->json_watch = g_child_watch_add(server->json_pid, json_grab_cb, server);
+
+ /* Set up I/O streams */
+ server->json_stream = g_unix_input_stream_new(std_out, TRUE);
+ server->pass_stream = g_unix_output_stream_new(std_in, TRUE);
+
+ gchar * pass = g_strdup(server->password);
+ g_output_stream_write_async(server->pass_stream,
+ pass,
+ strlen(pass), /* number of bytes */
+ G_PRIORITY_DEFAULT, /* priority */
+ NULL, /* cancellable */
+ password_write_cb,
+ pass);
+ }
+ }
+
+ return;
+}
+
+/* A little quickie function to handle the null server array */
+inline static GVariant *
+null_server_array (void)
+{
+ return g_variant_new_array(G_VARIANT_TYPE("(sssba(sbva{sv})a(si))"),
+ NULL, 0);
+}
+
+/**
+ * uccs_server_get_servers:
+ * @server: Server to get our list from
+ * @address: Who's asking
+ *
+ * Will get a valid variant with servers. If the asker hasn't unlocked us
+ * then the list will always be empty.
+ *
+ * Return value: A variant array
+ */
+GVariant *
+uccs_server_get_servers (UccsServer * server, const gchar * address)
+{
+ g_return_val_if_fail(IS_UCCS_SERVER(server), null_server_array());
+ g_return_val_if_fail(address != NULL, null_server_array());
+
+ if (!GPOINTER_TO_INT(g_hash_table_lookup(server->lovers, address))) {
+ g_warning("Address '%s' is not authorized", address);
+ return null_server_array();
+ }
+
+ gchar *last_used_server_name = NULL;
+ if (server->username != NULL && server->password != NULL) {
+ gchar *username_sha = g_compute_checksum_for_string (G_CHECKSUM_SHA256, server->username, -1);
+ gchar *file_path = g_build_path ("/", g_get_user_cache_dir(), "remote-login-service", "cache", username_sha, NULL);
+ gchar *encryptedContents;
+ gsize encryptedContentsLength;
+ if (g_file_get_contents (file_path, &encryptedContents, &encryptedContentsLength, NULL)) {
+ gchar *file_contents = do_aes_decrypt(encryptedContents, server->password, encryptedContentsLength);
+ g_free (encryptedContents);
+ if (file_contents != NULL) {
+ GKeyFile * key_file = g_key_file_new();
+ if (g_key_file_load_from_data (key_file, file_contents, strlen (file_contents), G_KEY_FILE_NONE, NULL)) {
+ last_used_server_name = g_key_file_get_string (key_file, server->parent.name, "last_used", NULL);
+ }
+ g_key_file_free (key_file);
+ g_free (file_contents);
+ }
+ }
+ g_free (username_sha);
+ g_free (file_path);
+ }
+
+ GVariantBuilder array;
+ g_variant_builder_init(&array, G_VARIANT_TYPE_ARRAY);
+ GList * lserver;
+ gint servercnt = 0;
+
+ Server * last_used_server = NULL;
+ if (last_used_server_name != NULL) {
+ for (lserver = server->subservers; last_used_server == NULL && lserver != NULL; lserver = g_list_next(lserver)) {
+ Server * serv = SERVER(lserver->data);
+
+ /* We only want servers that are all good */
+ if (serv->state != SERVER_STATE_ALLGOOD) {
+ continue;
+ }
+ if (g_strcmp0(serv->name, last_used_server_name) == 0)
+ last_used_server = serv;
+ }
+ }
+ g_free (last_used_server_name);
+
+ for (lserver = server->subservers; lserver != NULL; lserver = g_list_next(lserver)) {
+ Server * serv = SERVER(lserver->data);
+
+ /* We only want servers that are all good */
+ if (serv->state != SERVER_STATE_ALLGOOD) {
+ continue;
+ }
+
+ if (last_used_server != NULL)
+ serv->last_used = last_used_server == serv;
+
+ servercnt++;
+ g_variant_builder_add_value(&array, server_get_variant(serv));
+ }
+
+ if (servercnt == 0) {
+ g_variant_builder_clear(&array);
+ return null_server_array();
+ }
+
+ return g_variant_builder_end(&array);
+}
+
+/* Returns the cached domains as an array. Not currently with any of
+ this cached currently, so it's a NULL array. */
+static GVariant *
+get_cached_domains (Server * server)
+{
+ g_return_val_if_fail(IS_UCCS_SERVER(server), NULL);
+ return g_variant_new_array(G_VARIANT_TYPE_STRING, NULL, 0);
+}
+
+/* Tail recursive function to look at a list entry and see
+ if that server matches a URI, or go down the list */
+static Server *
+find_uri_helper (GList * list, const gchar * uri)
+{
+ if (list == NULL) return NULL;
+
+ Server * inserver = SERVER(list->data);
+
+ if (inserver == NULL) {
+ return find_uri_helper(g_list_next(list), uri);
+ }
+
+ Server * outserver = server_find_uri(inserver, uri);
+
+ if (outserver != NULL) {
+ return outserver;
+ }
+
+ return find_uri_helper(g_list_next(list), uri);
+}
+
+/* Look through our subservers to see if any of them match this
+ URI either */
+static Server *
+find_uri (Server * server, const gchar * uri)
+{
+ g_return_val_if_fail(IS_UCCS_SERVER(server), NULL);
+ /* If it is this server that's handled by the super class */
+ return find_uri_helper(UCCS_SERVER(server)->subservers, uri);
+}
+
+/* Look through our subservers to see if any of them match this
+ URI and set as used */
+static void
+set_last_used_server (Server * server, const gchar * uri)
+{
+ Server * subserver = server_find_uri(server, uri);
+
+ if (subserver != NULL) {
+ subserver->last_used = TRUE;
+
+ /* Write to disk */
+ if (UCCS_SERVER(server)->username != NULL && UCCS_SERVER(server)->password) {
+ GKeyFile * key_file = g_key_file_new();
+ g_key_file_set_string (key_file, server->name, "last_used", subserver->name);
+ gsize data_length;
+ gchar *data = g_key_file_to_data (key_file, &data_length, NULL);
+ g_key_file_free (key_file);
+
+ size_t enc_data_length;
+ gchar *enc_data = do_aes_encrypt(data, UCCS_SERVER(server)->password, &enc_data_length);
+ g_free (data);
+
+ gchar *dir_path = g_build_path ("/", g_get_user_cache_dir(), "remote-login-service", "cache", NULL);
+ gint status = g_mkdir_with_parents (dir_path, 0700);
+ if (status == 0)
+ {
+ gchar *username_sha = g_compute_checksum_for_string (G_CHECKSUM_SHA256, UCCS_SERVER(server)->username, -1);
+ gchar *path = g_build_path ("/", dir_path, username_sha, NULL);
+ gboolean success = g_file_set_contents (path, enc_data, enc_data_length, NULL);
+ if (!success) {
+ g_warning("Failing writting cache data to '%s'.", path);
+ }
+ g_free (username_sha);
+ g_free (path);
+ }
+ else
+ {
+ g_warning("Failed to create '%s'.", dir_path);
+ }
+ g_free (enc_data);
+ g_free (dir_path);
+ }
+ }
+}
diff --git a/src/uccs-server.h b/src/uccs-server.h
new file mode 100644
index 0000000..3171c96
--- /dev/null
+++ b/src/uccs-server.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2012 Canonical Ltd.
+ *
+ * This program is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 3, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranties of
+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Author: Ted Gould <ted@canonical.com>
+ */
+
+#ifndef __UCCS_SERVER_H__
+#define __UCCS_SERVER_H__
+
+#include <glib-object.h>
+#include <libnm-glib/nm-client.h>
+#include <libsoup/soup.h>
+#include "server.h"
+
+G_BEGIN_DECLS
+
+#define UCCS_SERVER_TYPE (uccs_server_get_type ())
+#define UCCS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), UCCS_SERVER_TYPE, UccsServer))
+#define UCCS_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), UCCS_SERVER_TYPE, UccsServerClass))
+#define IS_UCCS_SERVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), UCCS_SERVER_TYPE))
+#define IS_UCCS_SERVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), UCCS_SERVER_TYPE))
+#define UCCS_SERVER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), UCCS_SERVER_TYPE, UccsServerClass))
+
+typedef struct _UccsServer UccsServer;
+typedef struct _UccsServerClass UccsServerClass;
+
+struct _UccsServerClass {
+ ServerClass parent_class;
+};
+
+struct _UccsServer {
+ Server parent;
+
+ gchar * exec;
+
+ gchar * username;
+ gchar * password;
+
+ GHashTable * lovers;
+
+ GList * subservers;
+
+ GList * json_waiters;
+ guint json_watch;
+ GPid json_pid;
+
+ GInputStream * json_stream;
+ GOutputStream * pass_stream;
+
+ NMState min_network;
+ NMState last_network;
+ NMClient * nm_client;
+ gulong nm_signal;
+
+ gboolean verify_server;
+ gboolean verified_server;
+ SoupSession * session;
+};
+
+GType uccs_server_get_type (void);
+Server * uccs_server_new_from_keyfile (GKeyFile * keyfile, const gchar * name);
+void uccs_server_unlock (UccsServer * server, const gchar * address, const gchar * username, const gchar * password, gboolean allowcache, void (*callback) (UccsServer * server, gboolean unlocked, gpointer user_data), gpointer user_data);
+GVariant * uccs_server_get_servers (UccsServer * server, const gchar * address);
+const gchar *uccs_server_set_exec (UccsServer * server, const gchar * exec);
+
+G_END_DECLS
+
+#endif