diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 69 | ||||
-rw-r--r-- | src/Makefile.in | 775 | ||||
-rw-r--r-- | src/citrix-server.c | 225 | ||||
-rw-r--r-- | src/citrix-server.h | 57 | ||||
-rw-r--r-- | src/com.canonical.RemoteLogin.xml | 81 | ||||
-rw-r--r-- | src/crypt.c | 153 | ||||
-rw-r--r-- | src/crypt.h | 24 | ||||
-rw-r--r-- | src/defines.h | 47 | ||||
-rw-r--r-- | src/main.c | 453 | ||||
-rw-r--r-- | src/rdp-server.c | 225 | ||||
-rw-r--r-- | src/rdp-server.h | 57 | ||||
-rw-r--r-- | src/remote-login.c | 2244 | ||||
-rw-r--r-- | src/remote-login.h | 344 | ||||
-rw-r--r-- | src/server.c | 292 | ||||
-rw-r--r-- | src/server.h | 77 | ||||
-rw-r--r-- | src/uccs-server.c | 949 | ||||
-rw-r--r-- | src/uccs-server.h | 80 |
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 (¶mv[0], TYPE_REMOTE_LOGIN); + g_value_set_object (¶mv[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 (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[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 (¶mv[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 (¶mv[n], TYPE_REMOTE_LOGIN); + g_value_set_object (¶mv[n++], skeleton); + g_value_init (¶mv[n], G_TYPE_DBUS_METHOD_INVOCATION); + g_value_set_object (¶mv[n++], invocation); + if (info->pass_fdlist) + { +#ifdef G_OS_UNIX + g_value_init (¶mv[n], G_TYPE_UNIX_FD_LIST); + g_value_set_object (¶mv[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 (¶mv[n], G_TYPE_VARIANT); + g_value_set_variant (¶mv[n], child); + n++; + } + else + g_dbus_gvariant_to_gvalue (child, ¶mv[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 (¶mv[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 |